[project @ 1997-05-26 20:49:19 by andre]
[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 #define ZdZh(r,a,b)             r=ULTRASAFESTGCALL2(I_,(void *, I_, I_),stg_div,(a),(b))
458 #define remIntZh(r,a,b)         r=(a)%(b)
459 #define negateIntZh(r,a)        r=-(a)
460 /* Ever used ? -- SOF */
461 #define absIntZh(a)             r=(( (a) >= 0 ) ? (a) : (-(a)))
462 \end{code}
463
464 %************************************************************************
465 %*                                                                      *
466 \subsubsection[StgMacros-word-primops]{Primitive @Word#@ ops}
467 %*                                                                      *
468 %************************************************************************
469
470 \begin{code}
471 #define andZh(r,a,b)    r=(a)&(b)
472 #define orZh(r,a,b)     r=(a)|(b)
473 #define notZh(r,a)      r=~(a)
474
475 #define shiftLZh(r,a,b)   r=(a)<<(b)
476 #define shiftRAZh(r,a,b)  r=(a)>>(b)
477 #define shiftRLZh(r,a,b)  r=(a)>>(b)
478 #define iShiftLZh(r,a,b)  r=(a)<<(b)
479 #define iShiftRAZh(r,a,b) r=(a)>>(b)
480 #define iShiftRLZh(r,a,b) r=(a)>>(b)
481
482 #define int2WordZh(r,a) r=(W_)(a)
483 #define word2IntZh(r,a) r=(I_)(a)
484 \end{code}
485
486 %************************************************************************
487 %*                                                                      *
488 \subsubsection[StgMacros-addr-primops]{Primitive @Addr#@ ops}
489 %*                                                                      *
490 %************************************************************************
491
492 \begin{code}
493 #define int2AddrZh(r,a) r=(A_)(a)
494 #define addr2IntZh(r,a) r=(I_)(a)
495 \end{code}
496
497 %************************************************************************
498 %*                                                                      *
499 \subsubsection[StgMacros-float-primops]{Primitive @Float#@ ops}
500 %*                                                                      *
501 %************************************************************************
502
503 \begin{code}
504 #define plusFloatZh(r,a,b)      r=(a)+(b)
505 #define minusFloatZh(r,a,b)     r=(a)-(b)
506 #define timesFloatZh(r,a,b)     r=(a)*(b)
507 #define divideFloatZh(r,a,b)    r=(a)/(b)
508 #define negateFloatZh(r,a)      r=-(a)
509
510 #define int2FloatZh(r,a)        r=(StgFloat)(a)
511 #define float2IntZh(r,a)        r=(I_)(a)
512
513 #define expFloatZh(r,a)         r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),exp,a)
514 #define logFloatZh(r,a)         r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),log,a)
515 #define sqrtFloatZh(r,a)        r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),sqrt,a)
516 #define sinFloatZh(r,a)         r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),sin,a)
517 #define cosFloatZh(r,a)         r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),cos,a)
518 #define tanFloatZh(r,a)         r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),tan,a)
519 #define asinFloatZh(r,a)        r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),asin,a)
520 #define acosFloatZh(r,a)        r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),acos,a)
521 #define atanFloatZh(r,a)        r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),atan,a)
522 #define sinhFloatZh(r,a)        r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),sinh,a)
523 #define coshFloatZh(r,a)        r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),cosh,a)
524 #define tanhFloatZh(r,a)        r=(StgFloat) SAFESTGCALL1(StgDouble,(void *, StgDouble),tanh,a)
525 #define powerFloatZh(r,a,b)     r=(StgFloat) SAFESTGCALL2(StgDouble,(void *, StgDouble,StgDouble),pow,a,b)
526
527 /* encoding/decoding given w/ Integer stuff */
528 \end{code}
529
530 %************************************************************************
531 %*                                                                      *
532 \subsubsection[StgMacros-double-primops]{Primitive @Double#@ ops}
533 %*                                                                      *
534 %************************************************************************
535
536 \begin{code}
537 #define ZpZhZh(r,a,b)           r=(a)+(b)
538 #define ZmZhZh(r,a,b)           r=(a)-(b)
539 #define ZtZhZh(r,a,b)           r=(a)*(b)
540 #define ZdZhZh(r,a,b)           r=(a)/(b)
541 #define negateDoubleZh(r,a)     r=-(a)
542
543 #define int2DoubleZh(r,a)       r=(StgDouble)(a)
544 #define double2IntZh(r,a)       r=(I_)(a)
545
546 #define float2DoubleZh(r,a)     r=(StgDouble)(a)
547 #define double2FloatZh(r,a)     r=(StgFloat)(a)
548
549 #define expDoubleZh(r,a)        r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),exp,a)
550 #define logDoubleZh(r,a)        r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),log,a)
551 #define sqrtDoubleZh(r,a)       r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),sqrt,a)
552 #define sinDoubleZh(r,a)        r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),sin,a)
553 #define cosDoubleZh(r,a)        r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),cos,a)
554 #define tanDoubleZh(r,a)        r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),tan,a)
555 #define asinDoubleZh(r,a)       r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),asin,a)
556 #define acosDoubleZh(r,a)       r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),acos,a)
557 #define atanDoubleZh(r,a)       r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),atan,a)
558 #define sinhDoubleZh(r,a)       r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),sinh,a)
559 #define coshDoubleZh(r,a)       r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),cosh,a)
560 #define tanhDoubleZh(r,a)       r=(StgDouble) SAFESTGCALL1(StgDouble,(void *, StgDouble),tanh,a)
561 /* Power: **## */
562 #define ZtZtZhZh(r,a,b) r=(StgDouble) SAFESTGCALL2(StgDouble,(void *, StgDouble,StgDouble),pow,a,b)
563 \end{code}
564
565 %************************************************************************
566 %*                                                                      *
567 \subsubsection[StgMacros-integer-primops]{Primitive @Integer@-related ops (GMP stuff)}
568 %*                                                                      *
569 %************************************************************************
570
571 Dirty macros we use for the real business.
572
573 INVARIANT: When one of these macros is called, the only live data is
574 tidily on the STG stacks or in the STG registers (the code generator
575 ensures this).  If there are any pointer-arguments, they will be in
576 the first \tr{Ret*} registers (e.g., \tr{da} arg of \tr{gmpTake1Return1}).
577
578 OK, here are the real macros:
579 \begin{code}
580 #define gmpTake1Return1(size_chk_macro, liveness, mpz_op, ar,sr,dr, aa,sa,da)   \
581 { MP_INT arg;                                                                   \
582   MP_INT result;                                                                \
583   I_ space = size_chk_macro(sa);                                                \
584                                                                                 \
585   /* Check that there will be enough heap & make Hp visible to GMP allocator */ \
586   GMP_HEAP_LOOKAHEAD(liveness,space);                                           \
587                                                                                 \
588   /* Now we can initialise (post possible GC) */                                \
589   arg.alloc     = (aa);                                                         \
590   arg.size      = (sa);                                                         \
591   arg.d         = (unsigned long int *) (BYTE_ARR_CTS(da));                     \
592                                                                                 \
593   SAFESTGCALL1(void,(void *, MP_INT *),mpz_init,&result);                       \
594                                                                                 \
595   /* Perform the operation */                                                   \
596   SAFESTGCALL2(void,(void *, MP_INT *, MP_INT *),mpz_op,&result,&arg);          \
597                                                                                 \
598   GMP_HEAP_HANDBACK();          /* restore Hp */                                \
599   (ar) = result.alloc;                                                          \
600   (sr) = result.size;                                                           \
601   (dr) = (B_) (result.d - DATA_HS);                                             \
602   /* pt to *beginning* of object (GMP has been monkeying around in the middle) */ \
603 }
604
605
606 #define gmpTake2Return1(size_chk_macro, liveness, mpz_op, ar,sr,dr, a1,s1,d1, a2,s2,d2)\
607 { MP_INT arg1;                                                                  \
608   MP_INT arg2;                                                                  \
609   MP_INT result;                                                                \
610   I_ space = size_chk_macro(s1,s2);                                             \
611                                                                                 \
612   /* Check that there will be enough heap & make Hp visible to GMP allocator */ \
613   GMP_HEAP_LOOKAHEAD(liveness,space);                                           \
614                                                                                 \
615   /* Now we can initialise (post possible GC) */                                \
616   arg1.alloc    = (a1);                                                         \
617   arg1.size     = (s1);                                                         \
618   arg1.d        = (unsigned long int *) (BYTE_ARR_CTS(d1));                     \
619   arg2.alloc    = (a2);                                                         \
620   arg2.size     = (s2);                                                         \
621   arg2.d        = (unsigned long int *) (BYTE_ARR_CTS(d2));                     \
622                                                                                 \
623   SAFESTGCALL1(void,(void *, MP_INT *),mpz_init,&result);                       \
624                                                                                 \
625   /* Perform the operation */                                                   \
626   SAFESTGCALL3(void,(void *, MP_INT *, MP_INT *, MP_INT *),mpz_op,&result,&arg1,&arg2); \
627                                                                                 \
628   GMP_HEAP_HANDBACK();          /* restore Hp */                                \
629   (ar) = result.alloc;                                                          \
630   (sr) = result.size;                                                           \
631   (dr) = (B_) (result.d - DATA_HS);                                             \
632   /* pt to *beginning* of object (GMP has been monkeying around in the middle) */ \
633 }
634
635 #define gmpTake2Return2(size_chk_macro, liveness, mpz_op, ar1,sr1,dr1, ar2,sr2,dr2, a1,s1,d1, a2,s2,d2) \
636 { MP_INT arg1;                                                                  \
637   MP_INT arg2;                                                                  \
638   MP_INT result1;                                                               \
639   MP_INT result2;                                                               \
640   I_ space = size_chk_macro(s1,s2);                                             \
641                                                                                 \
642   /* Check that there will be enough heap & make Hp visible to GMP allocator */ \
643   GMP_HEAP_LOOKAHEAD(liveness,space);                                           \
644                                                                                 \
645   /* Now we can initialise (post possible GC) */                                \
646   arg1.alloc    = (a1);                                                         \
647   arg1.size     = (s1);                                                         \
648   arg1.d        = (unsigned long int *) (BYTE_ARR_CTS(d1));                     \
649   arg2.alloc    = (a2);                                                         \
650   arg2.size     = (s2);                                                         \
651   arg2.d        = (unsigned long int *) (BYTE_ARR_CTS(d2));                     \
652                                                                                 \
653   SAFESTGCALL1(void,(void *, MP_INT *),mpz_init,&result1);                      \
654   SAFESTGCALL1(void,(void *, MP_INT *),mpz_init,&result2);                      \
655                                                                                 \
656   /* Perform the operation */                                                   \
657   SAFESTGCALL4(void,(void *, MP_INT *, MP_INT *, MP_INT *, MP_INT *),mpz_op,&result1,&result2,&arg1,&arg2); \
658                                                                                 \
659   GMP_HEAP_HANDBACK();          /* restore Hp */                                \
660   (ar1) = result1.alloc;                                                        \
661   (sr1) = result1.size;                                                         \
662   (dr1) = (B_) (result1.d - DATA_HS);                                           \
663   (ar2) = result2.alloc;                                                        \
664   (sr2) = result2.size;                                                         \
665   (dr2) = (B_) (result2.d - DATA_HS);                                           \
666 }
667 \end{code}
668
669 Some handy size-munging macros: sometimes gratuitously {\em conservative}.
670 The \tr{+16} is to allow for the initial allocation of \tr{MP_INT} results.
671 The \tr{__abs} stuff is because negative-ness of GMP things is encoded
672 in their ``size''...
673 \begin{code}
674 #define __abs(a)                (( (a) >= 0 ) ? (a) : (-(a)))
675 #define GMP_SIZE_ONE()          (2 + DATA_HS + 16)
676 #define GMP_SAME_SIZE(a)        (__abs(a) + DATA_HS + 16)
677 #define GMP_MAX_SIZE(a,b)       ((__abs(a) > __abs(b) ? __abs(a) : __abs(b)) + 1 + DATA_HS + 16)
678                                 /* NB: the +1 is for the carry (or whatever) */
679 #define GMP_2MAX_SIZE(a,b)      (2 * GMP_MAX_SIZE(a,b))
680 #define GMP_ADD_SIZES(a,b)      (__abs(a) + __abs(b) + 1 + DATA_HS + 16)
681                                 /* the +1 may just be paranoia */
682 \end{code}
683
684 For the Integer/GMP stuff, we have macros that {\em look ahead} for
685 some space, but don't actually grab it.
686
687 If there are live pointers at the time of the lookahead, the caller
688 must make sure they are in \tr{Ret1}, \tr{Ret2}, ..., so they can be
689 handled normally.  We achieve this by having the code generator {\em
690 always} pass args to may-invoke-GC primitives in registers, using the
691 normal pointers-first policy.  This means that, if we do go to garbage
692 collection, everything is already in the Right Place.
693
694 Saving and restoring Hp register so the MP allocator can see them. If we are
695 performing liftime profiling need to save and restore HpLim as well so that
696 it can be bumped if allocation occurs.
697
698 The second argument to @GMP_HEAP_LOOKAHEAD@ must be an lvalue so that
699 it can be restored from @TSO_ARG1@ after a failed @HEAP_CHK@ in
700 threaded land.
701
702 \begin{code}
703 #define GMP_HEAP_LOOKAHEAD(liveness,n)                  \
704         do {                                            \
705         HEAP_CHK_AND_RESTORE_N(liveness,n,0);           \
706         Hp = Hp - (n);                                  \
707         UN_ALLOC_HEAP(n);       /* Undo ticky-ticky */  \
708         SAVE_Hp = Hp;           /* Hand over the hp */  \
709         DEBUG_SetGMPAllocBudget(n)                      \
710         }while(0)
711
712 #define GMP_HEAP_HANDBACK()                             \
713         Hp = SAVE_Hp;                                   \
714         DEBUG_ResetGMPAllocBudget()
715 \end{code}
716
717 \begin{code}
718 void *stgAllocForGMP   PROTO((size_t size_in_bytes));
719 void *stgReallocForGMP PROTO((void *ptr, size_t old_size, size_t new_size));
720 void stgDeallocForGMP  PROTO((void *ptr, size_t size));
721
722 #ifdef ALLOC_DEBUG
723 extern StgInt DEBUG_GMPAllocBudget;
724 #define DEBUG_SetGMPAllocBudget(n)  DEBUG_GMPAllocBudget = (n);
725 #define DEBUG_ResetGMPAllocBudget() DEBUG_GMPAllocBudget = 0;
726 #else
727 #define DEBUG_SetGMPAllocBudget(n)  /*nothing*/
728 #define DEBUG_ResetGMPAllocBudget() /*nothing*/
729 #endif
730 \end{code}
731
732 The real business (defining Integer primops):
733 \begin{code}
734 #define negateIntegerZh(ar,sr,dr, liveness, aa,sa,da) \
735         gmpTake1Return1(GMP_SAME_SIZE, liveness, mpz_neg, ar,sr,dr, aa,sa,da)
736
737 #define plusIntegerZh(ar,sr,dr, liveness, a1,s1,d1, a2,s2,d2) \
738         gmpTake2Return1(GMP_MAX_SIZE, liveness, mpz_add, ar,sr,dr, a1,s1,d1, a2,s2,d2)
739 #define minusIntegerZh(ar,sr,dr, liveness, a1,s1,d1, a2,s2,d2) \
740         gmpTake2Return1(GMP_MAX_SIZE, liveness, mpz_sub, ar,sr,dr, a1,s1,d1, a2,s2,d2)
741 #define timesIntegerZh(ar,sr,dr, liveness, a1,s1,d1, a2,s2,d2) \
742         gmpTake2Return1(GMP_ADD_SIZES, liveness, mpz_mul, ar,sr,dr, a1,s1,d1, a2,s2,d2)
743
744 /* div, mod, quot, rem are defined w/ quotRem & divMod */
745
746 #define quotRemIntegerZh(ar1,sr1,dr1, ar2,sr2,dr2, liveness, a1,s1,d1, a2,s2,d2) \
747         gmpTake2Return2(GMP_2MAX_SIZE, liveness, mpz_divmod, ar1,sr1,dr1, ar2,sr2,dr2, a1,s1,d1, a2,s2,d2)
748 #define divModIntegerZh(ar1,sr1,dr1, ar2,sr2,dr2, liveness,  a1,s1,d1, a2,s2,d2) \
749         gmpTake2Return2(GMP_2MAX_SIZE, liveness, mpz_mdivmod, ar1,sr1,dr1, ar2,sr2,dr2, a1,s1,d1, a2,s2,d2)
750 \end{code}
751
752 Comparison ops (@<@, @>=@, etc.) are defined in terms of the cmp
753 fellow (returns -ve, 0, or +ve).
754 \begin{code}
755 #define cmpIntegerZh(r, hp, a1,s1,d1, a2,s2,d2) /* calls mpz_cmp */             \
756 { MP_INT arg1;                                                                  \
757   MP_INT arg2;                                                                  \
758   /* Does not allocate memory */                                                \
759                                                                                 \
760   arg1.alloc    = (a1);                                                         \
761   arg1.size     = (s1);                                                         \
762   arg1.d        = (unsigned long int *) (BYTE_ARR_CTS(d1));                     \
763   arg2.alloc    = (a2);                                                         \
764   arg2.size     = (s2);                                                         \
765   arg2.d        = (unsigned long int *) (BYTE_ARR_CTS(d2));                     \
766                                                                                 \
767   (r) = SAFESTGCALL2(I_,(void *, MP_INT *, MP_INT *),mpz_cmp,&arg1,&arg2);      \
768 }
769 \end{code}
770
771 Coercions:
772
773 \begin{code}
774 #define integer2IntZh(r, hp, aa,sa,da)                                          \
775 { MP_INT arg;                                                                   \
776   /* Does not allocate memory */                                                \
777                                                                                 \
778   arg.alloc     = (aa);                                                         \
779   arg.size      = (sa);                                                         \
780   arg.d         = (unsigned long int *) (BYTE_ARR_CTS(da));                     \
781                                                                                 \
782   (r) = SAFESTGCALL1(I_,(void *, MP_INT *),mpz_get_si,&arg);                    \
783 }
784
785 /* Since we're forced to know a little bit about MP_INT layout to do this with
786    pre-allocated heap, we just inline the whole of mpz_init_set_si here.
787         ** DIRE WARNING.  if mpz_init_set_si changes, so does this! ***
788 */
789
790 #define int2IntegerZh(ar,sr,dr, hp, i)                                          \
791 { StgInt val; /* to snaffle arg to avoid aliasing */                            \
792                                                                                 \
793   val = (i);  /* snaffle... */                                                  \
794                                                                                 \
795   SET_DATA_HDR((hp),ArrayOfData_info,CCC,DATA_VHS+MIN_MP_INT_SIZE,0);           \
796                                                                                 \
797   if      ((val) < 0) { (sr) = -1; (hp)[DATA_HS] = -(val); }                    \
798   else if ((val) > 0) { (sr) =  1; (hp)[DATA_HS] =  (val); }                    \
799   else /* val==0 */   { (sr) =  0; }                                            \
800   (ar) = 1;                                                                     \
801   (dr) = (B_)(hp);              /* dr is an StgByteArray */                     \
802 }
803
804 #define word2IntegerZh(ar,sr,dr, hp, i)                                         \
805 { StgWord val; /* to snaffle arg to avoid aliasing */                           \
806                                                                                 \
807   val = (i);  /* snaffle... */                                                  \
808                                                                                 \
809   SET_DATA_HDR((hp),ArrayOfData_info,CCC,DATA_VHS+MIN_MP_INT_SIZE,0);           \
810                                                                                 \
811   if ((val) != 0)     { (sr) =  1; (hp)[DATA_HS] =  (val); }                    \
812   else /* val==0 */   { (sr) =  0; }                                            \
813   (ar) = 1;                                                                     \
814   (dr) = (B_)(hp);              /* dr is an StgByteArray */                     \
815 }
816
817 \end{code}
818
819 Then there are a few oddments to make life easier:
820 \begin{code}
821 /*
822    DIRE WARNING.
823    The "str" argument must be a literal C string.
824
825         addr2Integer( ..., "foo")   OK!
826
827         x = "foo";
828         addr2Integer( ..., x)       NO! NO!
829 */
830
831 #define addr2IntegerZh(ar,sr,dr, liveness, str)                                 \
832 { MP_INT result;                                                                \
833   /* taking the number of bytes/8 as the number of words of lookahead           \
834      is plenty conservative */                                                  \
835   I_ space = GMP_SAME_SIZE(sizeof(str) / 8 + 1);                                \
836                                                                                 \
837   GMP_HEAP_LOOKAHEAD(liveness, space);                                          \
838                                                                                 \
839   /* Perform the operation */                                                   \
840   if (SAFESTGCALL3(I_,(void *, MP_INT *, char *, int), mpz_init_set_str,&result,(str),/*base*/10)) \
841       abort();                                                                  \
842                                                                                 \
843   GMP_HEAP_HANDBACK();          /* restore Hp */                                \
844   (ar) = result.alloc;                                                          \
845   (sr) = result.size;                                                           \
846   (dr) = (B_) (result.d - DATA_HS);                                             \
847   /* pt to *beginning* of object (GMP has been monkeying around in the middle) */ \
848 }
849 \end{code}
850
851 Encoding and decoding float-ish things is pretty Integer-ish.  We use
852 these pretty magical support functions, essentially stolen from Lennart:
853 \begin{code}
854 StgFloat  __encodeFloat  PROTO((MP_INT *, I_));
855 void      __decodeFloat  PROTO((MP_INT * /*result1*/,
856                                 I_ * /*result2*/,
857                                 StgFloat));
858
859 StgDouble __encodeDouble PROTO((MP_INT *, I_));
860 void      __decodeDouble PROTO((MP_INT * /*result1*/,
861                                 I_ * /*result2*/,
862                                 StgDouble));
863 \end{code}
864
865 Some floating-point format info, made with the \tr{enquire} program
866 (version~4.3) [comes with gcc].
867 \begin{code}
868 /* this should be done by CPU architecture, insofar as possible [WDP] */
869
870 #if sparc_TARGET_ARCH   \
871  || alpha_TARGET_ARCH   \
872  || hppa1_1_TARGET_ARCH \
873  || i386_TARGET_ARCH    \
874  || m68k_TARGET_ARCH    \
875  || mipsel_TARGET_ARCH  \
876  || mipseb_TARGET_ARCH  \
877  || powerpc_TARGET_ARCH \
878  || rs6000_TARGET_ARCH
879
880 /* yes, it is IEEE floating point */
881 #include "ieee-flpt.h"
882
883 #if alpha_dec_osf1_TARGET       \
884  || i386_TARGET_ARCH            \
885  || mipsel_TARGET_ARCH
886
887 #undef BIGENDIAN /* little-endian weirdos... */
888 #else
889 #define BIGENDIAN 1
890 #endif
891
892 #else /* unknown floating-point format */
893
894 ******* ERROR *********** Any ideas about floating-point format?
895
896 #endif /* unknown floating-point */
897 \end{code}
898
899 \begin{code}
900 #if alpha_dec_osf1_TARGET
901 #define encodeFloatZh(r, hp, aa,sa,da, expon)   encodeDoubleZh(r, hp, aa,sa,da, expon)
902 #else
903 #define encodeFloatZh(r, hp, aa,sa,da, expon)   \
904 { MP_INT arg;                                   \
905   /* Does not allocate memory */                \
906                                                 \
907   arg.alloc     = aa;                           \
908   arg.size      = sa;                           \
909   arg.d         = (unsigned long int *) (BYTE_ARR_CTS(da)); \
910                                                 \
911   r = SAFESTGCALL2(StgFloat,(void *, MP_INT *, I_), __encodeFloat,&arg,(expon));        \
912 }
913 #endif /* ! alpha */
914
915 #define encodeDoubleZh(r, hp, aa,sa,da, expon)  \
916 { MP_INT arg;                                   \
917   /* Does not allocate memory */                \
918                                                 \
919   arg.alloc     = aa;                           \
920   arg.size      = sa;                           \
921   arg.d         = (unsigned long int *) (BYTE_ARR_CTS(da)); \
922                                                 \
923   r = SAFESTGCALL2(StgDouble,(void *, MP_INT *, I_), __encodeDouble,&arg,(expon));\
924 }
925
926 #if alpha_dec_osf1_TARGET
927 #define decodeFloatZh(exponr, ar,sr,dr, hp, f)  decodeDoubleZh(exponr, ar,sr,dr, hp, f)
928 #else
929 #define decodeFloatZh(exponr, ar,sr,dr, hp, f)                          \
930 { MP_INT mantissa;                                                      \
931   I_ exponent;                                                          \
932   StgFloat arg = (f);                                                   \
933                                                                         \
934   /* Be prepared to tell Lennart-coded __decodeFloat    */              \
935   /* where mantissa.d can be put (it does not care about the rest) */   \
936   SET_DATA_HDR(hp,ArrayOfData_info,CCC,DATA_VHS+MIN_MP_INT_SIZE,0);     \
937   mantissa.d = (hp) + DATA_HS;                                          \
938                                                                         \
939   /* Perform the operation */                                           \
940   SAFESTGCALL3(void,(void *, MP_INT *, I_ *, StgFloat),__decodeFloat,&mantissa,&exponent,arg);          \
941   exponr= exponent;                                                     \
942   ar    = mantissa.alloc;                                               \
943   sr    = mantissa.size;                                                \
944   dr    = (B_)(hp);                                                     \
945 }
946 #endif /* !alpha */
947
948 #define decodeDoubleZh(exponr, ar,sr,dr, hp, f)                         \
949 { MP_INT mantissa;                                                      \
950   I_ exponent;                                                          \
951   StgDouble arg = (f);                                                  \
952                                                                         \
953   /* Be prepared to tell Lennart-coded __decodeDouble   */              \
954   /* where mantissa.d can be put (it does not care about the rest) */   \
955   SET_DATA_HDR(hp,ArrayOfData_info,CCC,DATA_VHS+MIN_MP_INT_SIZE,0);     \
956   mantissa.d = (hp) + DATA_HS;                                          \
957                                                                         \
958   /* Perform the operation */                                           \
959   SAFESTGCALL3(void,(void *, MP_INT *, I_ *, StgDouble),__decodeDouble,&mantissa,&exponent,arg);                \
960   exponr= exponent;                                                     \
961   ar    = mantissa.alloc;                                               \
962   sr    = mantissa.size;                                                \
963   dr    = (B_)(hp);                                                     \
964 }
965 \end{code}
966
967 %************************************************************************
968 %*                                                                      *
969 \subsubsection[StgMacros-mv-floats]{Moving floats and doubles around (e.g., to/from stacks)}
970 %*                                                                      *
971 %************************************************************************
972
973 With GCC, we use magic non-standard inlining; for other compilers, we
974 just use functions (see also \tr{runtime/prims/PrimArith.lc}).
975
976 (The @OMIT_...@ is only used in compiling some of the RTS, none of
977 which uses these anyway.)
978
979 \begin{code}
980 #if alpha_TARGET_ARCH   \
981  || i386_TARGET_ARCH    \
982  || m68k_TARGET_ARCH
983
984 #define ASSIGN_FLT(dst, src) *(StgFloat *)(dst) = (src);
985 #define PK_FLT(src) (*(StgFloat *)(src))
986
987 #define ASSIGN_DBL(dst, src) *(StgDouble *)(dst) = (src);
988 #define PK_DBL(src) (*(StgDouble *)(src))
989
990 #else   /* not m68k || alpha || i[34]86 */
991
992 /* Special handling for machines with troublesome alignment constraints */
993
994 #define FLOAT_ALIGNMENT_TROUBLES    TRUE
995
996 #if ! defined(__GNUC__) || ! defined(__STG_GCC_REGS__)
997
998 void        ASSIGN_DBL PROTO((W_ [], StgDouble));
999 StgDouble   PK_DBL     PROTO((W_ []));
1000 void        ASSIGN_FLT PROTO((W_ [], StgFloat));
1001 StgFloat    PK_FLT     PROTO((W_ []));
1002
1003 #else /* yes, its __GNUC__ && we really want them */
1004
1005 #if sparc_TARGET_ARCH
1006
1007 #define ASSIGN_FLT(dst, src) *(StgFloat *)(dst) = (src);
1008 #define PK_FLT(src) (*(StgFloat *)(src))
1009
1010 #define ASSIGN_DBL(dst,src) \
1011       __asm__("st %2,%0\n\tst %R2,%1" : "=m" (((P_)(dst))[0]), \
1012         "=m" (((P_)(dst))[1]) : "f" (src));
1013
1014 #define PK_DBL(src) \
1015     ( { register double d; \
1016       __asm__("ld %1,%0\n\tld %2,%R0" : "=f" (d) : \
1017         "m" (((P_)(src))[0]), "m" (((P_)(src))[1])); d; \
1018     } )
1019
1020 #else /* ! sparc */
1021
1022 /* (not very) forward prototype declarations */
1023 void        ASSIGN_DBL PROTO((W_ [], StgDouble));
1024 StgDouble   PK_DBL     PROTO((W_ []));
1025 void        ASSIGN_FLT PROTO((W_ [], StgFloat));
1026 StgFloat    PK_FLT     PROTO((W_ []));
1027
1028 extern STG_INLINE
1029 void
1030 ASSIGN_DBL(W_ p_dest[], StgDouble src)
1031 {
1032     double_thing y;
1033     y.d = src;
1034     p_dest[0] = y.du.dhi;
1035     p_dest[1] = y.du.dlo;
1036 }
1037
1038 /* GCC also works with this version, but it generates
1039    the same code as the previous one, and is not ANSI
1040
1041 #define ASSIGN_DBL( p_dest, src ) \
1042         *p_dest = ((double_thing) src).du.dhi; \
1043         *(p_dest+1) = ((double_thing) src).du.dlo \
1044 */
1045
1046 extern STG_INLINE
1047 StgDouble
1048 PK_DBL(W_ p_src[])
1049 {
1050     double_thing y;
1051     y.du.dhi = p_src[0];
1052     y.du.dlo = p_src[1];
1053     return(y.d);
1054 }
1055
1056 extern STG_INLINE
1057 void
1058 ASSIGN_FLT(W_ p_dest[], StgFloat src)
1059 {
1060     float_thing y;
1061     y.f = src;
1062     *p_dest = y.fu;
1063 }
1064
1065 extern STG_INLINE
1066 StgFloat
1067 PK_FLT(W_ p_src[])
1068 {
1069     float_thing y;
1070     y.fu = *p_src;
1071     return(y.f);
1072 }
1073
1074 #endif /* ! sparc */
1075
1076 #endif /* __GNUC__ */
1077
1078 #endif /* not __m68k__ */
1079 \end{code}
1080
1081 %************************************************************************
1082 %*                                                                      *
1083 \subsubsection[StgMacros-array-primops]{Primitive arrays}
1084 %*                                                                      *
1085 %************************************************************************
1086
1087 We regularly use this macro to fish the ``contents'' part
1088 out of a DATA or TUPLE closure, which is what is used for
1089 non-ptr and ptr arrays (respectively).
1090
1091 BYTE_ARR_CTS returns a @C_ *@!
1092
1093 We {\em ASSUME} we can use the same macro for both!!
1094 \begin{code}
1095
1096 #ifdef DEBUG
1097 #define BYTE_ARR_CTS(a)                                 \
1098  ({ ASSERT(INFO_PTR(a) == (W_) ArrayOfData_info);       \
1099     ((C_ *) (((StgPtr) (a))+DATA_HS)); })
1100 #define PTRS_ARR_CTS(a)                                 \
1101  ({ ASSERT((INFO_PTR(a) == (W_) ArrayOfPtrs_info)       \
1102         || (INFO_PTR(a) == (W_) ImMutArrayOfPtrs_info));\
1103     ((a)+MUTUPLE_HS);} )
1104 #else
1105 #define BYTE_ARR_CTS(a)         ((char *) (((StgPtr) (a))+DATA_HS))
1106 #define PTRS_ARR_CTS(a)         ((a)+MUTUPLE_HS)
1107 #endif
1108
1109 /* sigh */
1110 extern I_ genSymZh(STG_NO_ARGS);
1111 extern I_ resetGenSymZh(STG_NO_ARGS);
1112 extern I_ incSeqWorldZh(STG_NO_ARGS);
1113
1114 extern I_ byteArrayHasNUL__ PROTO((const char *, I_));
1115 \end{code}
1116
1117 OK, the easy ops first: (all except \tr{newArr*}:
1118
1119 (OLD:) VERY IMPORTANT! The read/write/index primitive ops
1120 on @ByteArray#@s index the array using a {\em BYTE} offset, even
1121 if the thing begin gotten out is a multi-byte @Int#@, @Float#@ etc.
1122 This is because you might be trying to take apart a C struct, where
1123 the offset from the start of the struct isn't a multiple of the
1124 size of the thing you're getting.  Hence the @(char *)@ casts.
1125
1126 EVEN MORE IMPORTANT! The above is a lie.  The offsets for BlahArrays
1127 are in Blahs.  WDP 95/08
1128
1129 In the case of messing with @StgAddrs@ (@A_@), which are really \tr{void *},
1130 we cast to @P_@, because you can't index off an uncast \tr{void *}.
1131
1132 In the case of @Array#@ (which contain pointers), the offset is in units
1133 of one ptr (not bytes).
1134
1135 \begin{code}
1136 #define sameMutableArrayZh(r,a,b)       r=(I_)((a)==(b))
1137 #define sameMutableByteArrayZh(r,a,b)   r=(I_)((B_)(a)==(B_)(b))
1138
1139 #define readArrayZh(r,a,i)       r=((PP_) PTRS_ARR_CTS(a))[(i)]
1140
1141 #define readCharArrayZh(r,a,i)   indexCharOffAddrZh(r,BYTE_ARR_CTS(a),i)
1142 #define readIntArrayZh(r,a,i)    indexIntOffAddrZh(r,BYTE_ARR_CTS(a),i)
1143 #define readAddrArrayZh(r,a,i)   indexAddrOffAddrZh(r,BYTE_ARR_CTS(a),i)
1144 #define readFloatArrayZh(r,a,i)  indexFloatOffAddrZh(r,BYTE_ARR_CTS(a),i)
1145 #define readDoubleArrayZh(r,a,i) indexDoubleOffAddrZh(r,BYTE_ARR_CTS(a),i)
1146
1147 /* result ("r") arg ignored in write macros! */
1148 #define writeArrayZh(a,i,v)     ((PP_) PTRS_ARR_CTS(a))[(i)]=(v)
1149
1150 #define writeCharArrayZh(a,i,v)   ((C_ *)(BYTE_ARR_CTS(a)))[i] = (v)
1151 #define writeIntArrayZh(a,i,v)    ((I_ *)(BYTE_ARR_CTS(a)))[i] = (v)
1152 #define writeAddrArrayZh(a,i,v)   ((PP_)(BYTE_ARR_CTS(a)))[i] = (v)
1153 #define writeFloatArrayZh(a,i,v)  \
1154         ASSIGN_FLT((P_) (((StgFloat *)(BYTE_ARR_CTS(a))) + i),v)
1155 #define writeDoubleArrayZh(a,i,v) \
1156         ASSIGN_DBL((P_) (((StgDouble *)(BYTE_ARR_CTS(a))) + i),v)
1157
1158 #define indexArrayZh(r,a,i)       r=((PP_) PTRS_ARR_CTS(a))[(i)]
1159
1160 #define indexCharArrayZh(r,a,i)   indexCharOffAddrZh(r,BYTE_ARR_CTS(a),i)
1161 #define indexIntArrayZh(r,a,i)    indexIntOffAddrZh(r,BYTE_ARR_CTS(a),i)
1162 #define indexAddrArrayZh(r,a,i)   indexAddrOffAddrZh(r,BYTE_ARR_CTS(a),i)
1163 #define indexFloatArrayZh(r,a,i)  indexFloatOffAddrZh(r,BYTE_ARR_CTS(a),i)
1164 #define indexDoubleArrayZh(r,a,i) indexDoubleOffAddrZh(r,BYTE_ARR_CTS(a),i)
1165
1166 #define indexCharOffAddrZh(r,a,i)   r= ((C_ *)(a))[i]
1167 #define indexIntOffAddrZh(r,a,i)    r= ((I_ *)(a))[i]
1168 #define indexAddrOffAddrZh(r,a,i)   r= ((PP_)(a))[i]
1169 #define indexFloatOffAddrZh(r,a,i)  r= PK_FLT((P_) (((StgFloat *)(a)) + i))
1170 #define indexDoubleOffAddrZh(r,a,i) r= PK_DBL((P_) (((StgDouble *)(a)) + i))
1171
1172 /* Freezing arrays-of-ptrs requires changing an info table, for the
1173    benefit of the generational collector.  It needs to scavenge mutable
1174    objects, even if they are in old space.  When they become immutable,
1175    they can be removed from this scavenge list.  */
1176 #define unsafeFreezeArrayZh(r,a)                                \
1177         do {                                            \
1178         P_ result;                                      \
1179         result=(P_) (a);                                \
1180         FREEZE_MUT_HDR(result,ImMutArrayOfPtrs_info);   \
1181         r = result;                                     \
1182         }while(0)
1183
1184 #define unsafeFreezeByteArrayZh(r,a)    r=(B_)(a)
1185 \end{code}
1186
1187 Now the \tr{newArr*} ops:
1188
1189 \begin{code}
1190 /*
1191 --------------------
1192 Will: ToDo: we need to find suitable places to put this comment, and the
1193 "in-general" one which follows.
1194
1195 ************ Nota Bene.  The "n" in this macro is guaranteed to
1196 be a register, *not* (say) Node[1].  That means that it is guaranteed
1197 to survive GC, provided only that the register is kept unaltered.
1198 This is important, because "n" is used after the HEAP_CHK.
1199
1200 In general, *all* parameters to these primitive-op macros are always
1201 registers.  (Will: For exactly *which* primitive-op macros is this guaranteed?
1202 Exactly those which can trigger GC?)
1203 ------------------------
1204
1205 NOTE: the above may now be OLD (WDP 94/02/10)
1206 */
1207 \end{code}
1208
1209 For char arrays, the size is in {\em BYTES}.
1210
1211 \begin{code}
1212 #define newCharArrayZh(r,liveness,n)    newByteArray(r,liveness,(n) * sizeof(C_))
1213 #define newIntArrayZh(r,liveness,n)     newByteArray(r,liveness,(n) * sizeof(I_))
1214 #define newAddrArrayZh(r,liveness,n)    newByteArray(r,liveness,(n) * sizeof(P_))
1215 #define newFloatArrayZh(r,liveness,n)   newByteArray(r,liveness,(n) * sizeof(StgFloat))
1216 #define newDoubleArrayZh(r,liveness,n)  newByteArray(r,liveness,(n) * sizeof(StgDouble))
1217
1218 #define newByteArray(r,liveness,n)                              \
1219 {                                                               \
1220   P_ result;                                                    \
1221   I_ size;                                                      \
1222                                                                 \
1223   HEAP_CHK(liveness,DATA_HS+BYTES_TO_STGWORDS(n),0);            \
1224   size = BYTES_TO_STGWORDS(n);                                  \
1225   ALLOC_PRIM(DATA_HS,size,0,DATA_HS+size) /* ticky ticky */;    \
1226   CC_ALLOC(CCC,DATA_HS+size,ARR_K);                             \
1227                                                                 \
1228   result = Hp-(DATA_HS+size)+1;                                 \
1229   SET_DATA_HDR(result,ArrayOfData_info,CCC,DATA_VHS+size,0);    \
1230   r = (B_) result;                                              \
1231 }
1232 \end{code}
1233
1234 Arrays of pointers need to be initialised; uses \tr{TUPLES}!
1235 The initialisation value is guaranteed to be in a register,
1236 and will be indicated by the liveness mask, so it's ok to do
1237 a \tr{HEAP_CHK}, which may trigger GC.
1238
1239 \begin{code}
1240 /* The new array initialization routine for the NCG */
1241 void newArrZh_init PROTO((P_ result, I_ n, P_ init));
1242
1243 #define newArrayZh(r,liveness,n,init)                   \
1244 {                                                       \
1245   P_ p;                                                 \
1246   P_ result;                                            \
1247                                                         \
1248   HEAP_CHK(liveness, MUTUPLE_HS+(n),0);                 \
1249   ALLOC_PRIM(MUTUPLE_HS,(n),0,MUTUPLE_HS+(n)) /* ticky ticky */; \
1250   CC_ALLOC(CCC,MUTUPLE_HS+(n),ARR_K); /* cc prof */     \
1251                                                         \
1252   result = Hp + 1 - (MUTUPLE_HS+(n));                   \
1253   SET_MUTUPLE_HDR(result,ArrayOfPtrs_info,CCC,MUTUPLE_VHS+(n),0) \
1254   for (p = result+MUTUPLE_HS; p < (result+MUTUPLE_HS+(n)); p++) { \
1255         *p = (W_) (init);                               \
1256   }                                                     \
1257                                                         \
1258   r = result;                                           \
1259 }
1260 \end{code}
1261
1262 %************************************************************************
1263 %*                                                                      *
1264 \subsubsection[StgMacros-SynchVar-primops]{Synchronizing Variables PrimOps}
1265 %*                                                                      *
1266 %************************************************************************
1267
1268 \begin{code}
1269 ED_(PrelBase_Z91Z93_closure);
1270
1271 #define newSynchVarZh(r, hp)                            \
1272 {                                                       \
1273   ALLOC_PRIM(MUTUPLE_HS,3,0,MUTUPLE_HS+3) /* ticky ticky */; \
1274   CC_ALLOC(CCC,MUTUPLE_HS+3,ARR_K); /* cc prof */       \
1275   SET_SVAR_HDR(hp,EmptySVar_info,CCC);                  \
1276   SVAR_HEAD(hp) = SVAR_TAIL(hp) = SVAR_VALUE(hp) = PrelBase_Z91Z93_closure;     \
1277   r = hp;                                               \
1278 }
1279 \end{code}
1280
1281 \begin{code}
1282 #ifdef CONCURRENT
1283
1284 void Yield PROTO((W_));
1285
1286 #define takeMVarZh(r, liveness, node)                   \
1287 {                                                       \
1288   while (INFO_PTR(node) != (W_) FullSVar_info) {        \
1289     if (SVAR_HEAD(node) == PrelBase_Z91Z93_closure)             \
1290       SVAR_HEAD(node) = CurrentTSO;                     \
1291     else                                                \
1292       TSO_LINK(SVAR_TAIL(node)) = CurrentTSO;           \
1293     TSO_LINK(CurrentTSO) = (P_) PrelBase_Z91Z93_closure;                \
1294     SVAR_TAIL(node) = CurrentTSO;                       \
1295     DO_YIELD(liveness << 1);                            \
1296   }                                                     \
1297   SET_INFO_PTR(node, EmptySVar_info);                   \
1298   r = SVAR_VALUE(node);                                 \
1299   SVAR_VALUE(node) = PrelBase_Z91Z93_closure;                           \
1300 }
1301
1302 #else
1303
1304 #define takeMVarZh(r, liveness, node)                   \
1305 {                                                       \
1306   if (INFO_PTR(node) != (W_) FullSVar_info) {           \
1307     /* Don't wrap the calls; we're done with STG land */\
1308     fflush(stdout);                                     \
1309     fprintf(stderr, "takeMVar#: MVar is empty.\n");     \
1310     EXIT(EXIT_FAILURE);                                 \
1311   }                                                     \
1312   SET_INFO_PTR(node, EmptySVar_info);                   \
1313   r = SVAR_VALUE(node);                                 \
1314   SVAR_VALUE(node) = PrelBase_Z91Z93_closure;                           \
1315 }
1316
1317 #endif
1318 \end{code}
1319
1320 \begin{code}
1321 #ifdef CONCURRENT
1322
1323 #ifdef GRAN
1324
1325 /* Only difference to the !GRAN def: RunnableThreadsHd has been replaced by */
1326 /* ThreadQueueHd i.e. the tso is added at the end of the thread queue on */
1327 /* the CurrentProc. This means we have an implicit context switch after */
1328 /* putMVar even if unfair scheduling is used in GranSim (default)!  -- HWL */
1329
1330 #define putMVarZh(node, value)                          \
1331 {                                                       \
1332   P_ tso;                                               \
1333   if (INFO_PTR(node) == (W_) FullSVar_info) {           \
1334     /* Don't wrap the calls; we're done with STG land */\
1335     fflush(stdout);                                     \
1336     fprintf(stderr, "putMVar#: MVar already full.\n");  \
1337     EXIT(EXIT_FAILURE);                                 \
1338   }                                                     \
1339   SET_INFO_PTR(node, FullSVar_info);                    \
1340   SVAR_VALUE(node) = value;                             \
1341   tso = SVAR_HEAD(node);                                \
1342   if (tso != (P_) PrelBase_Z91Z93_closure) {                            \
1343     if (DO_QP_PROF)                                     \
1344       STGCALL3(void,(void *, char *, P_, P_),QP_Event2,do_qp_prof > 1 ? "RA" : "RG",tso,CurrentTSO);    \
1345     if (ThreadQueueHd == PrelBase_Z91Z93_closure)               \
1346       ThreadQueueHd = tso;                      \
1347     else                                                \
1348       TSO_LINK(ThreadQueueTl) = tso;            \
1349     ThreadQueueTl = tso;                                \
1350     SVAR_HEAD(node) = TSO_LINK(tso);                    \
1351     TSO_LINK(tso) = (P_) PrelBase_Z91Z93_closure;                       \
1352     if(SVAR_HEAD(node) == (P_) PrelBase_Z91Z93_closure)                 \
1353       SVAR_TAIL(node) = (P_) PrelBase_Z91Z93_closure;           \
1354   }                                                     \
1355 }
1356
1357 #else /* !GRAN */
1358
1359 #define putMVarZh(node, value)                          \
1360 {                                                       \
1361   P_ tso;                                               \
1362   if (INFO_PTR(node) == (W_) FullSVar_info) {           \
1363     /* Don't wrap the calls; we're done with STG land */\
1364     fflush(stdout);                                     \
1365     fprintf(stderr, "putMVar#: MVar already full.\n");  \
1366     EXIT(EXIT_FAILURE);                                 \
1367   }                                                     \
1368   SET_INFO_PTR(node, FullSVar_info);                    \
1369   SVAR_VALUE(node) = value;                             \
1370   tso = SVAR_HEAD(node);                                \
1371   if (tso != (P_) PrelBase_Z91Z93_closure) {                            \
1372     if (DO_QP_PROF)                                     \
1373       STGCALL3(void,(void *, char *, P_, P_),QP_Event2,do_qp_prof > 1 ? "RA" : "RG",tso,CurrentTSO);    \
1374     if (RunnableThreadsHd == PrelBase_Z91Z93_closure)                   \
1375       RunnableThreadsHd = tso;                          \
1376     else                                                \
1377       TSO_LINK(RunnableThreadsTl) = tso;                \
1378     RunnableThreadsTl = tso;                            \
1379     SVAR_HEAD(node) = TSO_LINK(tso);                    \
1380     TSO_LINK(tso) = (P_) PrelBase_Z91Z93_closure;                       \
1381     if(SVAR_HEAD(node) == (P_) PrelBase_Z91Z93_closure)                 \
1382       SVAR_TAIL(node) = (P_) PrelBase_Z91Z93_closure;           \
1383   }                                                     \
1384 }
1385
1386 #endif  /* GRAN */
1387
1388 #else
1389
1390 #define putMVarZh(node, value)                          \
1391 {                                                       \
1392   P_ tso;                                               \
1393   if (INFO_PTR(node) == (W_) FullSVar_info) {           \
1394     /* Don't wrap the calls; we're done with STG land */\
1395     fflush(stdout);                                     \
1396     fprintf(stderr, "putMVar#: MVar already full.\n");  \
1397     EXIT(EXIT_FAILURE);                                 \
1398   }                                                     \
1399   SET_INFO_PTR(node, FullSVar_info);                    \
1400   SVAR_VALUE(node) = value;                             \
1401 }
1402
1403 #endif
1404 \end{code}
1405
1406 \begin{code}
1407 #ifdef CONCURRENT
1408
1409 #define readIVarZh(r, liveness, node)                   \
1410 {                                                       \
1411   if (INFO_PTR(node) != (W_) ImMutArrayOfPtrs_info) {   \
1412     if (SVAR_HEAD(node) == PrelBase_Z91Z93_closure)             \
1413       SVAR_HEAD(node) = CurrentTSO;                     \
1414     else                                                \
1415       TSO_LINK(SVAR_TAIL(node)) = CurrentTSO;           \
1416     TSO_LINK(CurrentTSO) = (P_) PrelBase_Z91Z93_closure;                \
1417     SVAR_TAIL(node) = CurrentTSO;                       \
1418     DO_YIELD(liveness << 1);                            \
1419   }                                                     \
1420   r = SVAR_VALUE(node);                                 \
1421 }
1422
1423 #else
1424
1425 #define readIVarZh(r, liveness, node)                   \
1426 {                                                       \
1427   if (INFO_PTR(node) != (W_) ImMutArrayOfPtrs_info) {   \
1428     /* Don't wrap the calls; we're done with STG land */\
1429     fflush(stdout);                                     \
1430     fprintf(stderr, "readIVar#: IVar is empty.\n");     \
1431     EXIT(EXIT_FAILURE);                                 \
1432   }                                                     \
1433   r = SVAR_VALUE(node);                                 \
1434 }
1435
1436 #endif
1437 \end{code}
1438
1439 \begin{code}
1440 #ifdef CONCURRENT
1441
1442 #ifdef GRAN
1443
1444 /* Only difference to the !GRAN def: RunnableThreadsHd has been replaced by */
1445 /* ThreadQueueHd i.e. the tso is added at the end of the thread queue on */
1446 /* the CurrentProc. This means we have an implicit context switch after */
1447 /* writeIVar even if unfair scheduling is used in GranSim (default)!  -- HWL */
1448
1449 #define writeIVarZh(node, value)                        \
1450 {                                                       \
1451   P_ tso;                                               \
1452   if (INFO_PTR(node) == (W_) ImMutArrayOfPtrs_info) {   \
1453     /* Don't wrap the calls; we're done with STG land */\
1454     fflush(stdout);                                     \
1455     fprintf(stderr, "writeIVar#: IVar already full.\n");\
1456     EXIT(EXIT_FAILURE);                                 \
1457   }                                                     \
1458   tso = SVAR_HEAD(node);                                \
1459   if (tso != (P_) PrelBase_Z91Z93_closure) {                            \
1460     if (ThreadQueueHd == PrelBase_Z91Z93_closure)               \
1461       ThreadQueueHd = tso;                      \
1462     else                                                \
1463       TSO_LINK(ThreadQueueTl) = tso;            \
1464     while(TSO_LINK(tso) != PrelBase_Z91Z93_closure) {                   \
1465       if (DO_QP_PROF)                                   \
1466         STGCALL3(void,(void *, char *, P_, P_),QP_Event2,do_qp_prof > 1 ? "RA" : "RG",tso,CurrentTSO);  \
1467       tso = TSO_LINK(tso);                              \
1468     }                                                   \
1469     if (DO_QP_PROF)                                     \
1470       STGCALL3(void,(void *, char *, P_, P_),QP_Event2,do_qp_prof > 1 ? "RA" : "RG",tso,CurrentTSO);    \
1471     ThreadQueueTl = tso;                                \
1472   }                                                     \
1473   /* Don't use freeze, since it's conditional on GC */  \
1474   SET_INFO_PTR(node, ImMutArrayOfPtrs_info);            \
1475   MUTUPLE_CLOSURE_SIZE(node) = (MUTUPLE_VHS+1);         \
1476   SVAR_VALUE(node) = value;                             \
1477 }
1478
1479 #else /* !GRAN */
1480
1481 #define writeIVarZh(node, value)                        \
1482 {                                                       \
1483   P_ tso;                                               \
1484   if (INFO_PTR(node) == (W_) ImMutArrayOfPtrs_info) {   \
1485     /* Don't wrap the calls; we're done with STG land */\
1486     fflush(stdout);                                     \
1487     fprintf(stderr, "writeIVar#: IVar already full.\n");\
1488     EXIT(EXIT_FAILURE);                                 \
1489   }                                                     \
1490   tso = SVAR_HEAD(node);                                \
1491   if (tso != (P_) PrelBase_Z91Z93_closure) {                            \
1492     if (RunnableThreadsHd == PrelBase_Z91Z93_closure)                   \
1493       RunnableThreadsHd = tso;                          \
1494     else                                                \
1495       TSO_LINK(RunnableThreadsTl) = tso;                \
1496     while(TSO_LINK(tso) != PrelBase_Z91Z93_closure) {                   \
1497       if (DO_QP_PROF)                                   \
1498         STGCALL3(void,(void *, char *, P_, P_),QP_Event2,do_qp_prof > 1 ? "RA" : "RG",tso,CurrentTSO);  \
1499       tso = TSO_LINK(tso);                              \
1500     }                                                   \
1501     if (DO_QP_PROF)                                     \
1502       STGCALL3(void,(void *, char *, P_, P_),QP_Event2,do_qp_prof > 1 ? "RA" : "RG",tso,CurrentTSO);    \
1503     RunnableThreadsTl = tso;                            \
1504   }                                                     \
1505   /* Don't use freeze, since it's conditional on GC */  \
1506   SET_INFO_PTR(node, ImMutArrayOfPtrs_info);            \
1507   MUTUPLE_CLOSURE_SIZE(node) = (MUTUPLE_VHS+1);         \
1508   SVAR_VALUE(node) = value;                             \
1509 }
1510
1511 #endif  /* GRAN */
1512
1513 #else
1514
1515 #define writeIVarZh(node, value)                        \
1516 {                                                       \
1517   P_ tso;                                               \
1518   if (INFO_PTR(node) == (W_) ImMutArrayOfPtrs_info) {   \
1519     /* Don't wrap the calls; we're done with STG land */\
1520     fflush(stdout);                                     \
1521     fprintf(stderr, "writeIVar#: IVar already full.\n");\
1522     EXIT(EXIT_FAILURE);                                 \
1523   }                                                     \
1524   /* Don't use freeze, since it's conditional on GC */  \
1525   SET_INFO_PTR(node, ImMutArrayOfPtrs_info);            \
1526   MUTUPLE_CLOSURE_SIZE(node) = (MUTUPLE_VHS+1);         \
1527   SVAR_VALUE(node) = value;                             \
1528 }
1529
1530 #endif
1531 \end{code}
1532
1533 %************************************************************************
1534 %*                                                                      *
1535 \subsubsection[StgMacros-Wait-primops]{Delay/Wait PrimOps}
1536 %*                                                                      *
1537 %************************************************************************
1538
1539 \begin{code}
1540 #ifdef CONCURRENT
1541
1542 /* ToDo: for GRAN */
1543
1544 #define delayZh(liveness, us)                           \
1545   {                                                     \
1546     if (WaitingThreadsTl == PrelBase_Z91Z93_closure)            \
1547       WaitingThreadsHd = CurrentTSO;                    \
1548     else                                                \
1549       TSO_LINK(WaitingThreadsTl) = CurrentTSO;          \
1550     WaitingThreadsTl = CurrentTSO;                      \
1551     TSO_LINK(CurrentTSO) = PrelBase_Z91Z93_closure;                     \
1552     TSO_EVENT(CurrentTSO) = (W_) ((us) < 1 ? 1 : (us)); \
1553     DO_YIELD(liveness << 1);                            \
1554   }
1555
1556 #else
1557
1558 #define delayZh(liveness, us)                           \
1559   {                                                     \
1560     fflush(stdout);                                     \
1561     fprintf(stderr, "delay#: unthreaded build.\n");     \
1562     EXIT(EXIT_FAILURE);                                 \
1563   }
1564
1565 #endif
1566
1567 #ifdef CONCURRENT
1568
1569 /* ToDo: something for GRAN */
1570
1571 #define waitReadZh(liveness, fd)                        \
1572   {                                                     \
1573     if (WaitingThreadsTl == PrelBase_Z91Z93_closure)            \
1574       WaitingThreadsHd = CurrentTSO;                    \
1575     else                                                \
1576       TSO_LINK(WaitingThreadsTl) = CurrentTSO;          \
1577     WaitingThreadsTl = CurrentTSO;                      \
1578     TSO_LINK(CurrentTSO) = PrelBase_Z91Z93_closure;                     \
1579     TSO_EVENT(CurrentTSO) = (W_) (-(fd));               \
1580     DO_YIELD(liveness << 1);                            \
1581   }
1582
1583 #else
1584
1585 #define waitReadZh(liveness, fd)                        \
1586   {                                                     \
1587     fflush(stdout);                                     \
1588     fprintf(stderr, "waitRead#: unthreaded build.\n");  \
1589     EXIT(EXIT_FAILURE);                                 \
1590   }
1591
1592 #endif
1593
1594 #ifdef CONCURRENT
1595
1596 /* ToDo: something for GRAN */
1597
1598 #ifdef HAVE_SYS_TYPES_H
1599 #include <sys/types.h>
1600 #endif  HAVE_SYS_TYPES_H */
1601
1602 #define waitWriteZh(liveness, fd)                       \
1603   {                                                     \
1604     if (WaitingThreadsTl == PrelBase_Z91Z93_closure)            \
1605       WaitingThreadsHd = CurrentTSO;                    \
1606     else                                                \
1607       TSO_LINK(WaitingThreadsTl) = CurrentTSO;          \
1608     WaitingThreadsTl = CurrentTSO;                      \
1609     TSO_LINK(CurrentTSO) = PrelBase_Z91Z93_closure;                     \
1610     TSO_EVENT(CurrentTSO) = (W_) (-(fd+FD_SETSIZE));    \
1611     DO_YIELD(liveness << 1);                            \
1612   }
1613
1614 #else
1615
1616 #define waitWriteZh(liveness, fd)                       \
1617   {                                                     \
1618     fflush(stdout);                                     \
1619     fprintf(stderr, "waitWrite#: unthreaded build.\n"); \
1620     EXIT(EXIT_FAILURE);                                 \
1621   }
1622
1623 #endif
1624
1625 \end{code}
1626
1627 %************************************************************************
1628 %*                                                                      *
1629 \subsubsection[StgMacros-IO-primops]{Primitive I/O, error-handling primops}
1630 %*                                                                      *
1631 %************************************************************************
1632
1633 \begin{code}
1634 extern P_ TopClosure;
1635 EXTFUN(ErrorIO_innards);
1636 EXTFUN(__std_entry_error__);
1637
1638 #define errorIOZh(a)            \
1639     do { TopClosure=(a);        \
1640          (void) SAFESTGCALL1(I_,(void *, FILE *),fflush,stdout); \
1641          (void) SAFESTGCALL1(I_,(void *, FILE *),fflush,stderr); \
1642          JMP_(ErrorIO_innards); \
1643     } while(0)
1644
1645 #if !defined(CALLER_SAVES_SYSTEM)
1646 /* can use the macros */
1647 #define stg_getc(stream)        getc((FILE *) (stream))
1648 #define stg_putc(c,stream)      putc((c),((FILE *) (stream)))
1649 #else
1650 /* must not use the macros (they contain embedded calls to _filbuf/whatnot) */
1651 #define stg_getc(stream)        SAFESTGCALL1(I_,(void *, FILE *),fgetc,(FILE *) (stream))
1652 #define stg_putc(c,stream)      SAFESTGCALL2(I_,(void *, char, FILE *),fputc,(c),((FILE *) (stream)))
1653 #endif
1654
1655 int initialize_virtual_timer(int us);
1656 int install_segv_handler(STG_NO_ARGS);
1657 int install_vtalrm_handler(STG_NO_ARGS);
1658 void initUserSignals(STG_NO_ARGS);
1659 void blockUserSignals(STG_NO_ARGS);
1660 void unblockUserSignals(STG_NO_ARGS);
1661 IF_RTS(void blockVtAlrmSignal(STG_NO_ARGS);)
1662 IF_RTS(void unblockVtAlrmSignal(STG_NO_ARGS);)
1663 IF_RTS(void AwaitEvent(I_ delta);)
1664
1665 #if  defined(_POSIX_SOURCE) && !defined(nextstep3_TARGET_OS)
1666         /* For nextstep3_TARGET_OS comment see stgdefs.h. CaS */
1667 extern I_ sig_install PROTO((I_, I_, sigset_t *));
1668 #define stg_sig_ignore(s,m)     SAFESTGCALL3(I_,(void *, I_, I_),sig_install,s,STG_SIG_IGN,(sigset_t *)m)
1669 #define stg_sig_default(s,m)    SAFESTGCALL3(I_,(void *, I_, I_),sig_install,s,STG_SIG_DFL,(sigset_t *)m)
1670 #define stg_sig_catch(s,sp,m)   SAFESTGCALL3(I_,(void *, I_, I_),sig_install,s,sp,(sigset_t *)m)
1671 #else
1672 extern I_ sig_install PROTO((I_, I_));
1673 #define stg_sig_ignore(s,m)     SAFESTGCALL2(I_,(void *, I_, I_),sig_install,s,STG_SIG_IGN)
1674 #define stg_sig_default(s,m)    SAFESTGCALL2(I_,(void *, I_, I_),sig_install,s,STG_SIG_DFL)
1675 #define stg_sig_catch(s,sp,m)   SAFESTGCALL2(I_,(void *, I_, I_),sig_install,s,sp)
1676 #endif
1677
1678 #define STG_SIG_DFL     (-1)
1679 #define STG_SIG_IGN     (-2)
1680 #define STG_SIG_ERR     (-3)
1681
1682 StgInt getErrorHandler(STG_NO_ARGS);
1683 #ifndef PAR
1684 void   raiseError PROTO((StgStablePtr handler));
1685 StgInt catchError PROTO((StgStablePtr newErrorHandler));
1686 #endif
1687 void decrementErrorCount(STG_NO_ARGS);
1688
1689 #define stg_catchError(sp)        SAFESTGCALL1(I_,(void *, StgStablePtr),catchError,sp)
1690 #define stg_decrementErrorCount() SAFESTGCALL0(void,(void *),decrementErrorCount)
1691 \end{code}
1692
1693 %************************************************************************
1694 %*                                                                      *
1695 \subsubsection[StgMacros-stable-ptr]{Primitive ops for manipulating stable pointers}
1696 %*                                                                      *
1697 %************************************************************************
1698
1699
1700 The type of these should be:
1701
1702 \begin{verbatim}
1703 makeStablePointer#  :: a -> State# _RealWorld -> StateAndStablePtr# _RealWorld a
1704 deRefStablePointer# :: StablePtr# a -> State# _RealWorld -> StateAndPtr _RealWorld a
1705 \end{verbatim}
1706
1707 Since world-tokens are no longer explicitly passed around, the
1708 implementations have a few less arguments/results.
1709
1710 The simpler one is @deRefStablePointer#@ (which is only a primop
1711 because it is more polymorphic than is allowed of a ccall).
1712
1713 \begin{code}
1714 #ifdef PAR
1715
1716 #define deRefStablePtrZh(ri,sp)                                     \
1717 do {                                                                \
1718     fflush(stdout);                                                 \
1719     fprintf(stderr, "deRefStablePtr#: no stable pointer support.\n");\
1720     EXIT(EXIT_FAILURE);                                             \
1721 } while(0)
1722
1723 #else /* !PAR */
1724
1725 extern StgPtr _deRefStablePointer PROTO((StgInt, StgPtr));
1726
1727 #define deRefStablePtrZh(ri,sp) \
1728    ri = SAFESTGCALL2(I_,(void *, I_, P_),_deRefStablePointer,sp,StorageMgrInfo.StablePointerTable);
1729 \end{code}
1730
1731 Declarations for other stable pointer operations.
1732
1733 \begin{code}
1734 void    freeStablePointer       PROTO((I_ stablePtr));
1735
1736 void    enterStablePtr          PROTO((StgStablePtr, StgFunPtr));
1737 void    performIO               PROTO((StgStablePtr));
1738 I_      enterInt                PROTO((StgStablePtr));
1739 I_      enterFloat              PROTO((StgStablePtr));
1740 P_      deRefStablePointer      PROTO((StgStablePtr));
1741 IF_RTS(I_ catchSoftHeapOverflow PROTO((StgStablePtr, I_));)
1742 IF_RTS(I_ getSoftHeapOverflowHandler(STG_NO_ARGS);)
1743 IF_RTS(extern StgStablePtr softHeapOverflowHandler;)
1744 IF_RTS(void shutdownHaskell(STG_NO_ARGS);)
1745
1746 EXTFUN(stopPerformIODirectReturn);
1747 EXTFUN(startPerformIO);
1748 EXTFUN(stopEnterIntDirectReturn);
1749 EXTFUN(startEnterInt);
1750 EXTFUN(stopEnterFloatDirectReturn);
1751 EXTFUN(startEnterFloat);
1752
1753 void enterStablePtr PROTO((StgStablePtr stableIndex, StgFunPtr startCode));
1754
1755 #endif /* !PAR */
1756
1757 IF_RTS(extern I_ ErrorIO_call_count;)
1758 \end{code}
1759
1760 Somewhat harder is @makeStablePointer#@ --- it is usually simple but
1761 if we're unlucky, it will have to allocate a new table and copy the
1762 old bit over.  Since we might, very occasionally, have to call the
1763 garbage collector, this has to be a macro... sigh!
1764
1765 NB @newSP@ is required because it is entirely possible that
1766 @stablePtr@ and @unstablePtr@ are aliases and so we can't do the
1767 assignment to @stablePtr@ until we've finished with @unstablePtr@.
1768
1769 Another obscure piece of coding is the recalculation of the size of
1770 the table.  We do this just in case Jim's threads decide they want to
1771 context switch---in which case any stack-allocated variables may get
1772 trashed.  (If only there was a special heap check which didn't
1773 consider context switching...)
1774
1775 \begin{code}
1776 #ifndef PAR
1777
1778 /* Calculate SP Table size from number of pointers */
1779 #define SPTSizeFromNoPtrs( newNP ) (DYN_VHS + 1 + 2 * (newNP))
1780
1781 /* Calculate number of pointers in new table from number in old table:
1782    any strictly increasing expression will do here */
1783 #define CalcNewNoSPtrs( i ) ((i)*2 + 100)
1784
1785 void enlargeSPTable PROTO((P_, P_));
1786
1787 #define makeStablePtrZh(stablePtr,liveness,unstablePtr)             \
1788 do {                                                                \
1789   EXTDATA_RO(StablePointerTable_info);                              \
1790   EXTDATA(UnusedSP);                                                \
1791   StgStablePtr newSP;                                               \
1792                                                                     \
1793   if (SPT_EMPTY(StorageMgrInfo.StablePointerTable)) { /* free stack is empty */ \
1794     { /* Variables used before the heap check */                    \
1795       I_ OldNoPtrs = SPT_NoPTRS( StorageMgrInfo.StablePointerTable ); \
1796       I_ NewNoPtrs = CalcNewNoSPtrs( OldNoPtrs );                   \
1797       I_ NewSize = SPTSizeFromNoPtrs( NewNoPtrs );                  \
1798       HEAP_CHK(liveness, _FHS+NewSize, 0);                          \
1799     }                                                               \
1800     { /* Variables used after the heap check - same values */       \
1801       I_ OldNoPtrs = SPT_NoPTRS( StorageMgrInfo.StablePointerTable ); \
1802       I_ NewNoPtrs = CalcNewNoSPtrs( OldNoPtrs );                   \
1803       I_ NewSize = SPTSizeFromNoPtrs( NewNoPtrs );                  \
1804       P_ SPTable = Hp + 1 - (_FHS + NewSize);                       \
1805                                                                     \
1806       CC_ALLOC(CCC, _FHS+NewSize, SPT_K); /* cc prof */             \
1807       SET_DYN_HDR(SPTable,StablePointerTable_info,CCC,NewSize,NewNoPtrs);\
1808       SAFESTGCALL2(void, (void *, P_, P_), enlargeSPTable, SPTable, StorageMgrInfo.StablePointerTable);      \
1809       StorageMgrInfo.StablePointerTable = SPTable;                  \
1810     }                                                               \
1811   }                                                                 \
1812                                                                     \
1813   newSP = SPT_POP(StorageMgrInfo.StablePointerTable);               \
1814   SPT_SPTR(StorageMgrInfo.StablePointerTable, newSP) = unstablePtr; \
1815   CHECK_SPT_CLOSURE( StorageMgrInfo.StablePointerTable );           \
1816   stablePtr = newSP;                                                \
1817 } while (0)
1818
1819 #else
1820
1821 #define makeStablePtrZh(stablePtr,liveness,unstablePtr)             \
1822 do {                                                                \
1823     fflush(stdout);                                                 \
1824     fprintf(stderr, "makeStablePtr#: no stable pointer support.\n");\
1825     EXIT(EXIT_FAILURE);                                             \
1826 } while(0)
1827
1828 #endif /* !PAR */
1829 \end{code}
1830
1831 %************************************************************************
1832 %*                                                                      *
1833 \subsubsection[StgMacros-unsafePointerEquality]{Primitive `op' for breaking referential transparency}
1834 %*                                                                      *
1835 %************************************************************************
1836
1837 The type of this is @reallyUnsafePtrEquality :: a -> a -> Int#@ so we
1838 can expect three parameters: the two arguments and a "register" to put
1839 the result into.
1840
1841 Message to Will: This primop breaks referential transparency so badly
1842 you might want to leave it out.  On the other hand, if you hide it
1843 away in an appropriate monad, it's perfectly safe. [ADR]
1844
1845 Note that this primop is non-deterministic: different results can be
1846 obtained depending on just what the garbage collector (and code
1847 optimiser??) has done.  However, we can guarantee that if two objects
1848 are pointer-equal, they have the same denotation --- the converse most
1849 certainly doesn't hold.
1850
1851 ToDo ADR: The degree of non-determinism could be greatly reduced by
1852 following indirections.
1853
1854 \begin{code}
1855 #define reallyUnsafePtrEqualityZh(r,a,b) r=((StgPtr)(a) == (StgPtr)(b))
1856 \end{code}
1857
1858 %************************************************************************
1859 %*                                                                      *
1860 \subsubsection[StgMacros-parallel-primop]{Primitive `op' for sparking (etc)}
1861 %*                                                                      *
1862 %************************************************************************
1863
1864 Assuming local sparking in some form, we can now inline the spark request.
1865
1866 We build a doubly-linked list in the heap, so that we can handle FIFO
1867 or LIFO scheduling as we please.
1868
1869 Anything with tag >= 0 is in WHNF, so we discard it.
1870
1871 \begin{code}
1872 #ifdef CONCURRENT
1873
1874 ED_(PrelBase_Z91Z93_closure);
1875 ED_(True_closure);
1876
1877 #if defined(GRAN)
1878 #define parZh(r,node)                           \
1879         PARZh(r,node,1,0,0,0,0,0)
1880
1881 #define parAtZh(r,node,where,identifier,gran_info,size_info,par_info,rest) \
1882         parATZh(r,node,where,identifier,gran_info,size_info,par_info,rest,1)
1883
1884 #define parAtAbsZh(r,node,proc,identifier,gran_info,size_info,par_info,rest) \
1885         parATZh(r,node,proc,identifier,gran_info,size_info,par_info,rest,2)
1886
1887 #define parAtRelZh(r,node,proc,identifier,gran_info,size_info,par_info,rest) \
1888         parATZh(r,node,proc,identifier,gran_info,size_info,par_info,rest,3)
1889
1890 #define parAtForNowZh(r,node,where,identifier,gran_info,size_info,par_info,rest)        \
1891         parATZh(r,node,where,identifier,gran_info,size_info,par_info,rest,0)
1892
1893 #define parATZh(r,node,where,identifier,gran_info,size_info,par_info,rest,local)        \
1894 {                                                       \
1895   sparkq result;                                                \
1896   if (SHOULD_SPARK(node)) {                             \
1897     SaveAllStgRegs();                                   \
1898     { sparkq result;                                            \
1899       result = NewSpark((P_)node,identifier,gran_info,size_info,par_info,local);        \
1900       if (local==2) {         /* special case for parAtAbs */   \
1901         GranSimSparkAtAbs(result,(I_)where,identifier);\
1902       } else if (local==3) {  /* special case for parAtRel */   \
1903         GranSimSparkAtAbs(result,(I_)(CurrentProc+where),identifier);   \
1904       } else {       \
1905         GranSimSparkAt(result,where,identifier);        \
1906       }        \
1907       context_switch = 1;                               \
1908     }                                                   \
1909     RestoreAllStgRegs();                                \
1910   } else if (do_qp_prof) {                              \
1911     I_ tid = threadId++;                                \
1912     SAFESTGCALL2(void,(I_, P_),QP_Event0,tid,node);     \
1913   }                                                     \
1914   r = 1; /* return code for successful spark -- HWL */  \
1915 }
1916
1917 #define parLocalZh(r,node,identifier,gran_info,size_info,par_info,rest) \
1918         PARZh(r,node,rest,identifier,gran_info,size_info,par_info,1)
1919
1920 #define parGlobalZh(r,node,identifier,gran_info,size_info,par_info,rest) \
1921         PARZh(r,node,rest,identifier,gran_info,size_info,par_info,0)
1922
1923 #if 1
1924
1925 #define PARZh(r,node,rest,identifier,gran_info,size_info,par_info,local) \
1926 {                                                       \
1927   if (SHOULD_SPARK(node)) {                             \
1928     SaveAllStgRegs();                                   \
1929     { sparkq result;                                            \
1930       result = NewSpark((P_)node,identifier,gran_info,size_info,par_info,local);\
1931       add_to_spark_queue(result);                               \
1932       GranSimSpark(local,(P_)node);                                     \
1933       context_switch = 1;                               \
1934     }                                                   \
1935     RestoreAllStgRegs();                                \
1936   } else if (do_qp_prof) {                              \
1937     I_ tid = threadId++;                                \
1938     SAFESTGCALL2(void,(I_, P_),QP_Event0,tid,node);     \
1939   }                                                     \
1940   r = 1; /* return code for successful spark -- HWL */  \
1941 }
1942
1943 #else
1944
1945 #define PARZh(r,node,rest,identifier,gran_info,size_info,par_info,local) \
1946 {                                                       \
1947   sparkq result;                                                \
1948   if (SHOULD_SPARK(node)) {                             \
1949     result = NewSpark((P_)node,identifier,gran_info,size_info,par_info,local);\
1950     ADD_TO_SPARK_QUEUE(result);                         \
1951     SAFESTGCALL2(void,(W_),GranSimSpark,local,(P_)node);        \
1952     /* context_switch = 1;  not needed any more -- HWL */       \
1953   } else if (do_qp_prof) {                              \
1954     I_ tid = threadId++;                                \
1955     SAFESTGCALL2(void,(I_, P_),QP_Event0,tid,node);     \
1956   }                                                     \
1957   r = 1; /* return code for successful spark -- HWL */  \
1958 }
1959
1960 #endif 
1961
1962 #define copyableZh(r,node)                              \
1963   /* copyable not yet implemented!! */
1964
1965 #define noFollowZh(r,node)                              \
1966   /* noFollow not yet implemented!! */
1967
1968 #else  /* !GRAN */
1969
1970 extern I_ required_thread_count;
1971
1972 #ifdef PAR
1973 #define COUNT_SPARK     TSO_GLOBALSPARKS(CurrentTSO)++
1974 #else
1975 #define COUNT_SPARK
1976 #endif
1977
1978 /* 
1979    Note that we must bump the required thread count NOW, rather
1980    than when the thread is actually created.  
1981  */
1982
1983 #define forkZh(r,liveness,node)                         \
1984 {                                                       \
1985   while (PendingSparksTl[REQUIRED_POOL] == PendingSparksLim[REQUIRED_POOL]) \
1986     DO_YIELD((liveness << 1) | 1);                      \
1987   COUNT_SPARK;                                          \
1988   if (SHOULD_SPARK(node)) {                             \
1989     *PendingSparksTl[REQUIRED_POOL]++ = (P_)(node);     \
1990   } else if (DO_QP_PROF) {                              \
1991     I_ tid = threadId++;                                \
1992     SAFESTGCALL2(void,(I_, P_),QP_Event0,tid,node);     \
1993   }                                                     \
1994   required_thread_count++;                              \
1995   context_switch = 1;                                   \
1996   r = 1; /* Should not be necessary */                  \
1997 }
1998
1999 #define parZh(r,node)                                   \
2000 {                                                       \
2001   COUNT_SPARK;                                          \
2002   if (SHOULD_SPARK(node) &&                             \
2003    PendingSparksTl[ADVISORY_POOL] < PendingSparksLim[ADVISORY_POOL]) {  \
2004     *PendingSparksTl[ADVISORY_POOL]++ = (P_)(node);     \
2005   } else {                                              \
2006     sparksIgnored++;                                    \
2007     if (DO_QP_PROF) {                                   \
2008       I_ tid = threadId++;                              \
2009       SAFESTGCALL2(void,(I_, P_),QP_Event0,tid,node);   \
2010     }                                                   \
2011   }                                                     \
2012   r = 1; /* Should not be necessary */                  \
2013 }
2014
2015 #endif  /* GRAN */ 
2016 \end{code}
2017
2018 The following seq# code should only be used in unoptimized code.
2019 Be warned: it's a potential bug-farm.
2020
2021 First we push two words on the B stack: the current value of RetReg 
2022 (which may or may not be live), and a continuation snatched largely out
2023 of thin air (it's a point within this code block).  Then we set RetReg
2024 to the special polymorphic return code for seq, load up Node with the
2025 closure to be evaluated, and we're off.  When the eval returns to the
2026 polymorphic seq return point, the two words are popped off the B stack,
2027 RetReg is restored, and we jump to the continuation, completing the
2028 primop and going on our merry way.
2029
2030 \begin{code}
2031
2032 ED_RO_(vtbl_seq);
2033
2034 #define seqZh(r,liveness,node)              \
2035   ({                                        \
2036     __label__ cont;                         \
2037     /* STK_CHK(liveness,0,2,0,0,0,0); */    \
2038     /* SpB -= BREL(2); */                   \
2039     SpB[BREL(0)] = (W_) RetReg;             \
2040     SpB[BREL(1)] = (W_) &&cont;             \
2041     RetReg = (StgRetAddr) vtbl_seq;         \
2042     Node = node;                            \
2043     ENT_VIA_NODE();                         \
2044     InfoPtr = (D_)(INFO_PTR(Node));         \
2045     JMP_(ENTRY_CODE(InfoPtr));              \
2046     cont:                                   \
2047     r = 1; /* Should be unnecessary */      \
2048   })
2049
2050 #endif  /* CONCURRENT */
2051 \end{code}
2052
2053 %************************************************************************
2054 %*                                                                      *
2055 \subsubsection[StgMacros-foreign-objects]{Foreign Objects}
2056 %*                                                                      *
2057 %************************************************************************
2058
2059 [Based on previous MallocPtr comments -- SOF]
2060
2061 This macro is used to construct a ForeignObj on the heap.
2062
2063 What this does is plug the pointer (which will be in a local
2064 variable) together with its finalising/free routine, into a fresh heap
2065 object and then sets a result (which will be a register) to point
2066 to the fresh heap object.
2067
2068 To accommodate per-object finalisation, augment the macro with a
2069 finalisation routine argument. Nothing spectacular, just plug the
2070 pointer to the routine into the ForeignObj -- SOF 4/96
2071
2072 Question: what's this "SET_ACTIVITY" stuff - should I be doing this
2073 too?  (It's if you want to use the SPAT profiling tools to
2074 characterize program behavior by ``activity'' -- tail-calling,
2075 heap-checking, etc. -- see Ticky.lh.  It is quite specialized.
2076 WDP 95/1)
2077
2078 (Swapped first two arguments to make it come into line with what appears
2079 to be `standard' format, return register then liveness mask. -- SOF 4/96)
2080
2081 \begin{code}
2082 #ifndef PAR
2083
2084 StgInt eqForeignObj PROTO((StgForeignObj p1, StgForeignObj p2));
2085
2086 #define makeForeignObjZh(r, liveness, mptr, finalise)    \
2087 do {                                                     \
2088   P_ result;                                             \
2089                                                          \
2090   HEAP_CHK((W_)liveness, _FHS + ForeignObj_SIZE,0);              \
2091   CC_ALLOC(CCC,_FHS + ForeignObj_SIZE,ForeignObj_K); /* cc prof */   \
2092                                                                    \
2093   result = Hp + 1 - (_FHS + ForeignObj_SIZE);                      \
2094   SET_ForeignObj_HDR(result,ForeignObj_info,CCC,_FHS + ForeignObj_SIZE,0); \
2095   ForeignObj_CLOSURE_DATA(result)      = (P_)mptr;                 \
2096   ForeignObj_CLOSURE_FINALISER(result) = (P_)finalise;             \
2097   ForeignObj_CLOSURE_LINK(result) = StorageMgrInfo.ForeignObjList; \
2098   StorageMgrInfo.ForeignObjList = result;                          \
2099                                                         \
2100                                                         \
2101  /*fprintf(stderr,"DEBUG: ForeignObj(0x%x) = <0x%x, 0x%x, 0x%x, 0x%x>\n",       \
2102       result,                                           \
2103       result[0],result[1],                              \
2104       result[2],result[3]);*/                           \
2105                                                         \
2106   CHECK_ForeignObj_CLOSURE( result );                   \
2107   VALIDATE_ForeignObjList( StorageMgrInfo.ForeignObjList ); \
2108                                                         \
2109   (r) = (P_) result;                                    \
2110 } while (0)
2111
2112 #define writeForeignObjZh(res,datum)    ((PP_) ForeignObj_CLOSURE_DATA(res)) = ((P_)datum)
2113
2114 #else
2115 #define makeForeignObjZh(r, liveness, mptr, finalise)               \
2116 do {                                                                \
2117     fflush(stdout);                                                 \
2118     fprintf(stderr, "makeForeignObj#: no foreign object support.\n");\
2119     EXIT(EXIT_FAILURE);                                             \
2120 } while(0)
2121
2122 #define writeForeignObjZh(res,datum)    \
2123 do {                                                                \
2124     fflush(stdout);                                                 \
2125     fprintf(stderr, "writeForeignObj#: no foreign object support.\n");\
2126     EXIT(EXIT_FAILURE);                                             \
2127 } while(0)
2128
2129 #endif /* !PAR */
2130 \end{code}
2131
2132
2133 End-of-file's multi-slurp protection:
2134 \begin{code}
2135 #endif /* ! STGMACROS_H */
2136 \end{code}