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