mirrored from https://gitlab.haskell.org/ghc/ghc.git
/
PrimOps.h
750 lines (612 loc) · 26.1 KB
/
PrimOps.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
/* -----------------------------------------------------------------------------
* $Id: PrimOps.h,v 1.9 1999/01/23 17:48:23 sof Exp $
*
* Macros for primitive operations in STG-ish C code.
*
* ---------------------------------------------------------------------------*/
#ifndef PRIMOPS_H
#define PRIMOPS_H
/* -----------------------------------------------------------------------------
Comparison PrimOps.
-------------------------------------------------------------------------- */
#define gtCharZh(r,a,b) r=(I_)((a)> (b))
#define geCharZh(r,a,b) r=(I_)((a)>=(b))
#define eqCharZh(r,a,b) r=(I_)((a)==(b))
#define neCharZh(r,a,b) r=(I_)((a)!=(b))
#define ltCharZh(r,a,b) r=(I_)((a)< (b))
#define leCharZh(r,a,b) r=(I_)((a)<=(b))
/* Int comparisons: >#, >=# etc */
#define ZgZh(r,a,b) r=(I_)((I_)(a) >(I_)(b))
#define ZgZeZh(r,a,b) r=(I_)((I_)(a)>=(I_)(b))
#define ZeZeZh(r,a,b) r=(I_)((I_)(a)==(I_)(b))
#define ZdZeZh(r,a,b) r=(I_)((I_)(a)!=(I_)(b))
#define ZlZh(r,a,b) r=(I_)((I_)(a) <(I_)(b))
#define ZlZeZh(r,a,b) r=(I_)((I_)(a)<=(I_)(b))
#define gtWordZh(r,a,b) r=(I_)((W_)(a) >(W_)(b))
#define geWordZh(r,a,b) r=(I_)((W_)(a)>=(W_)(b))
#define eqWordZh(r,a,b) r=(I_)((W_)(a)==(W_)(b))
#define neWordZh(r,a,b) r=(I_)((W_)(a)!=(W_)(b))
#define ltWordZh(r,a,b) r=(I_)((W_)(a) <(W_)(b))
#define leWordZh(r,a,b) r=(I_)((W_)(a)<=(W_)(b))
#define gtAddrZh(r,a,b) r=(I_)((a) >(b))
#define geAddrZh(r,a,b) r=(I_)((a)>=(b))
#define eqAddrZh(r,a,b) r=(I_)((a)==(b))
#define neAddrZh(r,a,b) r=(I_)((a)!=(b))
#define ltAddrZh(r,a,b) r=(I_)((a) <(b))
#define leAddrZh(r,a,b) r=(I_)((a)<=(b))
#define gtFloatZh(r,a,b) r=(I_)((a)> (b))
#define geFloatZh(r,a,b) r=(I_)((a)>=(b))
#define eqFloatZh(r,a,b) r=(I_)((a)==(b))
#define neFloatZh(r,a,b) r=(I_)((a)!=(b))
#define ltFloatZh(r,a,b) r=(I_)((a)< (b))
#define leFloatZh(r,a,b) r=(I_)((a)<=(b))
/* Double comparisons: >##, >=#@ etc */
#define ZgZhZh(r,a,b) r=(I_)((a) >(b))
#define ZgZeZhZh(r,a,b) r=(I_)((a)>=(b))
#define ZeZeZhZh(r,a,b) r=(I_)((a)==(b))
#define ZdZeZhZh(r,a,b) r=(I_)((a)!=(b))
#define ZlZhZh(r,a,b) r=(I_)((a) <(b))
#define ZlZeZhZh(r,a,b) r=(I_)((a)<=(b))
/* used by returning comparison primops, defined in Prims.hc. */
extern const StgClosure *PrelBase_Bool_closure_tbl[];
/* -----------------------------------------------------------------------------
Char# PrimOps.
-------------------------------------------------------------------------- */
#define ordZh(r,a) r=(I_)((W_) (a))
#define chrZh(r,a) r=(StgChar)((W_)(a))
/* -----------------------------------------------------------------------------
Int# PrimOps.
-------------------------------------------------------------------------- */
I_ stg_div (I_ a, I_ b);
#define ZpZh(r,a,b) r=(a)+(b)
#define ZmZh(r,a,b) r=(a)-(b)
#define ZtZh(r,a,b) r=(a)*(b)
#define quotIntZh(r,a,b) r=(a)/(b)
#define ZdZh(r,a,b) r=ULTRASAFESTGCALL2(I_,(void *, I_, I_),stg_div,(a),(b))
#define remIntZh(r,a,b) r=(a)%(b)
#define negateIntZh(r,a) r=-(a)
/* The following operations are the standard add,subtract and multiply
* except that they return a carry if the operation overflows.
*
* They are all defined in terms of 32-bit integers and use the GCC
* 'long long' extension to get a 64-bit result. We'd like to use
* 64-bit integers on 64-bit architectures, but it seems that gcc's
* 'long long' type is set at 64-bits even on a 64-bit machine.
*/
#ifdef WORDS_BIGENDIAN
#define C 0
#define R 1
#else
#define C 1
#define R 0
#endif
typedef union {
StgInt64 l;
StgInt32 i[2];
} long_long_u ;
#define addWithCarryZh(r,c,a,b) \
{ long_long_u z; \
z.l = a + b; \
r = z.i[R]; \
c = z.i[C]; \
}
#define subWithCarryZh(r,c,a,b) \
{ long_long_u z; \
z.l = a + b; \
r = z.i[R]; \
c = z.i[C]; \
}
#define mulWithCarryZh(r,c,a,b) \
{ long_long_u z; \
z.l = a * b; \
r = z.i[R]; \
c = z.i[C]; \
}
/* -----------------------------------------------------------------------------
Word PrimOps.
-------------------------------------------------------------------------- */
#define quotWordZh(r,a,b) r=((W_)a)/((W_)b)
#define remWordZh(r,a,b) r=((W_)a)%((W_)b)
#define andZh(r,a,b) r=(a)&(b)
#define orZh(r,a,b) r=(a)|(b)
#define xorZh(r,a,b) r=(a)^(b)
#define notZh(r,a) r=~(a)
#define shiftLZh(r,a,b) r=(a)<<(b)
#define shiftRLZh(r,a,b) r=(a)>>(b)
#define iShiftLZh(r,a,b) r=(a)<<(b)
/* Right shifting of signed quantities is not portable in C, so
the behaviour you'll get from using these primops depends
on the whatever your C compiler is doing. ToDo: fix/document. -- sof 8/98
*/
#define iShiftRAZh(r,a,b) r=(a)>>(b)
#define iShiftRLZh(r,a,b) r=(a)>>(b)
#define int2WordZh(r,a) r=(W_)(a)
#define word2IntZh(r,a) r=(I_)(a)
/* -----------------------------------------------------------------------------
Addr PrimOps.
-------------------------------------------------------------------------- */
#define int2AddrZh(r,a) r=(A_)(a)
#define addr2IntZh(r,a) r=(I_)(a)
#define indexCharOffAddrZh(r,a,i) r= ((C_ *)(a))[i]
#define indexIntOffAddrZh(r,a,i) r= ((I_ *)(a))[i]
#define indexAddrOffAddrZh(r,a,i) r= ((PP_)(a))[i]
#define indexFloatOffAddrZh(r,a,i) r= PK_FLT((P_) (((StgFloat *)(a)) + i))
#define indexDoubleOffAddrZh(r,a,i) r= PK_DBL((P_) (((StgDouble *)(a)) + i))
#define indexStablePtrOffAddrZh(r,a,i) r= ((StgStablePtr *)(a))[i]
#ifdef SUPPORT_LONG_LONGS
#define indexInt64OffAddrZh(r,a,i) r= ((LI_ *)(a))[i]
#define indexWord64OffAddrZh(r,a,i) r= ((LW_ *)(a))[i]
#endif
#define writeCharOffAddrZh(a,i,v) ((C_ *)(a))[i] = (v)
#define writeIntOffAddrZh(a,i,v) ((I_ *)(a))[i] = (v)
#define writeWordOffAddrZh(a,i,v) ((W_ *)(a))[i] = (v)
#define writeAddrOffAddrZh(a,i,v) ((PP_)(a))[i] = (v)
#define writeForeignObjOffAddrZh(a,i,v) ((PP_)(a))[i] = ForeignObj_CLOSURE_DATA(v)
#define writeFloatOffAddrZh(a,i,v) ASSIGN_FLT((P_) (((StgFloat *)(a)) + i),v)
#define writeDoubleOffAddrZh(a,i,v) ASSIGN_DBL((P_) (((StgDouble *)(a)) + i),v)
#define writeStablePtrOffAddrZh(a,i,v) ((StgStablePtr *)(a))[i] = (v)
#ifdef SUPPORT_LONG_LONGS
#define writeInt64OffAddrZh(a,i,v) ((LI_ *)(a))[i] = (v)
#define writeWord64OffAddrZh(a,i,v) ((LW_ *)(a))[i] = (v)
#endif
/* -----------------------------------------------------------------------------
Float PrimOps.
-------------------------------------------------------------------------- */
#define plusFloatZh(r,a,b) r=(a)+(b)
#define minusFloatZh(r,a,b) r=(a)-(b)
#define timesFloatZh(r,a,b) r=(a)*(b)
#define divideFloatZh(r,a,b) r=(a)/(b)
#define negateFloatZh(r,a) r=-(a)
#define int2FloatZh(r,a) r=(StgFloat)(a)
#define float2IntZh(r,a) r=(I_)(a)
#define expFloatZh(r,a) r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,exp,a)
#define logFloatZh(r,a) r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,log,a)
#define sqrtFloatZh(r,a) r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,sqrt,a)
#define sinFloatZh(r,a) r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,sin,a)
#define cosFloatZh(r,a) r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,cos,a)
#define tanFloatZh(r,a) r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,tan,a)
#define asinFloatZh(r,a) r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,asin,a)
#define acosFloatZh(r,a) r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,acos,a)
#define atanFloatZh(r,a) r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,atan,a)
#define sinhFloatZh(r,a) r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,sinh,a)
#define coshFloatZh(r,a) r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,cosh,a)
#define tanhFloatZh(r,a) r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,tanh,a)
#define powerFloatZh(r,a,b) r=(StgFloat) RET_PRIM_STGCALL2(StgDouble,pow,a,b)
/* -----------------------------------------------------------------------------
Double PrimOps.
-------------------------------------------------------------------------- */
#define ZpZhZh(r,a,b) r=(a)+(b)
#define ZmZhZh(r,a,b) r=(a)-(b)
#define ZtZhZh(r,a,b) r=(a)*(b)
#define ZdZhZh(r,a,b) r=(a)/(b)
#define negateDoubleZh(r,a) r=-(a)
#define int2DoubleZh(r,a) r=(StgDouble)(a)
#define double2IntZh(r,a) r=(I_)(a)
#define float2DoubleZh(r,a) r=(StgDouble)(a)
#define double2FloatZh(r,a) r=(StgFloat)(a)
#define expDoubleZh(r,a) r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,exp,a)
#define logDoubleZh(r,a) r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,log,a)
#define sqrtDoubleZh(r,a) r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,sqrt,a)
#define sinDoubleZh(r,a) r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,sin,a)
#define cosDoubleZh(r,a) r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,cos,a)
#define tanDoubleZh(r,a) r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,tan,a)
#define asinDoubleZh(r,a) r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,asin,a)
#define acosDoubleZh(r,a) r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,acos,a)
#define atanDoubleZh(r,a) r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,atan,a)
#define sinhDoubleZh(r,a) r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,sinh,a)
#define coshDoubleZh(r,a) r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,cosh,a)
#define tanhDoubleZh(r,a) r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,tanh,a)
/* Power: **## */
#define ZtZtZhZh(r,a,b) r=(StgDouble) RET_PRIM_STGCALL2(StgDouble,pow,a,b)
/* -----------------------------------------------------------------------------
Integer PrimOps.
-------------------------------------------------------------------------- */
/* We can do integer2Int and cmpInteger inline, since they don't need
* to allocate any memory.
*/
#define integer2IntZh(r, aa,sa,da) \
{ MP_INT arg; \
\
arg._mp_alloc = (aa); \
arg._mp_size = (sa); \
arg._mp_d = (unsigned long int *) (BYTE_ARR_CTS(da)); \
\
(r) = RET_PRIM_STGCALL1(I_,mpz_get_si,&arg); \
}
#define integer2WordZh(r, aa,sa,da) \
{ MP_INT arg; \
\
arg._mp_alloc = (aa); \
arg._mp_size = (sa); \
arg._mp_d = (unsigned long int *) (BYTE_ARR_CTS(da)); \
\
(r) = RET_PRIM_STGCALL1(I_,mpz_get_ui,&arg); \
}
#define cmpIntegerZh(r, a1,s1,d1, a2,s2,d2) \
{ MP_INT arg1; \
MP_INT arg2; \
\
arg1._mp_alloc= (a1); \
arg1._mp_size = (s1); \
arg1._mp_d = (unsigned long int *) (BYTE_ARR_CTS(d1)); \
arg2._mp_alloc= (a2); \
arg2._mp_size = (s2); \
arg2._mp_d = (unsigned long int *) (BYTE_ARR_CTS(d2)); \
\
(r) = RET_PRIM_STGCALL2(I_,mpz_cmp,&arg1,&arg2); \
}
/* A glorious hack: calling mpz_neg would entail allocation and
* copying, but by looking at what mpz_neg actually does, we can
* derive a better version:
*/
#define negateIntegerZh(ra, rs, rd, a, s, d) \
{ \
(ra) = (a); \
(rs) = -(s); \
(rd) = d; \
}
/* The rest are all out-of-line: -------- */
/* Integer arithmetic */
EF_(plusIntegerZh_fast);
EF_(minusIntegerZh_fast);
EF_(timesIntegerZh_fast);
EF_(gcdIntegerZh_fast);
EF_(quotRemIntegerZh_fast);
EF_(divModIntegerZh_fast);
/* Conversions */
EF_(int2IntegerZh_fast);
EF_(word2IntegerZh_fast);
EF_(addr2IntegerZh_fast);
/* Floating-point encodings/decodings */
EF_(encodeFloatZh_fast);
EF_(decodeFloatZh_fast);
EF_(encodeDoubleZh_fast);
EF_(decodeDoubleZh_fast);
/* -----------------------------------------------------------------------------
Word64 PrimOps.
-------------------------------------------------------------------------- */
#ifdef SUPPORT_LONG_LONGS
#define integerToWord64Zh(r, aa,sa,da) \
{ unsigned long int* d; \
StgNat64 res; \
\
d = (unsigned long int *) (BYTE_ARR_CTS(da)); \
if ( (aa) == 0 ) { \
res = (LW_)0; \
} else if ( (aa) == 1) { \
res = (LW_)d[0]; \
} else { \
res = (LW_)d[0] + (LW_)d[1] * 0x100000000ULL; \
} \
(r) = res; \
}
#define integerToInt64Zh(r, aa,sa,da) \
{ unsigned long int* d; \
StgInt64 res; \
\
d = (unsigned long int *) (BYTE_ARR_CTS(da)); \
if ( (aa) == 0 ) { \
res = (LI_)0; \
} else if ( (aa) == 1) { \
res = (LI_)d[0]; \
} else { \
res = (LI_)d[0] + (LI_)d[1] * 0x100000000LL; \
if ( sa < 0 ) { \
res = (LI_)-res; \
} \
} \
(r) = res; \
}
/* Conversions */
EF_(int64ToIntegerZh_fast);
EF_(word64ToIntegerZh_fast);
/* The rest are (way!) out of line, implemented via C entry points.
*/
I_ stg_gtWord64 (StgNat64, StgNat64);
I_ stg_geWord64 (StgNat64, StgNat64);
I_ stg_eqWord64 (StgNat64, StgNat64);
I_ stg_neWord64 (StgNat64, StgNat64);
I_ stg_ltWord64 (StgNat64, StgNat64);
I_ stg_leWord64 (StgNat64, StgNat64);
I_ stg_gtInt64 (StgInt64, StgInt64);
I_ stg_geInt64 (StgInt64, StgInt64);
I_ stg_eqInt64 (StgInt64, StgInt64);
I_ stg_neInt64 (StgInt64, StgInt64);
I_ stg_ltInt64 (StgInt64, StgInt64);
I_ stg_leInt64 (StgInt64, StgInt64);
LW_ stg_remWord64 (StgNat64, StgNat64);
LW_ stg_quotWord64 (StgNat64, StgNat64);
LI_ stg_remInt64 (StgInt64, StgInt64);
LI_ stg_quotInt64 (StgInt64, StgInt64);
LI_ stg_negateInt64 (StgInt64);
LI_ stg_plusInt64 (StgInt64, StgInt64);
LI_ stg_minusInt64 (StgInt64, StgInt64);
LI_ stg_timesInt64 (StgInt64, StgInt64);
LW_ stg_and64 (StgNat64, StgNat64);
LW_ stg_or64 (StgNat64, StgNat64);
LW_ stg_xor64 (StgNat64, StgNat64);
LW_ stg_not64 (StgNat64);
LW_ stg_shiftL64 (StgNat64, StgInt);
LW_ stg_shiftRL64 (StgNat64, StgInt);
LI_ stg_iShiftL64 (StgInt64, StgInt);
LI_ stg_iShiftRL64 (StgInt64, StgInt);
LI_ stg_iShiftRA64 (StgInt64, StgInt);
LI_ stg_intToInt64 (StgInt);
I_ stg_int64ToInt (StgInt64);
LW_ stg_int64ToWord64 (StgInt64);
LW_ stg_wordToWord64 (StgWord);
W_ stg_word64ToWord (StgNat64);
LI_ stg_word64ToInt64 (StgNat64);
#endif
/* -----------------------------------------------------------------------------
Array PrimOps.
-------------------------------------------------------------------------- */
/* We cast to void* instead of StgChar* because this avoids a warning
* about increasing the alignment requirements.
*/
#define REAL_BYTE_ARR_CTS(a) ((void *) (((StgArrWords *)(a))->payload))
#define REAL_PTRS_ARR_CTS(a) ((P_) (((StgMutArrPtrs *)(a))->payload))
#ifdef DEBUG
#define BYTE_ARR_CTS(a) \
({ ASSERT((GET_INFO(a) == &ARR_WORDS_info) \
|| (GET_INFO(a) == &MUT_ARR_WORDS_info)); \
REAL_BYTE_ARR_CTS(a); })
#define PTRS_ARR_CTS(a) \
({ ASSERT((GET_INFO(a) == &ARR_PTRS_info) \
|| (GET_INFO(a) == &MUT_ARR_PTRS_info)); \
REAL_PTRS_ARR_CTS(a); })
#else
#define BYTE_ARR_CTS(a) REAL_BYTE_ARR_CTS(a)
#define PTRS_ARR_CTS(a) REAL_PTRS_ARR_CTS(a)
#endif
extern I_ genSymZh(void);
extern I_ resetGenSymZh(void);
/*--- everything except new*Array is done inline: */
#define sameMutableArrayZh(r,a,b) r=(I_)((a)==(b))
#define sameMutableByteArrayZh(r,a,b) r=(I_)((a)==(b))
#define readArrayZh(r,a,i) r=((PP_) PTRS_ARR_CTS(a))[(i)]
#define readCharArrayZh(r,a,i) indexCharOffAddrZh(r,BYTE_ARR_CTS(a),i)
#define readIntArrayZh(r,a,i) indexIntOffAddrZh(r,BYTE_ARR_CTS(a),i)
#define readWordArrayZh(r,a,i) indexWordOffAddrZh(r,BYTE_ARR_CTS(a),i)
#define readAddrArrayZh(r,a,i) indexAddrOffAddrZh(r,BYTE_ARR_CTS(a),i)
#define readFloatArrayZh(r,a,i) indexFloatOffAddrZh(r,BYTE_ARR_CTS(a),i)
#define readDoubleArrayZh(r,a,i) indexDoubleOffAddrZh(r,BYTE_ARR_CTS(a),i)
#define readStablePtrArrayZh(r,a,i) indexStablePtrOffAddrZh(r,BYTE_ARR_CTS(a),i)
#ifdef SUPPORT_LONG_LONGS
#define readInt64ArrayZh(r,a,i) indexInt64OffAddrZh(r,BYTE_ARR_CTS(a),i)
#define readWord64ArrayZh(r,a,i) indexWord64OffAddrZh(r,BYTE_ARR_CTS(a),i)
#endif
/* result ("r") arg ignored in write macros! */
#define writeArrayZh(a,i,v) ((PP_) PTRS_ARR_CTS(a))[(i)]=(v)
#define writeCharArrayZh(a,i,v) ((C_ *)(BYTE_ARR_CTS(a)))[i] = (v)
#define writeIntArrayZh(a,i,v) ((I_ *)(BYTE_ARR_CTS(a)))[i] = (v)
#define writeWordArrayZh(a,i,v) ((W_ *)(BYTE_ARR_CTS(a)))[i] = (v)
#define writeAddrArrayZh(a,i,v) ((PP_)(BYTE_ARR_CTS(a)))[i] = (v)
#define writeFloatArrayZh(a,i,v) \
ASSIGN_FLT((P_) (((StgFloat *)(BYTE_ARR_CTS(a))) + i),v)
#define writeDoubleArrayZh(a,i,v) \
ASSIGN_DBL((P_) (((StgDouble *)(BYTE_ARR_CTS(a))) + i),v)
#define writeStablePtrArrayZh(a,i,v) ((StgStablePtr *)(BYTE_ARR_CTS(a)))[i] = (v)
#ifdef SUPPORT_LONG_LONGS
#define writeInt64ArrayZh(a,i,v) ((LI_ *)(BYTE_ARR_CTS(a)))[i] = (v)
#define writeWord64ArrayZh(a,i,v) ((LW_ *)(BYTE_ARR_CTS(a)))[i] = (v)
#endif
#define indexArrayZh(r,a,i) r=((PP_) PTRS_ARR_CTS(a))[(i)]
#define indexCharArrayZh(r,a,i) indexCharOffAddrZh(r,BYTE_ARR_CTS(a),i)
#define indexIntArrayZh(r,a,i) indexIntOffAddrZh(r,BYTE_ARR_CTS(a),i)
#define indexWordArrayZh(r,a,i) indexWordOffAddrZh(r,BYTE_ARR_CTS(a),i)
#define indexAddrArrayZh(r,a,i) indexAddrOffAddrZh(r,BYTE_ARR_CTS(a),i)
#define indexFloatArrayZh(r,a,i) indexFloatOffAddrZh(r,BYTE_ARR_CTS(a),i)
#define indexDoubleArrayZh(r,a,i) indexDoubleOffAddrZh(r,BYTE_ARR_CTS(a),i)
#define indexStablePtrArrayZh(r,a,i) indexStablePtrOffAddrZh(r,BYTE_ARR_CTS(a),i)
#ifdef SUPPORT_LONG_LONGS
#define indexInt64ArrayZh(r,a,i) indexInt64OffAddrZh(r,BYTE_ARR_CTS(a),i)
#define indexWord64ArrayZh(r,a,i) indexWord64OffAddrZh(r,BYTE_ARR_CTS(a),i)
#endif
#define indexCharOffForeignObjZh(r,fo,i) indexCharOffAddrZh(r,ForeignObj_CLOSURE_DATA(fo),i)
#define indexIntOffForeignObjZh(r,fo,i) indexIntOffAddrZh(r,ForeignObj_CLOSURE_DATA(fo),i)
#define indexWordOffForeignObjZh(r,fo,i) indexWordOffAddrZh(r,ForeignObj_CLOSURE_DATA(fo),i)
#define indexAddrOffForeignObjZh(r,fo,i) indexAddrOffAddrZh(r,ForeignObj_CLOSURE_DATA(fo),i)
#define indexFloatOffForeignObjZh(r,fo,i) indexFloatOffAddrZh(r,ForeignObj_CLOSURE_DATA(fo),i)
#define indexDoubleOffForeignObjZh(r,fo,i) indexDoubleOffAddrZh(r,ForeignObj_CLOSURE_DATA(fo),i)
#define indexStablePtrOffForeignObjZh(r,fo,i) indexStablePtrOffAddrZh(r,ForeignObj_CLOSURE_DATA(fo),i)
#ifdef SUPPORT_LONG_LONGS
#define indexInt64OffForeignObjZh(r,fo,i) indexInt64OffAddrZh(r,ForeignObj_CLOSURE_DATA(fo),i)
#define indexWord64OffForeignObjZh(r,fo,i) indexWord64OffAddrZh(r,ForeignObj_CLOSURE_DATA(fo),i)
#endif
#define indexCharOffAddrZh(r,a,i) r= ((C_ *)(a))[i]
#define indexIntOffAddrZh(r,a,i) r= ((I_ *)(a))[i]
#define indexWordOffAddrZh(r,a,i) r= ((W_ *)(a))[i]
#define indexAddrOffAddrZh(r,a,i) r= ((PP_)(a))[i]
#define indexFloatOffAddrZh(r,a,i) r= PK_FLT((P_) (((StgFloat *)(a)) + i))
#define indexDoubleOffAddrZh(r,a,i) r= PK_DBL((P_) (((StgDouble *)(a)) + i))
#ifdef SUPPORT_LONG_LONGS
#define indexInt64OffAddrZh(r,a,i) r= ((LI_ *)(a))[i]
#define indexWord64OffAddrZh(r,a,i) r= ((LW_ *)(a))[i]
#endif
/* Freezing arrays-of-ptrs requires changing an info table, for the
benefit of the generational collector. It needs to scavenge mutable
objects, even if they are in old space. When they become immutable,
they can be removed from this scavenge list. */
#define unsafeFreezeArrayZh(r,a) \
{ \
SET_INFO((StgClosure *)a,&MUT_ARR_PTRS_FROZEN_info); \
r = a; \
}
#define unsafeFreezeByteArrayZh(r,a) r=(a)
#define sizeofByteArrayZh(r,a) \
r = (((StgArrWords *)(a))->words * sizeof(W_))
#define sizeofMutableByteArrayZh(r,a) \
r = (((StgArrWords *)(a))->words * sizeof(W_))
/* and the out-of-line ones... */
EF_(newCharArrayZh_fast);
EF_(newIntArrayZh_fast);
EF_(newWordArrayZh_fast);
EF_(newAddrArrayZh_fast);
EF_(newFloatArrayZh_fast);
EF_(newDoubleArrayZh_fast);
EF_(newStablePtrArrayZh_fast);
EF_(newArrayZh_fast);
/* encoding and decoding of floats/doubles. */
/* We only support IEEE floating point format */
#include "ieee-flpt.h"
#if FLOATS_AS_DOUBLES /* i.e. 64-bit machines */
#define encodeFloatZh(r, aa,sa,da, expon) encodeDoubleZh(r, aa,sa,da, expon)
#else
#define encodeFloatZh(r, aa,sa,da, expon) \
{ MP_INT arg; \
/* Does not allocate memory */ \
\
arg._mp_alloc = aa; \
arg._mp_size = sa; \
arg._mp_d = (unsigned long int *) (BYTE_ARR_CTS(da)); \
\
r = RET_PRIM_STGCALL2(StgFloat, __encodeFloat,&arg,(expon));\
}
#endif /* FLOATS_AS_DOUBLES */
#define encodeDoubleZh(r, aa,sa,da, expon) \
{ MP_INT arg; \
/* Does not allocate memory */ \
\
arg._mp_alloc = aa; \
arg._mp_size = sa; \
arg._mp_d = (unsigned long int *) (BYTE_ARR_CTS(da)); \
\
r = RET_PRIM_STGCALL2(StgDouble, __encodeDouble,&arg,(expon));\
}
/* The decode operations are out-of-line because they need to allocate
* a byte array.
*/
#ifdef FLOATS_AS_DOUBLES
#define decodeFloatZh_fast decodeDoubleZh_fast
#else
EF_(decodeFloatZh_fast);
#endif
EF_(decodeDoubleZh_fast);
/* grimy low-level support functions defined in StgPrimFloat.c */
extern StgDouble __encodeDouble (MP_INT *s, I_ e);
extern StgFloat __encodeFloat (MP_INT *s, I_ e);
extern void __decodeDouble (MP_INT *man, I_ *_exp, StgDouble dbl);
extern void __decodeFloat (MP_INT *man, I_ *_exp, StgFloat flt);
extern StgInt isDoubleNaN(StgDouble d);
extern StgInt isDoubleInfinite(StgDouble d);
extern StgInt isDoubleDenormalized(StgDouble d);
extern StgInt isDoubleNegativeZero(StgDouble d);
extern StgInt isFloatNaN(StgFloat f);
extern StgInt isFloatInfinite(StgFloat f);
extern StgInt isFloatDenormalized(StgFloat f);
extern StgInt isFloatNegativeZero(StgFloat f);
/* -----------------------------------------------------------------------------
Mutable variables
newMutVar is out of line.
-------------------------------------------------------------------------- */
EF_(newMutVarZh_fast);
#define readMutVarZh(r,a) r=(P_)(((StgMutVar *)(a))->var)
#define writeMutVarZh(a,v) (P_)(((StgMutVar *)(a))->var)=(v)
#define sameMutVarZh(r,a,b) r=(I_)((a)==(b))
/* -----------------------------------------------------------------------------
MVar PrimOps.
All out of line, because they either allocate or may block.
-------------------------------------------------------------------------- */
#define sameMVarZh(r,a,b) r=(I_)((a)==(b))
/* Assume external decl of EMPTY_MVAR_info is in scope by now */
#define isEmptyMVarZh(r,a) r=(I_)((GET_INFO((StgMVar*)(a))) == &EMPTY_MVAR_info )
EF_(newMVarZh_fast);
EF_(takeMVarZh_fast);
EF_(putMVarZh_fast);
/* -----------------------------------------------------------------------------
Delay/Wait PrimOps
-------------------------------------------------------------------------- */
/* Hmm, I'll think about these later. */
/* -----------------------------------------------------------------------------
Primitive I/O, error-handling PrimOps
-------------------------------------------------------------------------- */
EF_(catchZh_fast);
EF_(raiseZh_fast);
extern void stg_exit(I_ n) __attribute__ ((noreturn));
/* -----------------------------------------------------------------------------
Stable Pointer PrimOps.
-------------------------------------------------------------------------- */
#ifndef PAR
extern StgPtr *stable_ptr_table;
extern StgPtr *stable_ptr_free;
#define deRefStablePtrZh(r,sp) (r=stable_ptr_table[(sp)])
#define eqStablePtrZh(r,sp1,sp2) (r=(sp1==sp2))
#define freeStablePointer(stable_ptr) \
{ \
stable_ptr_table[stable_ptr] = (P_)stable_ptr_free; \
stable_ptr_free = &stable_ptr_table[stable_ptr]; \
}
EF_(makeStablePtrZh_fast);
#else /* PAR */
#define deRefStablePtrZh(ri,sp) \
do { \
fflush(stdout); \
fprintf(stderr, "deRefStablePtr#: no stable pointer support.\n");\
stg_exit(EXIT_FAILURE); \
} while(0)
#define eqStablePtrZh(ri,sp1,sp2) \
do { \
fflush(stdout); \
fprintf(stderr, "eqStablePtr#: no stable pointer support.\n"); \
stg_exit(EXIT_FAILURE); \
} while(0)
#define makeStablePtrZh(stablePtr,liveness,unstablePtr) \
do { \
fflush(stdout); \
fprintf(stderr, "makeStablePtr#: no stable pointer support.\n");\
EXIT(EXIT_FAILURE); \
} while(0)
#define freeStablePtrZh(stablePtr,liveness,unstablePtr) \
do { \
fflush(stdout); \
fprintf(stderr, "makeStablePtr#: no stable pointer support.\n");\
EXIT(EXIT_FAILURE); \
} while(0)
#endif
/* -----------------------------------------------------------------------------
Parallel PrimOps.
-------------------------------------------------------------------------- */
EF_(forkZh_fast);
EF_(killThreadZh_fast);
EF_(seqZh_fast);
/* Hmm, I'll think about these later. */
/* -----------------------------------------------------------------------------
Pointer equality
-------------------------------------------------------------------------- */
/* warning: extremely non-referentially transparent, need to hide in
an appropriate monad.
ToDo: follow indirections.
*/
#define reallyUnsafePtrEqualityZh(r,a,b) r=((StgPtr)(a) == (StgPtr)(b))
/* -----------------------------------------------------------------------------
Weak Pointer PrimOps.
-------------------------------------------------------------------------- */
#ifndef PAR
EF_(mkWeakZh_fast);
EF_(deRefWeakZh_fast);
#define sameWeakZh(w1,w2) ((w1)==(w2))
#endif
/* -----------------------------------------------------------------------------
Foreign Object PrimOps.
-------------------------------------------------------------------------- */
#ifndef PAR
#define ForeignObj_CLOSURE_DATA(c) (((StgForeignObj *)c)->data)
EF_(makeForeignObjZh_fast);
#define writeForeignObjZh(res,datum) \
(ForeignObj_CLOSURE_DATA(res) = (P_)(datum))
#define eqForeignObj(f1,f2) ((f1)==(f2))
#endif
/* -----------------------------------------------------------------------------
Signal processing. Not really primops, but called directly from
Haskell.
-------------------------------------------------------------------------- */
#define STG_SIG_DFL (-1)
#define STG_SIG_IGN (-2)
#define STG_SIG_ERR (-3)
#define STG_SIG_HAN (-4)
extern StgInt sig_install (StgInt, StgInt, StgStablePtr, sigset_t *);
#define stg_sig_default(sig,mask) sig_install(sig,STG_SIG_DFL,0,(sigset_t *)mask)
#define stg_sig_ignore(sig,mask) sig_install(sig,STG_SIG_IGN,0,(sigset_t *)mask)
#define stg_sig_catch(sig,ptr,mask) sig_install(sig,STG_SIG_HAN,ptr,(sigset_t *)mask)
#endif PRIMOPS_H