2 /* -----------------------------------------------------------------------------
5 * Copyright (c) 1994-1998.
7 * $RCSfile: Evaluator.c,v $
9 * $Date: 1999/04/27 12:27:50 $
10 * ---------------------------------------------------------------------------*/
20 #include "SchedAPI.h" /* for createGenThread */
21 #include "Schedule.h" /* for context_switch */
23 #include "Bytecodes.h"
24 #include "Assembler.h" /* for CFun stuff */
25 #include "ForeignCall.h"
26 #include "StablePriv.h"
27 #include "PrimOps.h" /* for __{encode,decode}{Float,Double} */
28 #include "Evaluator.h"
32 #include "Disassembler.h"
38 #include <math.h> /* These are for primops */
39 #include <limits.h> /* These are for primops */
40 #include <float.h> /* These are for primops */
42 #include <ieee754.h> /* These are for primops */
45 #ifdef STANDALONE_INTEGER
46 #include "sainteger.h"
48 #error Non-standalone integer not yet supported
52 /* An incredibly useful abbreviation.
53 * Interestingly, there are some uses of END_TSO_QUEUE_closure that
54 * can't use it because they use the closure at type StgClosure* or
55 * even StgPtr*. I suspect they should be changed. -- ADR
57 #define EndTSOQueue stgCast(StgTSO*,(void*)&END_TSO_QUEUE_closure)
59 /* These macros are rather delicate - read a good ANSI C book carefully
63 #define mycat(x,y) x##y
64 #define mycat2(x,y) mycat(x,y)
65 #define mycat3(x,y,z) mycat2(x,mycat2(y,z))
67 #if defined(__GNUC__) && !defined(DEBUG)
68 #define USE_GCC_LABELS 1
70 #define USE_GCC_LABELS 0
74 /* --------------------------------------------------------------------------
75 * Crude profiling stuff (mainly to assess effect of optimiser)
76 * ------------------------------------------------------------------------*/
78 #ifdef CRUDE_PROFILING
87 struct { int /*StgVar*/ who;
95 CPRecord cpTab[M_CPTAB];
102 for (i = 0; i < M_CPTAB; i++)
103 cpTab[i].who = CP_NIL;
107 void cp_enter ( StgBCO* b )
111 int /*StgVar*/ v = b->stgexpr;
112 if ((void*)v == NULL) return;
121 h = (-v) % M_CPTAB; else
124 assert (h >= 0 && h < M_CPTAB);
125 while (cpTab[h].who != v && cpTab[h].who != CP_NIL) {
126 h++; if (h == M_CPTAB) h = 0;
129 if (cpTab[cpCurr].who == CP_NIL) {
130 cpTab[cpCurr].who = v;
131 if (!is_ret_cont) cpTab[cpCurr].enters = 1;
132 cpTab[cpCurr].bytes = cpTab[cpCurr].insns = 0;
134 if (cpInUse * 2 > M_CPTAB) {
135 fprintf(stderr, "\nCRUDE_PROFILING hash table is too full\n" );
139 if (!is_ret_cont) cpTab[cpCurr].enters++;
145 void cp_bill_words ( int nw )
147 if (cpCurr == CP_NIL) return;
148 cpTab[cpCurr].bytes += sizeof(StgWord)*nw;
152 void cp_bill_insns ( int ni )
154 if (cpCurr == CP_NIL) return;
155 cpTab[cpCurr].insns += ni;
159 static double percent ( double a, double b )
161 return (100.0 * a) / b;
165 void cp_show ( void )
167 int i, j, max, maxN, totE, totB, totI, cumE, cumB, cumI;
170 if (cpInUse == -1) return;
172 fflush(stdout);fflush(stderr);
175 totE = totB = totI = 0;
176 for (i = 0; i < M_CPTAB; i++) {
177 cpTab[i].twho = cpTab[i].who;
178 if (cpTab[i].who != CP_NIL) {
179 totE += cpTab[i].enters;
180 totB += cpTab[i].bytes;
181 totI += cpTab[i].insns;
186 "%6d (%7.3f M) enters, "
187 "%6d (%7.3f M) insns, "
188 "%6d (%7.3f M) bytes\n\n",
189 totE, totE/1000000.0, totI, totI/1000000.0, totB, totB/1000000.0 );
191 cumE = cumB = cumI = 0;
192 for (j = 0; j < 32; j++) {
195 for (i = 0; i < M_CPTAB; i++)
196 if (cpTab[i].who != CP_NIL &&
197 cpTab[i].enters > maxN) {
198 maxN = cpTab[i].enters;
201 if (max == -1) break;
203 cumE += cpTab[max].enters;
204 cumB += cpTab[max].bytes;
205 cumI += cpTab[max].insns;
207 strcpy(nm, maybeName(cpTab[max].who));
208 if (strcmp(nm, "(unknown)")==0)
209 sprintf ( nm, "id%d", -cpTab[max].who);
211 printf ( "%20s %7d es (%4.1f%%, %4.1f%% c) "
212 "%7d bs (%4.1f%%, %4.1f%% c) "
213 "%7d is (%4.1f%%, %4.1f%% c)\n",
215 cpTab[max].enters, percent(cpTab[max].enters,totE), percent(cumE,totE),
216 cpTab[max].bytes, percent(cpTab[max].bytes,totB), percent(cumB,totB),
217 cpTab[max].insns, percent(cpTab[max].insns,totI), percent(cumI,totI)
220 cpTab[max].twho = cpTab[max].who;
221 cpTab[max].who = CP_NIL;
224 for (i = 0; i < M_CPTAB; i++)
225 cpTab[i].who = cpTab[i].twho;
233 /* --------------------------------------------------------------------------
234 * Hugs Hooks - a bit of a hack
235 * ------------------------------------------------------------------------*/
237 /* A total hack -- this code has an endian dependancy and only works
238 on little-endian archs.
240 void setRtsFlags( int x );
241 void setRtsFlags( int x )
243 *(int*)(&(RtsFlags.DebugFlags)) = x;
246 /* --------------------------------------------------------------------------
249 * ToDo: figure out why these are being used and crush them!
250 * ------------------------------------------------------------------------*/
252 void OnExitHook (void)
255 void StackOverflowHook (unsigned long stack_size)
257 fprintf(stderr,"Stack Overflow\n");
260 void OutOfHeapHook (unsigned long request_size, unsigned long heap_size)
262 fprintf(stderr,"Out Of Heap\n");
265 void MallocFailHook (unsigned long request_size /* in bytes */, char *msg)
267 fprintf(stderr,"Malloc Fail\n");
270 void defaultsHook (void)
276 /* --------------------------------------------------------------------------
277 * Entering-objects and bytecode interpreter part of evaluator
278 * ------------------------------------------------------------------------*/
280 /* The primop (and all other) parts of this evaluator operate upon the
281 machine state which lives in MainRegTable. enter is different:
282 to make its closure- and bytecode-interpreting loops go fast, some of that
283 state is pulled out into local vars (viz, registers, if we are lucky).
284 That means that we need to save(load) the local state at every exit(reentry)
285 into enter. That is, around every procedure call it makes. Blargh!
286 If you modify this code, __be warned__ it will fail in mysterious ways if
287 you fail to preserve this property.
289 Currently the pulled-out state is Sp in xSp, Su in xSu and SpLim in xSpLim.
290 The SSS macros saves the state back in MainRegTable, and LLL loads it from
291 MainRegTable. RETURN(v) does SSS and then returns v; all exits should
292 be via RETURN and not plain return.
294 Since xSp, xSu and xSpLim are local vars in enter, they are not visible
295 in procedures called from enter. To fix this, either (1) turn the
296 procedures into macros, so they get copied inline, or (2) bracket
297 the procedure call with SSS and LLL so that the local and global
298 machine states are synchronised for the duration of the call.
302 /* Forward decls ... */
303 static void* enterBCO_primop1 ( int );
304 static void* enterBCO_primop2 ( int , int* /*StgThreadReturnCode* */ );
305 static inline void PopUpdateFrame ( StgClosure* obj );
306 static inline void PopCatchFrame ( void );
307 static inline void PopSeqFrame ( void );
308 static inline void PopStopFrame( StgClosure* obj );
309 static inline void PushTaggedRealWorld( void );
310 static inline void PushTaggedInteger ( mpz_ptr );
311 static inline StgPtr grabHpUpd( nat size );
312 static inline StgPtr grabHpNonUpd( nat size );
313 static StgClosure* raiseAnError ( StgClosure* errObj );
315 static int enterCountI = 0;
317 #ifdef STANDALONE_INTEGER
318 StgDouble B__encodeDouble (B* s, I_ e);
319 void B__decodeDouble (B* man, I_* exp, StgDouble dbl);
320 #if ! FLOATS_AS_DOUBLES
321 StgFloat B__encodeFloat (B* s, I_ e);
322 void B__decodeFloat (B* man, I_* exp, StgFloat flt);
323 StgPtr CreateByteArrayToHoldInteger ( int );
324 B* IntegerInsideByteArray ( StgPtr );
325 void SloppifyIntegerEnd ( StgPtr );
332 /* Macros to save/load local state. */
334 #define SSS { tSp=Sp = xSp; tSu=Su = xSu; tSpLim=SpLim = xSpLim; }
335 #define LLL { tSp=xSp = Sp; tSu=xSu = Su; tSpLim=xSpLim = SpLim; }
337 #define SSS { Sp = xSp; Su = xSu; SpLim = xSpLim; }
338 #define LLL { xSp = Sp; xSu = Su; xSpLim = SpLim; }
341 #define RETURN(vvv) { StgThreadReturnCode retVal=(vvv); SSS; return retVal; }
344 /* Macros to operate directly on the pulled-out machine state.
345 These mirror some of the small procedures used in the primop code
346 below, except you have to be careful about side effects,
347 ie xPushPtr(xStackPtr(n)) won't work! It certainly isn't the
348 same as PushPtr(StackPtr(n)). Also note that (1) some of
349 the macros, in particular xPopTagged*, do not make the tag
350 sanity checks that their non-x cousins do, and (2) some of
351 the macros depend critically on the semantics of C comma
352 expressions to work properly
354 #define xPushPtr(ppp) { xSp--; *xSp=(StgWord)(ppp); }
355 #define xPopPtr() ((StgPtr)(*xSp++))
357 #define xPushCPtr(ppp) { xSp--; *xSp=(StgWord)(ppp); }
358 #define xPopCPtr() ((StgClosure*)(*xSp++))
360 #define xPushWord(ppp) { xSp--; *xSp=(StgWord)(ppp); }
361 #define xPopWord() ((StgWord)(*xSp++))
363 #define xStackPtr(nnn) ((StgPtr)(*(xSp+(nnn))))
364 #define xStackWord(nnn) ((StgWord)(*(xSp+(nnn))))
365 #define xSetStackWord(iii,www) xSp[iii]=(StgWord)(www)
367 #define xPushTag(ttt) { xSp--; *xSp=(StgWord)(ttt); }
368 #define xPopTag(ttt) { StackTag t = (StackTag)(*xSp++); \
371 #define xPushTaggedInt(xxx) { xSp -= sizeofW(StgInt); \
372 *xSp = (xxx); xPushTag(INT_TAG); }
373 #define xTaggedStackInt(iii) ((StgInt)(*(xSp+1+(iii))))
374 #define xPopTaggedInt() ((xSp++,xSp+=sizeofW(StgInt), \
375 (StgInt)(*(xSp-sizeofW(StgInt)))))
377 #define xPushTaggedWord(xxx) { xSp -= sizeofW(StgWord); \
378 *xSp = (xxx); xPushTag(WORD_TAG); }
379 #define xTaggedStackWord(iii) ((StgWord)(*(xSp+1+(iii))))
380 #define xPopTaggedWord() ((xSp++,xSp+=sizeofW(StgWord), \
381 (StgWord)(*(xSp-sizeofW(StgWord)))))
383 #define xPushTaggedAddr(xxx) { xSp -= sizeofW(StgAddr); \
384 *xSp = (StgWord)(xxx); xPushTag(ADDR_TAG); }
385 #define xTaggedStackAddr(iii) ((StgAddr)(*(xSp+1+(iii))))
386 #define xPopTaggedAddr() ((xSp++,xSp+=sizeofW(StgAddr), \
387 (StgAddr)(*(xSp-sizeofW(StgAddr)))))
389 #define xPushTaggedChar(xxx) { xSp -= sizeofW(StgChar); \
390 *xSp = (StgWord)(xxx); xPushTag(CHAR_TAG); }
391 #define xTaggedStackChar(iii) ((StgChar)(*(xSp+1+(iii))))
392 #define xPopTaggedChar() ((xSp++,xSp+=sizeofW(StgChar), \
393 (StgChar)(*(xSp-sizeofW(StgChar)))))
395 #define xPushTaggedFloat(xxx) { xSp -= sizeofW(StgFloat); \
396 ASSIGN_FLT(xSp,xxx); xPushTag(FLOAT_TAG); }
397 #define xTaggedStackFloat(iii) PK_FLT(xSp+1+(iii))
398 #define xPopTaggedFloat() ((xSp++,xSp+=sizeofW(StgFloat), \
399 PK_FLT(xSp-sizeofW(StgFloat))))
401 #define xPushTaggedDouble(xxx) { xSp -= sizeofW(StgDouble); \
402 ASSIGN_DBL(xSp,xxx); xPushTag(DOUBLE_TAG); }
403 #define xTaggedStackDouble(iii) PK_DBL(xSp+1+(iii))
404 #define xPopTaggedDouble() ((xSp++,xSp+=sizeofW(StgDouble), \
405 PK_DBL(xSp-sizeofW(StgDouble))))
408 #define xPopUpdateFrame(ooo) \
410 /* NB: doesn't assume that Sp == Su */ \
411 IF_DEBUG(evaluator, \
412 fprintf(stderr, "Updating "); \
413 printPtr(stgCast(StgPtr,xSu->updatee)); \
414 fprintf(stderr, " with "); \
416 fprintf(stderr,"xSp = %p\txSu = %p\n\n", xSp, xSu); \
418 UPD_IND(xSu->updatee,ooo); \
419 xSp = stgCast(StgStackPtr,xSu) + sizeofW(StgUpdateFrame); \
425 /* Instruction stream macros */
426 #define BCO_INSTR_8 *bciPtr++
427 #define BCO_INSTR_16 ((bciPtr += 2, (*(bciPtr-2) << 8) + *(bciPtr-1)))
428 #define PC (bciPtr - &(bcoInstr(bco,0)))
431 StgThreadReturnCode enter( StgClosure* obj0 )
433 /* use of register here is primarily to make it clear to compilers
434 that these entities are non-aliasable.
436 register StgPtr xSp; /* local state -- stack pointer */
437 register StgUpdateFrame* xSu; /* local state -- frame pointer */
438 register StgPtr xSpLim; /* local state -- stack lim pointer */
439 register StgClosure* obj; /* object currently under evaluation */
440 char eCount; /* enter counter, for context switching */
443 /* use the t values to check that Su/Sp/SpLim do not change unexpectedly */
444 StgPtr tSp = Sp; StgUpdateFrame* tSu = Su; StgPtr tSpLim = SpLim;
450 /* Load the local state from global state, and Party On, Dudes! */
451 /* From here onwards, we operate with the local state and
452 save/reload it as necessary.
461 assert(SpLim == tSpLim);
465 ASSERT(xSpLim <= xSp && xSp <= stgCast(StgPtr,xSu));
467 "\n---------------------------------------------------------------\n");
468 fprintf(stderr,"(%d) Entering: ",enterCountI); printObj(obj);
469 fprintf(stderr,"xSp = %p\txSu = %p\n", xSp, xSu);
470 fprintf(stderr, "\n" );
471 printStack(xSp,CurrentTSO->stack+CurrentTSO->stack_size,xSu);
472 fprintf(stderr, "\n\n");
478 if (context_switch) {
479 xPushCPtr(obj); /* code to restart with */
480 RETURN(ThreadYielding);
484 switch ( get_itbl(obj)->type ) {
486 barf("Invalid object %p",obj);
490 /* ---------------------------------------------------- */
491 /* Start of the bytecode evaluator */
492 /* ---------------------------------------------------- */
494 # if !DEBUG && USE_GCC_LABELS
495 # define Ins(x) &&l##x
496 static void *labs[] = { INSTRLIST };
498 # define LoopTopLabel
499 # define Case(x) l##x
500 # define Continue goto *labs[BCO_INSTR_8]
501 # define Dispatch Continue;
504 # define LoopTopLabel insnloop:
505 # define Case(x) case x
506 # define Continue goto insnloop
507 # define Dispatch switch (BCO_INSTR_8) {
508 # define EndDispatch }
511 register StgWord8* bciPtr; /* instruction pointer */
512 register StgBCO* bco = (StgBCO*)obj;
515 /* Don't need to SSS ... LLL around doYouWantToGC */
516 wantToGC = doYouWantToGC();
518 xPushCPtr((StgClosure*)bco); /* code to restart with */
519 RETURN(HeapOverflow);
527 bciPtr = &(bcoInstr(bco,0));
531 ASSERT(PC < bco->n_instrs);
533 fprintf(stderr,"Sp = %p\tSu = %p\tpc = %d\t", xSp, xSu, PC);
537 //fprintf(stderr,"\n");
538 // for (i = 4; i >= 0; i--)
539 // fprintf(stderr, "%d %p\n", i, (StgPtr)(*(Sp+i)));
541 fprintf(stderr,"\n");
546 SSS; cp_bill_insns(1); LLL;
551 Case(i_INTERNAL_ERROR):
552 barf("INTERNAL_ERROR at %p:%d",bco,PC-1);
554 barf("PANIC at %p:%d",bco,PC-1);
558 if (xSp - n < xSpLim) {
559 xPushCPtr((StgClosure*)bco); /* code to restart with */
560 RETURN(StackOverflow);
567 if ((StgPtr*)(xSp + n) > (StgPtr*)xSu) {
568 StgWord words = (P_)xSu - xSp;
570 /* first build a PAP */
571 ASSERT((P_)xSu >= xSp); /* was (words >= 0) but that's always true */
572 if (words == 0) { /* optimisation */
573 /* Skip building the PAP and update with an indirection. */
576 /* In the evaluator, we avoid the need to do
577 * a heap check here by including the size of
578 * the PAP in the heap check we performed
579 * when we entered the BCO.
583 SSS; pap = (StgPAP*)grabHpNonUpd(PAP_sizeW(words)); LLL;
584 SET_HDR(pap,&PAP_info,CC_pap);
587 for (i = 0; i < (I_)words; ++i) {
588 payloadWord(pap,i) = xSp[i];
591 obj = stgCast(StgClosure*,pap);
594 /* now deal with "update frame" */
595 /* as an optimisation, we process all on top of stack */
596 /* instead of just the top one */
597 ASSERT(xSp==(P_)xSu);
599 switch (get_itbl(xSu)->type) {
601 /* Hit a catch frame during an arg satisfaction check,
602 * so the thing returning (1) has not thrown an
603 * exception, and (2) is of functional type. Just
604 * zap the catch frame and carry on down the stack
605 * (looking for more arguments, basically).
607 SSS; PopCatchFrame(); LLL;
610 xPopUpdateFrame(obj);
613 SSS; PopStopFrame(obj); LLL;
614 RETURN(ThreadFinished);
616 SSS; PopSeqFrame(); LLL;
617 ASSERT(xSp != (P_)xSu);
618 /* Hit a SEQ frame during an arg satisfaction check.
619 * So now return to bco_info which is under the
620 * SEQ frame. The following code is copied from a
621 * case RET_BCO further down. (The reason why we're
622 * here is that something of functional type has
623 * been seq-d on, and we're now returning to the
624 * algebraic-case-continuation which forced the
625 * evaluation in the first place.)
637 barf("Invalid update frame during argcheck");
639 } while (xSp==(P_)xSu);
647 int words = BCO_INSTR_8;
648 SSS; p = grabHpUpd(AP_sizeW(words)); LLL;
652 Case(i_ALLOC_CONSTR):
655 StgInfoTable* info = bcoConstAddr(bco,BCO_INSTR_8);
656 SSS; p = grabHpNonUpd(sizeW_fromITBL(info)); LLL;
657 SET_HDR((StgClosure*)p,info,??);
663 int x = BCO_INSTR_8; /* ToDo: Word not Int! */
665 StgAP_UPD* o = stgCast(StgAP_UPD*,xStackPtr(x));
666 SET_HDR(o,&AP_UPD_info,??);
668 o->fun = stgCast(StgClosure*,xPopPtr());
669 for(x=0; x < y; ++x) {
670 payloadWord(o,x) = xPopWord();
673 fprintf(stderr,"\tBuilt ");
675 printObj(stgCast(StgClosure*,o));
686 o = stgCast(StgAP_UPD*,xStackPtr(x));
687 SET_HDR(o,&AP_UPD_info,??);
689 o->fun = stgCast(StgClosure*,xPopPtr());
690 for(x=0; x < y; ++x) {
691 payloadWord(o,x) = xPopWord();
694 fprintf(stderr,"\tBuilt ");
696 printObj(stgCast(StgClosure*,o));
705 StgPAP* o = stgCast(StgPAP*,xStackPtr(x));
706 SET_HDR(o,&PAP_info,??);
708 o->fun = stgCast(StgClosure*,xPopPtr());
709 for(x=0; x < y; ++x) {
710 payloadWord(o,x) = xPopWord();
713 fprintf(stderr,"\tBuilt ");
715 printObj(stgCast(StgClosure*,o));
722 int offset = BCO_INSTR_8;
723 StgClosure* o = stgCast(StgClosure*,xStackPtr(offset));
724 const StgInfoTable* info = get_itbl(o);
725 nat p = info->layout.payload.ptrs;
726 nat np = info->layout.payload.nptrs;
728 for(i=0; i < p; ++i) {
729 payloadCPtr(o,i) = xPopCPtr();
731 for(i=0; i < np; ++i) {
732 payloadWord(o,p+i) = 0xdeadbeef;
735 fprintf(stderr,"\tBuilt ");
737 printObj(stgCast(StgClosure*,o));
744 int offset = BCO_INSTR_16;
745 StgClosure* o = stgCast(StgClosure*,xStackPtr(offset));
746 const StgInfoTable* info = get_itbl(o);
747 nat p = info->layout.payload.ptrs;
748 nat np = info->layout.payload.nptrs;
750 for(i=0; i < p; ++i) {
751 payloadCPtr(o,i) = xPopCPtr();
753 for(i=0; i < np; ++i) {
754 payloadWord(o,p+i) = 0xdeadbeef;
757 fprintf(stderr,"\tBuilt ");
759 printObj(stgCast(StgClosure*,o));
768 ASSERT(xSp+x+y <= stgCast(StgPtr,xSu));
769 /* a_1, .. a_x, b_1, .. b_y, s => a_1, .. a_x, s */
771 xSetStackWord(x+y,xStackWord(x));
781 ASSERT(xSp+x+y <= stgCast(StgPtr,xSu));
782 /* a_1, .. a_x, b_1, .. b_y, s => a_1, .. a_x, s */
784 xSetStackWord(x+y,xStackWord(x));
796 xPushPtr(bcoConstPtr(bco,BCO_INSTR_8));
797 xPushPtr(stgCast(StgPtr,&ret_bco_info));
802 int tag = BCO_INSTR_8;
803 StgWord offset = BCO_INSTR_16;
804 if (constrTag(stgCast(StgClosure*,xStackPtr(0))) != tag) {
811 StgClosure* o = stgCast(StgClosure*,xStackPtr(0));
812 const StgInfoTable* itbl = get_itbl(o);
813 int i = itbl->layout.payload.ptrs;
814 ASSERT( itbl->type == CONSTR
815 || itbl->type == CONSTR_STATIC
816 || itbl->type == CONSTR_NOCAF_STATIC
819 xPushCPtr(payloadCPtr(o,i));
825 int n = BCO_INSTR_16;
826 StgPtr p = xStackPtr(n);
832 StgPtr p = xStackPtr(BCO_INSTR_8);
838 xPushPtr(stgCast(StgPtr,bcoConstPtr(bco,BCO_INSTR_8)));
843 int n = BCO_INSTR_16;
844 xPushPtr(stgCast(StgPtr,bcoConstPtr(bco,n)));
849 SSS; PushTaggedRealWorld(); LLL;
854 StgInt i = xTaggedStackInt(BCO_INSTR_8);
860 xPushTaggedInt(bcoConstInt(bco,BCO_INSTR_8));
866 SSS; o = (StgClosure*)grabHpNonUpd(Izh_sizeW); LLL;
867 SET_HDR(o,&Izh_con_info,??);
868 payloadWord(o,0) = xPopTaggedInt();
870 fprintf(stderr,"\tBuilt ");
872 printObj(stgCast(StgClosure*,o));
875 xPushPtr(stgCast(StgPtr,o));
880 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
881 /* ASSERT(isIntLike(con)); */
882 xPushTaggedInt(payloadWord(con,0));
887 StgWord offset = BCO_INSTR_16;
888 StgInt x = xPopTaggedInt();
889 StgInt y = xPopTaggedInt();
895 Case(i_CONST_INTEGER):
899 char* s = bcoConstAddr(bco,BCO_INSTR_8);
902 p = CreateByteArrayToHoldInteger(n);
903 do_fromStr ( s, n, IntegerInsideByteArray(p));
904 SloppifyIntegerEnd(p);
911 StgWord w = xTaggedStackWord(BCO_INSTR_8);
917 xPushTaggedWord(bcoConstWord(bco,BCO_INSTR_8));
923 SSS; o = (StgClosure*)grabHpNonUpd(Wzh_sizeW); LLL;
924 SET_HDR(o,&Wzh_con_info,??);
925 payloadWord(o,0) = xPopTaggedWord();
927 fprintf(stderr,"\tBuilt ");
929 printObj(stgCast(StgClosure*,o));
932 xPushPtr(stgCast(StgPtr,o));
937 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
938 /* ASSERT(isWordLike(con)); */
939 xPushTaggedWord(payloadWord(con,0));
944 StgAddr a = xTaggedStackAddr(BCO_INSTR_8);
950 xPushTaggedAddr(bcoConstAddr(bco,BCO_INSTR_8));
956 SSS; o = (StgClosure*)grabHpNonUpd(Azh_sizeW); LLL;
957 SET_HDR(o,&Azh_con_info,??);
958 payloadPtr(o,0) = xPopTaggedAddr();
960 fprintf(stderr,"\tBuilt ");
962 printObj(stgCast(StgClosure*,o));
965 xPushPtr(stgCast(StgPtr,o));
970 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
971 /* ASSERT(isAddrLike(con)); */
972 xPushTaggedAddr(payloadPtr(con,0));
977 StgChar c = xTaggedStackChar(BCO_INSTR_8);
983 xPushTaggedChar(bcoConstChar(bco,BCO_INSTR_8));
989 SSS; o = (StgClosure*)grabHpNonUpd(Czh_sizeW); LLL;
990 SET_HDR(o,&Czh_con_info,??);
991 payloadWord(o,0) = xPopTaggedChar();
992 xPushPtr(stgCast(StgPtr,o));
994 fprintf(stderr,"\tBuilt ");
996 printObj(stgCast(StgClosure*,o));
1001 Case(i_UNPACK_CHAR):
1003 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1004 /* ASSERT(isCharLike(con)); */
1005 xPushTaggedChar(payloadWord(con,0));
1010 StgFloat f = xTaggedStackFloat(BCO_INSTR_8);
1011 xPushTaggedFloat(f);
1014 Case(i_CONST_FLOAT):
1016 xPushTaggedFloat(bcoConstFloat(bco,BCO_INSTR_8));
1022 SSS; o = (StgClosure*)grabHpNonUpd(Fzh_sizeW); LLL;
1023 SET_HDR(o,&Fzh_con_info,??);
1024 ASSIGN_FLT(&payloadWord(o,0),xPopTaggedFloat());
1026 fprintf(stderr,"\tBuilt ");
1028 printObj(stgCast(StgClosure*,o));
1031 xPushPtr(stgCast(StgPtr,o));
1034 Case(i_UNPACK_FLOAT):
1036 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1037 /* ASSERT(isFloatLike(con)); */
1038 xPushTaggedFloat(PK_FLT(&payloadWord(con,0)));
1043 StgDouble d = xTaggedStackDouble(BCO_INSTR_8);
1044 xPushTaggedDouble(d);
1047 Case(i_CONST_DOUBLE):
1049 xPushTaggedDouble(bcoConstDouble(bco,BCO_INSTR_8));
1052 Case(i_CONST_DOUBLE_big):
1054 int n = BCO_INSTR_16;
1055 xPushTaggedDouble(bcoConstDouble(bco,n));
1058 Case(i_PACK_DOUBLE):
1061 SSS; o = (StgClosure*)grabHpNonUpd(Dzh_sizeW); LLL;
1062 SET_HDR(o,&Dzh_con_info,??);
1063 ASSIGN_DBL(&payloadWord(o,0),xPopTaggedDouble());
1065 fprintf(stderr,"\tBuilt ");
1066 printObj(stgCast(StgClosure*,o));
1068 xPushPtr(stgCast(StgPtr,o));
1071 Case(i_UNPACK_DOUBLE):
1073 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1074 /* ASSERT(isDoubleLike(con)); */
1075 xPushTaggedDouble(PK_DBL(&payloadWord(con,0)));
1080 fprintf(stderr, "unimp: i_VAR_STABLE\n" ); exit(0);
1081 /*fix side effects here ...*/
1083 xPushTaggedStablePtr(xTaggedStackStable(BCO_INSTR_8));
1087 Case(i_PACK_STABLE):
1090 fprintf(stderr, "unimp: i_PACK_STABLE\n" ); exit(0);
1092 SSS; o = (StgClosure*)grabHpNonUpd(Stablezh_sizeW); LLL;
1093 SET_HDR(o,&StablePtr_con_info,??);
1094 payloadWord(o,0) = xPopTaggedStablePtr();
1096 fprintf(stderr,"\tBuilt ");
1097 printObj(stgCast(StgClosure*,o));
1099 xPushPtr(stgCast(StgPtr,o));
1103 Case(i_UNPACK_STABLE):
1106 fprintf(stderr, "unimp: i_UNPACK_STABLE\n" ); exit(0);
1108 con = stgCast(StgClosure*,xStackPtr(0));
1109 ASSERT(isStableLike(con));
1110 xPushTaggedStablePtr(payloadWord(con,0));
1119 SSS; p = enterBCO_primop1 ( i ); LLL;
1120 if (p) { obj = p; goto enterLoop; };
1127 trc = 12345678; /* Hope that no StgThreadReturnCode has this value */
1129 SSS; p = enterBCO_primop2 ( i, &trc ); LLL;
1131 if (trc == 12345678) {
1132 /* we want to enter p */
1133 obj = p; goto enterLoop;
1135 /* p is the the StgThreadReturnCode for this thread */
1136 RETURN((StgThreadReturnCode)p);
1142 /* combined insns, created by peephole opt */
1145 int x = BCO_INSTR_8;
1146 int y = BCO_INSTR_8;
1147 ASSERT(xSp+x+y <= stgCast(StgPtr,xSu));
1148 /* a_1, .. a_x, b_1, .. b_y, s => a_1, .. a_x, s */
1155 xSetStackWord(x+y,xStackWord(x));
1165 p = xStackPtr(BCO_INSTR_8);
1167 p = xStackPtr(BCO_INSTR_8);
1174 xPushPtr(bcoConstPtr(bco,BCO_INSTR_8));
1175 xPushPtr(stgCast(StgPtr,&ret_bco_info));
1176 p = xStackPtr(BCO_INSTR_8);
1182 StgPtr retaddr = bcoConstPtr(bco,BCO_INSTR_8);
1183 StgPtr ptr = xStackPtr(BCO_INSTR_8);
1185 /* A shortcut. We're going to push the address of a
1186 return continuation, and then enter a variable, so
1187 that when the var is evaluated, we return to the
1188 continuation. The shortcut is: if the var is a
1189 constructor, don't bother to enter it. Instead,
1190 push the variable on the stack (since this is what
1191 the continuation expects) and jump directly to the
1194 if (get_itbl((StgClosure*)ptr)->type == CONSTR) {
1196 obj = (StgClosure*)retaddr;
1198 fprintf(stderr, "object to enter is a constructor -- "
1199 "jumping directly to return continuation\n" );
1204 /* This is the normal, non-short-cut route */
1206 xPushPtr(stgCast(StgPtr,&ret_bco_info));
1207 obj = (StgClosure*)ptr;
1212 Case(i_VAR_DOUBLE_big):
1213 Case(i_CONST_FLOAT_big):
1214 Case(i_VAR_FLOAT_big):
1215 Case(i_CONST_CHAR_big):
1216 Case(i_VAR_CHAR_big):
1217 Case(i_CONST_ADDR_big):
1218 Case(i_VAR_ADDR_big):
1219 Case(i_CONST_INTEGER_big):
1220 Case(i_CONST_INT_big):
1221 Case(i_VAR_INT_big):
1222 Case(i_VAR_WORD_big):
1223 Case(i_RETADDR_big):
1227 disInstr ( bco, PC );
1228 barf("\nUnrecognised instruction");
1232 barf("enterBCO: ran off end of loop");
1236 # undef LoopTopLabel
1242 /* ---------------------------------------------------- */
1243 /* End of the bytecode evaluator */
1244 /* ---------------------------------------------------- */
1248 StgBlockingQueue* bh;
1249 StgCAF* caf = (StgCAF*)obj;
1250 if (xSp - sizeofW(StgUpdateFrame) < xSpLim) {
1251 xPushCPtr(obj); /* code to restart with */
1252 RETURN(StackOverflow);
1254 /* ToDo: look for xSp==xSu && stackInt(0) == UPD_FRAME
1255 and insert an indirection immediately */
1256 SSS; bh = (StgBlockingQueue*)grabHpUpd(BLACKHOLE_sizeW()); LLL;
1257 SET_INFO(bh,&CAF_BLACKHOLE_info);
1258 bh->blocking_queue = EndTSOQueue;
1260 fprintf(stderr,"Created CAF_BLACKHOLE %p for CAF %p in evaluator\n",bh,caf));
1261 SET_INFO(caf,&CAF_ENTERED_info);
1262 caf->value = (StgClosure*)bh;
1263 if (caf->mut_link == NULL) {
1264 SSS; recordOldToNewPtrs((StgMutClosure*)caf); LLL;
1266 SSS; PUSH_UPD_FRAME(bh,0); LLL;
1267 xSp -= sizeofW(StgUpdateFrame);
1268 caf->link = enteredCAFs;
1275 StgCAF* caf = (StgCAF*)obj;
1276 obj = caf->value; /* it's just a fancy indirection */
1282 /*was StgBlackHole* */
1283 StgBlockingQueue* bh = (StgBlockingQueue*)obj;
1284 /* Put ourselves on the blocking queue for this black hole and block */
1285 CurrentTSO->link = bh->blocking_queue;
1286 bh->blocking_queue = CurrentTSO;
1287 xPushCPtr(obj); /* code to restart with */
1288 barf("enter: CAF_BLACKHOLE unexpected!");
1289 RETURN(ThreadBlocked);
1293 StgAP_UPD* ap = stgCast(StgAP_UPD*,obj);
1295 if (xSp - (i + sizeofW(StgUpdateFrame)) < xSpLim) {
1296 xPushCPtr(obj); /* code to restart with */
1297 RETURN(StackOverflow);
1299 /* ToDo: look for xSp==xSu && stackInt(0) == UPD_FRAME
1300 and insert an indirection immediately */
1301 SSS; PUSH_UPD_FRAME(ap,0); LLL;
1302 xSp -= sizeofW(StgUpdateFrame);
1304 xPushWord(payloadWord(ap,i));
1307 #ifndef LAZY_BLACKHOLING
1310 /* superfluous - but makes debugging easier */
1311 StgBlackHole* bh = stgCast(StgBlackHole*,ap);
1312 SET_INFO(bh,&BLACKHOLE_info);
1313 bh->blocking_queue = EndTSOQueue;
1314 IF_DEBUG(gccafs,fprintf(stderr,"Eagerly blackholed AP_UPD %p in evaluator\n",bh));
1317 #endif /* LAZY_BLACKHOLING */
1322 StgPAP* pap = stgCast(StgPAP*,obj);
1323 int i = pap->n_args; /* ToDo: stack check */
1324 /* ToDo: if PAP is in whnf, we can update any update frames
1328 xPushWord(payloadWord(pap,i));
1335 obj = stgCast(StgInd*,obj)->indirectee;
1340 obj = stgCast(StgIndOldGen*,obj)->indirectee;
1344 case CONSTR_INTLIKE:
1345 case CONSTR_CHARLIKE:
1347 case CONSTR_NOCAF_STATIC:
1350 switch (get_itbl(stgCast(StgClosure*,xSp))->type) {
1352 SSS; PopCatchFrame(); LLL;
1355 xPopUpdateFrame(obj);
1358 SSS; PopSeqFrame(); LLL;
1362 ASSERT(xSp==(P_)xSu);
1366 /*fprintf(stderr,"xSp = %p\txSu = %p\n", xSp, xSu);*/
1367 /*printStack(xSp,CurrentTSO->stack+CurrentTSO->stack_size,xSu);*/
1370 SSS; PopStopFrame(obj); LLL;
1371 RETURN(ThreadFinished);
1381 /* was: goto enterLoop;
1382 But we know that obj must be a bco now, so jump directly.
1385 case RET_SMALL: /* return to GHC */
1389 barf("todo: RET_[VEC_]{BIG,SMALL}");
1391 belch("entered CONSTR with invalid continuation on stack");
1394 printObj(stgCast(StgClosure*,xSp));
1397 barf("bailing out");
1404 fprintf(stderr, "enterCountI = %d\n", enterCountI);
1405 fprintf(stderr, "panic: enter: entered unknown closure\n");
1407 fprintf(stderr, "what it points at is\n");
1408 printObj( ((StgEvacuated*)obj) ->evacuee);
1412 CurrentTSO->whatNext = ThreadEnterGHC;
1413 xPushCPtr(obj); /* code to restart with */
1414 RETURN(ThreadYielding);
1417 barf("Ran off the end of enter - yoiks");
1434 #undef xSetStackWord
1437 #undef xPushTaggedInt
1438 #undef xPopTaggedInt
1439 #undef xTaggedStackInt
1440 #undef xPushTaggedWord
1441 #undef xPopTaggedWord
1442 #undef xTaggedStackWord
1443 #undef xPushTaggedAddr
1444 #undef xTaggedStackAddr
1445 #undef xPopTaggedAddr
1446 #undef xPushTaggedChar
1447 #undef xTaggedStackChar
1448 #undef xPopTaggedChar
1449 #undef xPushTaggedFloat
1450 #undef xTaggedStackFloat
1451 #undef xPopTaggedFloat
1452 #undef xPushTaggedDouble
1453 #undef xTaggedStackDouble
1454 #undef xPopTaggedDouble
1458 /* --------------------------------------------------------------------------
1459 * Supporting routines for primops
1460 * ------------------------------------------------------------------------*/
1462 static inline void PushTag ( StackTag t )
1464 static inline void PushPtr ( StgPtr x )
1465 { *(--stgCast(StgPtr*,Sp)) = x; }
1466 static inline void PushCPtr ( StgClosure* x )
1467 { *(--stgCast(StgClosure**,Sp)) = x; }
1468 static inline void PushInt ( StgInt x )
1469 { *(--stgCast(StgInt*,Sp)) = x; }
1470 static inline void PushWord ( StgWord x )
1471 { *(--stgCast(StgWord*,Sp)) = x; }
1474 static inline void checkTag ( StackTag t1, StackTag t2 )
1475 { ASSERT(t1 == t2);}
1476 static inline void PopTag ( StackTag t )
1477 { checkTag(t,*(Sp++)); }
1478 static inline StgPtr PopPtr ( void )
1479 { return *stgCast(StgPtr*,Sp)++; }
1480 static inline StgClosure* PopCPtr ( void )
1481 { return *stgCast(StgClosure**,Sp)++; }
1482 static inline StgInt PopInt ( void )
1483 { return *stgCast(StgInt*,Sp)++; }
1484 static inline StgWord PopWord ( void )
1485 { return *stgCast(StgWord*,Sp)++; }
1487 static inline StgPtr stackPtr ( StgStackOffset i )
1488 { return *stgCast(StgPtr*, Sp+i); }
1489 static inline StgInt stackInt ( StgStackOffset i )
1490 { return *stgCast(StgInt*, Sp+i); }
1491 static inline StgWord stackWord ( StgStackOffset i )
1492 { return *stgCast(StgWord*,Sp+i); }
1494 static inline void setStackWord ( StgStackOffset i, StgWord w )
1497 static inline void PushTaggedRealWorld( void )
1498 { PushTag(REALWORLD_TAG); }
1499 inline void PushTaggedInt ( StgInt x )
1500 { Sp -= sizeofW(StgInt); *Sp = x; PushTag(INT_TAG); }
1501 static inline void PushTaggedWord ( StgWord x )
1502 { Sp -= sizeofW(StgWord); *Sp = x; PushTag(WORD_TAG); }
1503 static inline void PushTaggedAddr ( StgAddr x )
1504 { Sp -= sizeofW(StgAddr); *Sp = (W_)x; PushTag(ADDR_TAG); }
1505 static inline void PushTaggedChar ( StgChar x )
1506 { Sp -= sizeofW(StgChar); *Sp = stgCast(StgWord,x); PushTag(CHAR_TAG); }
1507 static inline void PushTaggedFloat ( StgFloat x )
1508 { Sp -= sizeofW(StgFloat); ASSIGN_FLT(Sp,x); PushTag(FLOAT_TAG); }
1509 static inline void PushTaggedDouble ( StgDouble x )
1510 { Sp -= sizeofW(StgDouble); ASSIGN_DBL(Sp,x); PushTag(DOUBLE_TAG); }
1511 static inline void PushTaggedStablePtr ( StgStablePtr x )
1512 { Sp -= sizeofW(StgStablePtr); *Sp = x; PushTag(STABLE_TAG); }
1513 static inline void PushTaggedBool ( int x )
1514 { PushTaggedInt(x); }
1518 static inline void PopTaggedRealWorld ( void )
1519 { PopTag(REALWORLD_TAG); }
1520 inline StgInt PopTaggedInt ( void )
1521 { StgInt r; PopTag(INT_TAG); r = *stgCast(StgInt*, Sp);
1522 Sp += sizeofW(StgInt); return r;}
1523 static inline StgWord PopTaggedWord ( void )
1524 { StgWord r; PopTag(WORD_TAG); r = *stgCast(StgWord*, Sp);
1525 Sp += sizeofW(StgWord); return r;}
1526 static inline StgAddr PopTaggedAddr ( void )
1527 { StgAddr r; PopTag(ADDR_TAG); r = *stgCast(StgAddr*, Sp);
1528 Sp += sizeofW(StgAddr); return r;}
1529 static inline StgChar PopTaggedChar ( void )
1530 { StgChar r; PopTag(CHAR_TAG); r = stgCast(StgChar, *Sp);
1531 Sp += sizeofW(StgChar); return r;}
1532 static inline StgFloat PopTaggedFloat ( void )
1533 { StgFloat r; PopTag(FLOAT_TAG); r = PK_FLT(Sp);
1534 Sp += sizeofW(StgFloat); return r;}
1535 static inline StgDouble PopTaggedDouble ( void )
1536 { StgDouble r; PopTag(DOUBLE_TAG); r = PK_DBL(Sp);
1537 Sp += sizeofW(StgDouble); return r;}
1538 static inline StgStablePtr PopTaggedStablePtr ( void )
1539 { StgInt r; PopTag(STABLE_TAG); r = *stgCast(StgStablePtr*, Sp);
1540 Sp += sizeofW(StgStablePtr); return r;}
1544 static inline StgInt taggedStackInt ( StgStackOffset i )
1545 { checkTag(INT_TAG,Sp[i]); return *stgCast(StgInt*, Sp+1+i); }
1546 static inline StgWord taggedStackWord ( StgStackOffset i )
1547 { checkTag(WORD_TAG,Sp[i]); return *stgCast(StgWord*, Sp+1+i); }
1548 static inline StgAddr taggedStackAddr ( StgStackOffset i )
1549 { checkTag(ADDR_TAG,Sp[i]); return *stgCast(StgAddr*, Sp+1+i); }
1550 static inline StgChar taggedStackChar ( StgStackOffset i )
1551 { checkTag(CHAR_TAG,Sp[i]); return stgCast(StgChar, *(Sp+1+i)) ; }
1552 static inline StgFloat taggedStackFloat ( StgStackOffset i )
1553 { checkTag(FLOAT_TAG,Sp[i]); return PK_FLT(Sp+1+i); }
1554 static inline StgDouble taggedStackDouble ( StgStackOffset i )
1555 { checkTag(DOUBLE_TAG,Sp[i]); return PK_DBL(Sp+1+i); }
1556 static inline StgStablePtr taggedStackStable ( StgStackOffset i )
1557 { checkTag(STABLE_TAG,Sp[i]); return *stgCast(StgStablePtr*, Sp+1+i); }
1560 /* --------------------------------------------------------------------------
1563 * Should we allocate from a nursery or use the
1564 * doYouWantToGC/allocate interface? We'd already implemented a
1565 * nursery-style scheme when the doYouWantToGC/allocate interface
1567 * One reason to prefer the doYouWantToGC/allocate interface is to
1568 * support operations which allocate an unknown amount in the heap
1569 * (array ops, gmp ops, etc)
1570 * ------------------------------------------------------------------------*/
1572 static inline StgPtr grabHpUpd( nat size )
1574 ASSERT( size >= MIN_UPD_SIZE + sizeofW(StgHeader) );
1575 #ifdef CRUDE_PROFILING
1576 cp_bill_words ( size );
1578 return allocate(size);
1581 static inline StgPtr grabHpNonUpd( nat size )
1583 ASSERT( size >= MIN_NONUPD_SIZE + sizeofW(StgHeader) );
1584 #ifdef CRUDE_PROFILING
1585 cp_bill_words ( size );
1587 return allocate(size);
1590 /* --------------------------------------------------------------------------
1591 * Manipulate "update frame" list:
1592 * o Update frames (based on stg_do_update and friends in Updates.hc)
1593 * o Error handling/catching (based on catchzh_fast and friends in Prims.hc)
1594 * o Seq frames (based on seq_frame_entry in Prims.hc)
1596 * ------------------------------------------------------------------------*/
1598 static inline void PopUpdateFrame( StgClosure* obj )
1600 /* NB: doesn't assume that Sp == Su */
1602 fprintf(stderr, "Updating ");
1603 printPtr(stgCast(StgPtr,Su->updatee));
1604 fprintf(stderr, " with ");
1606 fprintf(stderr,"Sp = %p\tSu = %p\n\n", Sp, Su);
1608 #ifndef LAZY_BLACKHOLING
1609 ASSERT(get_itbl(Su->updatee)->type == BLACKHOLE
1610 || get_itbl(Su->updatee)->type == CAF_BLACKHOLE
1612 #endif /* LAZY_BLACKHOLING */
1613 UPD_IND(Su->updatee,obj);
1614 Sp = stgCast(StgStackPtr,Su) + sizeofW(StgUpdateFrame);
1618 static inline void PopStopFrame( StgClosure* obj )
1620 /* Move Su just off the end of the stack, we're about to spam the
1621 * STOP_FRAME with the return value.
1623 Su = stgCast(StgUpdateFrame*,Sp+1);
1624 *stgCast(StgClosure**,Sp) = obj;
1627 static inline void PushCatchFrame( StgClosure* handler )
1630 /* ToDo: stack check! */
1631 Sp -= sizeofW(StgCatchFrame);
1632 fp = stgCast(StgCatchFrame*,Sp);
1633 SET_HDR(fp,&catch_frame_info,CCCS);
1634 fp->handler = handler;
1636 Su = stgCast(StgUpdateFrame*,fp);
1639 static inline void PopCatchFrame( void )
1641 /* NB: doesn't assume that Sp == Su */
1642 /* fprintf(stderr,"Popping catch frame\n"); */
1643 Sp = stgCast(StgStackPtr,Su) + sizeofW(StgCatchFrame);
1644 Su = stgCast(StgCatchFrame*,Su)->link;
1647 static inline void PushSeqFrame( void )
1650 /* ToDo: stack check! */
1651 Sp -= sizeofW(StgSeqFrame);
1652 fp = stgCast(StgSeqFrame*,Sp);
1653 SET_HDR(fp,&seq_frame_info,CCCS);
1655 Su = stgCast(StgUpdateFrame*,fp);
1658 static inline void PopSeqFrame( void )
1660 /* NB: doesn't assume that Sp == Su */
1661 Sp = stgCast(StgStackPtr,Su) + sizeofW(StgSeqFrame);
1662 Su = stgCast(StgSeqFrame*,Su)->link;
1665 static inline StgClosure* raiseAnError( StgClosure* errObj )
1667 StgClosure *raise_closure;
1669 /* This closure represents the expression 'raise# E' where E
1670 * is the exception raised. It is used to overwrite all the
1671 * thunks which are currently under evaluataion.
1673 raise_closure = (StgClosure *)allocate(sizeofW(StgClosure)+1);
1674 raise_closure->header.info = &raise_info;
1675 raise_closure->payload[0] = R1.cl;
1678 switch (get_itbl(Su)->type) {
1680 UPD_IND(Su->updatee,raise_closure);
1681 Sp = stgCast(StgStackPtr,Su) + sizeofW(StgUpdateFrame);
1687 case CATCH_FRAME: /* found it! */
1689 StgCatchFrame* fp = stgCast(StgCatchFrame*,Su);
1690 StgClosure *handler = fp->handler;
1692 Sp += sizeofW(StgCatchFrame); /* Pop */
1697 barf("raiseError: uncaught exception: STOP_FRAME");
1699 barf("raiseError: weird activation record");
1704 static StgClosure* raisePrim(char* msg)
1706 /* ToDo: figure out some way to turn the msg into a Haskell Exception
1707 * Hack: we don't know how to build an Exception but we do know how
1708 * to build a (recursive!) error object.
1709 * The result isn't pretty but it's (slightly) better than nothing.
1711 nat size = sizeof(StgClosure) + 1;
1712 StgClosure* errObj = stgCast(StgClosure*,grabHpNonUpd(size));
1713 SET_INFO(errObj,&raise_info);
1714 errObj->payload[0] = errObj;
1715 fprintf(stderr, "\n\n\nRAISE PRIM %s\n", msg);
1719 /* At the moment, I prefer to put it on stdout to make things as
1720 * close to Hugs' old behaviour as possible.
1722 fprintf(stdout, "Program error: %s", msg);
1725 return raiseAnError(stgCast(StgClosure*,errObj));
1728 #define raiseIndex(where) raisePrim("Array index out of range in " where)
1729 #define raiseDiv0(where) raisePrim("Division by 0 in " where)
1731 /* --------------------------------------------------------------------------
1733 * ------------------------------------------------------------------------*/
1735 #define OP_CC_B(e) \
1737 unsigned char x = PopTaggedChar(); \
1738 unsigned char y = PopTaggedChar(); \
1739 PushTaggedBool(e); \
1744 unsigned char x = PopTaggedChar(); \
1753 #define OP_IW_I(e) \
1755 StgInt x = PopTaggedInt(); \
1756 StgWord y = PopTaggedWord(); \
1760 #define OP_II_I(e) \
1762 StgInt x = PopTaggedInt(); \
1763 StgInt y = PopTaggedInt(); \
1767 #define OP_II_B(e) \
1769 StgInt x = PopTaggedInt(); \
1770 StgInt y = PopTaggedInt(); \
1771 PushTaggedBool(e); \
1776 PushTaggedAddr(e); \
1781 StgInt x = PopTaggedInt(); \
1782 PushTaggedAddr(e); \
1787 StgInt x = PopTaggedInt(); \
1793 PushTaggedChar(e); \
1798 StgInt x = PopTaggedInt(); \
1799 PushTaggedChar(e); \
1804 PushTaggedWord(e); \
1809 StgInt x = PopTaggedInt(); \
1810 PushTaggedWord(e); \
1815 PushTaggedFloat(e); \
1820 StgInt x = PopTaggedInt(); \
1821 PushTaggedFloat(e); \
1826 PushTaggedDouble(e); \
1831 StgInt x = PopTaggedInt(); \
1832 PushTaggedDouble(e); \
1835 #define OP_WW_B(e) \
1837 StgWord x = PopTaggedWord(); \
1838 StgWord y = PopTaggedWord(); \
1839 PushTaggedBool(e); \
1842 #define OP_WW_W(e) \
1844 StgWord x = PopTaggedWord(); \
1845 StgWord y = PopTaggedWord(); \
1846 PushTaggedWord(e); \
1851 StgWord x = PopTaggedWord(); \
1857 StgWord x = PopTaggedWord(); \
1858 PushTaggedWord(e); \
1861 #define OP_AA_B(e) \
1863 StgAddr x = PopTaggedAddr(); \
1864 StgAddr y = PopTaggedAddr(); \
1865 PushTaggedBool(e); \
1869 StgAddr x = PopTaggedAddr(); \
1872 #define OP_AI_C(s) \
1874 StgAddr x = PopTaggedAddr(); \
1875 int y = PopTaggedInt(); \
1878 PushTaggedChar(r); \
1880 #define OP_AI_I(s) \
1882 StgAddr x = PopTaggedAddr(); \
1883 int y = PopTaggedInt(); \
1888 #define OP_AI_A(s) \
1890 StgAddr x = PopTaggedAddr(); \
1891 int y = PopTaggedInt(); \
1894 PushTaggedAddr(s); \
1896 #define OP_AI_F(s) \
1898 StgAddr x = PopTaggedAddr(); \
1899 int y = PopTaggedInt(); \
1902 PushTaggedFloat(r); \
1904 #define OP_AI_D(s) \
1906 StgAddr x = PopTaggedAddr(); \
1907 int y = PopTaggedInt(); \
1910 PushTaggedDouble(r); \
1912 #define OP_AI_s(s) \
1914 StgAddr x = PopTaggedAddr(); \
1915 int y = PopTaggedInt(); \
1918 PushTaggedStablePtr(r); \
1920 #define OP_AIC_(s) \
1922 StgAddr x = PopTaggedAddr(); \
1923 int y = PopTaggedInt(); \
1924 StgChar z = PopTaggedChar(); \
1927 #define OP_AII_(s) \
1929 StgAddr x = PopTaggedAddr(); \
1930 int y = PopTaggedInt(); \
1931 StgInt z = PopTaggedInt(); \
1934 #define OP_AIA_(s) \
1936 StgAddr x = PopTaggedAddr(); \
1937 int y = PopTaggedInt(); \
1938 StgAddr z = PopTaggedAddr(); \
1941 #define OP_AIF_(s) \
1943 StgAddr x = PopTaggedAddr(); \
1944 int y = PopTaggedInt(); \
1945 StgFloat z = PopTaggedFloat(); \
1948 #define OP_AID_(s) \
1950 StgAddr x = PopTaggedAddr(); \
1951 int y = PopTaggedInt(); \
1952 StgDouble z = PopTaggedDouble(); \
1955 #define OP_AIs_(s) \
1957 StgAddr x = PopTaggedAddr(); \
1958 int y = PopTaggedInt(); \
1959 StgStablePtr z = PopTaggedStablePtr(); \
1964 #define OP_FF_B(e) \
1966 StgFloat x = PopTaggedFloat(); \
1967 StgFloat y = PopTaggedFloat(); \
1968 PushTaggedBool(e); \
1971 #define OP_FF_F(e) \
1973 StgFloat x = PopTaggedFloat(); \
1974 StgFloat y = PopTaggedFloat(); \
1975 PushTaggedFloat(e); \
1980 StgFloat x = PopTaggedFloat(); \
1981 PushTaggedFloat(e); \
1986 StgFloat x = PopTaggedFloat(); \
1987 PushTaggedBool(e); \
1992 StgFloat x = PopTaggedFloat(); \
1998 StgFloat x = PopTaggedFloat(); \
1999 PushTaggedDouble(e); \
2002 #define OP_DD_B(e) \
2004 StgDouble x = PopTaggedDouble(); \
2005 StgDouble y = PopTaggedDouble(); \
2006 PushTaggedBool(e); \
2009 #define OP_DD_D(e) \
2011 StgDouble x = PopTaggedDouble(); \
2012 StgDouble y = PopTaggedDouble(); \
2013 PushTaggedDouble(e); \
2018 StgDouble x = PopTaggedDouble(); \
2019 PushTaggedBool(e); \
2024 StgDouble x = PopTaggedDouble(); \
2025 PushTaggedDouble(e); \
2030 StgDouble x = PopTaggedDouble(); \
2036 StgDouble x = PopTaggedDouble(); \
2037 PushTaggedFloat(e); \
2041 #ifdef STANDALONE_INTEGER
2042 StgPtr CreateByteArrayToHoldInteger ( int nbytes )
2044 StgInt words = (nbytes+sizeof(W_)-1)/sizeof(W_);
2045 StgWord size = sizeofW(StgArrWords) + words;
2046 StgArrWords* arr = (StgArrWords*)allocate(size);
2047 SET_HDR(arr,&ARR_WORDS_info,CCCS);
2049 ASSERT(nbytes <= arr->words * sizeof(W_));
2052 for (i = 0; i < words; ++i) {
2053 arr->payload[i] = 0xdeadbeef;
2055 { B* b = (B*) &(arr->payload[0]);
2056 b->used = b->sign = 0;
2062 B* IntegerInsideByteArray ( StgPtr arr0 )
2065 StgArrWords* arr = (StgArrWords*)arr0;
2066 ASSERT(GET_INFO(arr) == &ARR_WORDS_info);
2067 b = (B*) &(arr->payload[0]);
2071 void SloppifyIntegerEnd ( StgPtr arr0 )
2073 StgArrWords* arr = (StgArrWords*)arr0;
2074 B* b = (B*) & (arr->payload[0]);
2075 I_ nwunused = arr->words - sizeofW(B) - (b->used+sizeof(W_)-1)/sizeof(W_);
2076 if (nwunused >= ((I_)sizeofW(StgArrWords))) {
2078 b->size -= nwunused * sizeof(W_);
2079 if (b->size < b->used) b->size = b->used;
2082 arr->words -= nwunused;
2083 slop = &(arr->payload[arr->words]);
2084 SET_HDR(slop,&ARR_WORDS_info,CCCS);
2085 slop->words = nwunused - sizeofW(StgArrWords);
2086 ASSERT( &(slop->payload[slop->words]) ==
2087 &(arr->payload[arr->words + nwunused]) );
2091 #define OP_Z_Z(op) \
2093 B* x = IntegerInsideByteArray(PopPtr()); \
2094 int n = mycat2(size_,op)(x); \
2095 StgPtr p = CreateByteArrayToHoldInteger(n); \
2096 mycat2(do_,op)(x,n,IntegerInsideByteArray(p)); \
2097 SloppifyIntegerEnd(p); \
2100 #define OP_ZZ_Z(op) \
2102 B* x = IntegerInsideByteArray(PopPtr()); \
2103 B* y = IntegerInsideByteArray(PopPtr()); \
2104 int n = mycat2(size_,op)(x,y); \
2105 StgPtr p = CreateByteArrayToHoldInteger(n); \
2106 mycat2(do_,op)(x,y,n,IntegerInsideByteArray(p)); \
2107 SloppifyIntegerEnd(p); \
2115 #define HEADER_mI(ty,where) \
2116 StgArrWords* x = stgCast(StgArrWords*,PopPtr()); \
2117 nat i = PopTaggedInt(); \
2118 if (i * sizeof(ty) + (sizeof(ty)) > sizeof(StgWord) * x->words) { \
2119 return (raiseIndex(where)); \
2121 #define OP_mI_ty(ty,where,s) \
2123 HEADER_mI(mycat2(Stg,ty),where) \
2124 { mycat2(Stg,ty) r; \
2126 mycat2(PushTagged,ty)(r); \
2129 #define OP_mIty_(ty,where,s) \
2131 HEADER_mI(mycat2(Stg,ty),where) \
2133 mycat2(Stg,ty) z = mycat2(PopTagged,ty)(); \
2139 void myStackCheck ( void )
2141 //StgPtr sp = (StgPtr)Sp;
2142 StgPtr su = (StgPtr)Su;
2143 //fprintf(stderr, "myStackCheck\n");
2144 if (!(SpLim <= Sp && Sp <= stgCast(StgPtr,Su))) {
2145 fprintf(stderr, "myStackCheck: invalid initial Sp/Su \n" );
2149 if (!(su >= CurrentTSO->stack && su <= CurrentTSO->stack + CurrentTSO->stack_size)) {
2150 fprintf ( stderr, "myStackCheck: su out of stack\n" );
2153 switch (get_itbl(stgCast(StgClosure*,su))->type) {
2155 su = (StgPtr) ((StgCatchFrame*)(su))->link;
2158 su = (StgPtr) ((StgUpdateFrame*)(su))->link;
2161 su = (StgPtr) ((StgSeqFrame*)(su))->link;
2166 fprintf(stderr, "myStackCheck: invalid activation record\n"); assert(0);
2173 /* --------------------------------------------------------------------------
2174 * Primop stuff for bytecode interpreter
2175 * ------------------------------------------------------------------------*/
2177 /* Returns & of the next thing to enter (if throwing an exception),
2178 or NULL in the normal case.
2180 static void* enterBCO_primop1 ( int primop1code )
2182 switch (primop1code) {
2183 case i_pushseqframe:
2185 StgClosure* c = PopCPtr();
2190 case i_pushcatchframe:
2192 StgClosure* e = PopCPtr();
2193 StgClosure* h = PopCPtr();
2199 case i_gtChar: OP_CC_B(x>y); break;
2200 case i_geChar: OP_CC_B(x>=y); break;
2201 case i_eqChar: OP_CC_B(x==y); break;
2202 case i_neChar: OP_CC_B(x!=y); break;
2203 case i_ltChar: OP_CC_B(x<y); break;
2204 case i_leChar: OP_CC_B(x<=y); break;
2205 case i_charToInt: OP_C_I(x); break;
2206 case i_intToChar: OP_I_C(x); break;
2208 case i_gtInt: OP_II_B(x>y); break;
2209 case i_geInt: OP_II_B(x>=y); break;
2210 case i_eqInt: OP_II_B(x==y); break;
2211 case i_neInt: OP_II_B(x!=y); break;
2212 case i_ltInt: OP_II_B(x<y); break;
2213 case i_leInt: OP_II_B(x<=y); break;
2214 case i_minInt: OP__I(INT_MIN); break;
2215 case i_maxInt: OP__I(INT_MAX); break;
2216 case i_plusInt: OP_II_I(x+y); break;
2217 case i_minusInt: OP_II_I(x-y); break;
2218 case i_timesInt: OP_II_I(x*y); break;
2221 int x = PopTaggedInt();
2222 int y = PopTaggedInt();
2224 return (raiseDiv0("quotInt"));
2226 /* ToDo: protect against minInt / -1 errors
2227 * (repeat for all other division primops)
2234 int x = PopTaggedInt();
2235 int y = PopTaggedInt();
2237 return (raiseDiv0("remInt"));
2244 StgInt x = PopTaggedInt();
2245 StgInt y = PopTaggedInt();
2247 return (raiseDiv0("quotRemInt"));
2249 PushTaggedInt(x%y); /* last result */
2250 PushTaggedInt(x/y); /* first result */
2253 case i_negateInt: OP_I_I(-x); break;
2255 case i_andInt: OP_II_I(x&y); break;
2256 case i_orInt: OP_II_I(x|y); break;
2257 case i_xorInt: OP_II_I(x^y); break;
2258 case i_notInt: OP_I_I(~x); break;
2259 case i_shiftLInt: OP_II_I(x<<y); break;
2260 case i_shiftRAInt: OP_II_I(x>>y); break; /* ToDo */
2261 case i_shiftRLInt: OP_II_I(x>>y); break; /* ToDo */
2263 case i_gtWord: OP_WW_B(x>y); break;
2264 case i_geWord: OP_WW_B(x>=y); break;
2265 case i_eqWord: OP_WW_B(x==y); break;
2266 case i_neWord: OP_WW_B(x!=y); break;
2267 case i_ltWord: OP_WW_B(x<y); break;
2268 case i_leWord: OP_WW_B(x<=y); break;
2269 case i_minWord: OP__W(0); break;
2270 case i_maxWord: OP__W(UINT_MAX); break;
2271 case i_plusWord: OP_WW_W(x+y); break;
2272 case i_minusWord: OP_WW_W(x-y); break;
2273 case i_timesWord: OP_WW_W(x*y); break;
2276 StgWord x = PopTaggedWord();
2277 StgWord y = PopTaggedWord();
2279 return (raiseDiv0("quotWord"));
2281 PushTaggedWord(x/y);
2286 StgWord x = PopTaggedWord();
2287 StgWord y = PopTaggedWord();
2289 return (raiseDiv0("remWord"));
2291 PushTaggedWord(x%y);
2296 StgWord x = PopTaggedWord();
2297 StgWord y = PopTaggedWord();
2299 return (raiseDiv0("quotRemWord"));
2301 PushTaggedWord(x%y); /* last result */
2302 PushTaggedWord(x/y); /* first result */
2305 case i_negateWord: OP_W_W(-x); break;
2306 case i_andWord: OP_WW_W(x&y); break;
2307 case i_orWord: OP_WW_W(x|y); break;
2308 case i_xorWord: OP_WW_W(x^y); break;
2309 case i_notWord: OP_W_W(~x); break;
2310 case i_shiftLWord: OP_WW_W(x<<y); break;
2311 case i_shiftRAWord: OP_WW_W(x>>y); break; /* ToDo */
2312 case i_shiftRLWord: OP_WW_W(x>>y); break; /* ToDo */
2313 case i_intToWord: OP_I_W(x); break;
2314 case i_wordToInt: OP_W_I(x); break;
2316 case i_gtAddr: OP_AA_B(x>y); break;
2317 case i_geAddr: OP_AA_B(x>=y); break;
2318 case i_eqAddr: OP_AA_B(x==y); break;
2319 case i_neAddr: OP_AA_B(x!=y); break;
2320 case i_ltAddr: OP_AA_B(x<y); break;
2321 case i_leAddr: OP_AA_B(x<=y); break;
2322 case i_intToAddr: OP_I_A((StgAddr)x); break; /* ToDo */
2323 case i_addrToInt: OP_A_I((StgInt)x); break; /* ToDo */
2325 case i_indexCharOffAddr: OP_AI_C(indexCharOffAddrzh(r,x,y)); break;
2326 case i_readCharOffAddr: OP_AI_C(indexCharOffAddrzh(r,x,y)); break;
2327 case i_writeCharOffAddr: OP_AIC_(writeCharOffAddrzh(x,y,z)); break;
2329 case i_indexIntOffAddr: OP_AI_I(indexIntOffAddrzh(r,x,y)); break;
2330 case i_readIntOffAddr: OP_AI_I(indexIntOffAddrzh(r,x,y)); break;
2331 case i_writeIntOffAddr: OP_AII_(writeIntOffAddrzh(x,y,z)); break;
2333 case i_indexAddrOffAddr: OP_AI_A(indexAddrOffAddrzh(r,x,y)); break;
2334 case i_readAddrOffAddr: OP_AI_A(indexAddrOffAddrzh(r,x,y)); break;
2335 case i_writeAddrOffAddr: OP_AIA_(writeAddrOffAddrzh(x,y,z)); break;
2337 case i_indexFloatOffAddr: OP_AI_F(indexFloatOffAddrzh(r,x,y)); break;
2338 case i_readFloatOffAddr: OP_AI_F(indexFloatOffAddrzh(r,x,y)); break;
2339 case i_writeFloatOffAddr: OP_AIF_(writeFloatOffAddrzh(x,y,z)); break;
2341 case i_indexDoubleOffAddr: OP_AI_D(indexDoubleOffAddrzh(r,x,y)); break;
2342 case i_readDoubleOffAddr: OP_AI_D(indexDoubleOffAddrzh(r,x,y)); break;
2343 case i_writeDoubleOffAddr: OP_AID_(writeDoubleOffAddrzh(x,y,z)); break;
2345 #ifdef PROVIDE_STABLE
2346 case i_indexStableOffAddr: OP_AI_s(indexStablePtrOffAddrzh(r,x,y)); break;
2347 case i_readStableOffAddr: OP_AI_s(indexStablePtrOffAddrzh(r,x,y)); break;
2348 case i_writeStableOffAddr: OP_AIs_(writeStablePtrOffAddrzh(x,y,z)); break;
2351 #ifdef STANDALONE_INTEGER
2352 case i_compareInteger:
2354 B* x = IntegerInsideByteArray(PopPtr());
2355 B* y = IntegerInsideByteArray(PopPtr());
2356 StgInt r = do_cmp(x,y);
2357 PushTaggedInt(r<0 ? -1 : (r>0 ? 1 : 0));
2360 case i_negateInteger: OP_Z_Z(neg); break;
2361 case i_plusInteger: OP_ZZ_Z(add); break;
2362 case i_minusInteger: OP_ZZ_Z(sub); break;
2363 case i_timesInteger: OP_ZZ_Z(mul); break;
2364 case i_quotRemInteger:
2366 B* x = IntegerInsideByteArray(PopPtr());
2367 B* y = IntegerInsideByteArray(PopPtr());
2368 int n = size_qrm(x,y);
2369 StgPtr q = CreateByteArrayToHoldInteger(n);
2370 StgPtr r = CreateByteArrayToHoldInteger(n);
2371 if (do_getsign(y)==0)
2372 return (raiseDiv0("quotRemInteger"));
2373 do_qrm(x,y,n,IntegerInsideByteArray(q),
2374 IntegerInsideByteArray(r));
2375 SloppifyIntegerEnd(q);
2376 SloppifyIntegerEnd(r);
2381 case i_intToInteger:
2383 int n = size_fromInt();
2384 StgPtr p = CreateByteArrayToHoldInteger(n);
2385 do_fromInt( PopTaggedInt(), n, IntegerInsideByteArray(p));
2389 case i_wordToInteger:
2391 int n = size_fromWord();
2392 StgPtr p = CreateByteArrayToHoldInteger(n);
2393 do_fromWord( PopTaggedWord(), n, IntegerInsideByteArray(p));
2397 case i_integerToInt: PushTaggedInt(do_toInt(
2398 IntegerInsideByteArray(PopPtr())
2402 case i_integerToWord: PushTaggedWord(do_toWord(
2403 IntegerInsideByteArray(PopPtr())
2407 case i_integerToFloat: PushTaggedFloat(do_toFloat(
2408 IntegerInsideByteArray(PopPtr())
2412 case i_integerToDouble: PushTaggedDouble(do_toDouble(
2413 IntegerInsideByteArray(PopPtr())
2417 #error Non-standalone integer not yet implemented
2418 #endif /* STANDALONE_INTEGER */
2420 case i_gtFloat: OP_FF_B(x>y); break;
2421 case i_geFloat: OP_FF_B(x>=y); break;
2422 case i_eqFloat: OP_FF_B(x==y); break;
2423 case i_neFloat: OP_FF_B(x!=y); break;
2424 case i_ltFloat: OP_FF_B(x<y); break;
2425 case i_leFloat: OP_FF_B(x<=y); break;
2426 case i_minFloat: OP__F(FLT_MIN); break;
2427 case i_maxFloat: OP__F(FLT_MAX); break;
2428 case i_radixFloat: OP__I(FLT_RADIX); break;
2429 case i_digitsFloat: OP__I(FLT_MANT_DIG); break;
2430 case i_minExpFloat: OP__I(FLT_MIN_EXP); break;
2431 case i_maxExpFloat: OP__I(FLT_MAX_EXP); break;
2432 case i_plusFloat: OP_FF_F(x+y); break;
2433 case i_minusFloat: OP_FF_F(x-y); break;
2434 case i_timesFloat: OP_FF_F(x*y); break;
2437 StgFloat x = PopTaggedFloat();
2438 StgFloat y = PopTaggedFloat();
2441 return (raiseDiv0("divideFloat"));
2444 PushTaggedFloat(x/y);
2447 case i_negateFloat: OP_F_F(-x); break;
2448 case i_floatToInt: OP_F_I(x); break;
2449 case i_intToFloat: OP_I_F(x); break;
2450 case i_expFloat: OP_F_F(exp(x)); break;
2451 case i_logFloat: OP_F_F(log(x)); break;
2452 case i_sqrtFloat: OP_F_F(sqrt(x)); break;
2453 case i_sinFloat: OP_F_F(sin(x)); break;
2454 case i_cosFloat: OP_F_F(cos(x)); break;
2455 case i_tanFloat: OP_F_F(tan(x)); break;
2456 case i_asinFloat: OP_F_F(asin(x)); break;
2457 case i_acosFloat: OP_F_F(acos(x)); break;
2458 case i_atanFloat: OP_F_F(atan(x)); break;
2459 case i_sinhFloat: OP_F_F(sinh(x)); break;
2460 case i_coshFloat: OP_F_F(cosh(x)); break;
2461 case i_tanhFloat: OP_F_F(tanh(x)); break;
2462 case i_powerFloat: OP_FF_F(pow(x,y)); break;
2464 #ifdef STANDALONE_INTEGER
2465 case i_encodeFloatZ:
2467 StgPtr sig = PopPtr();
2468 StgInt exp = PopTaggedInt();
2470 B__encodeFloat(IntegerInsideByteArray(sig), exp)
2474 case i_decodeFloatZ:
2476 StgFloat f = PopTaggedFloat();
2477 StgPtr sig = CreateByteArrayToHoldInteger(size_fltmantissa());
2479 B__decodeFloat(IntegerInsideByteArray(sig), &exp, f);
2485 #error encode/decodeFloatZ not yet implemented for GHC ints
2487 case i_isNaNFloat: OP_F_B(isFloatNaN(x)); break;
2488 case i_isInfiniteFloat: OP_F_B(isFloatInfinite(x)); break;
2489 case i_isNegativeZeroFloat: OP_F_B(isFloatNegativeZero(x)); break;
2490 case i_isDenormalizedFloat: OP_F_B(isFloatDenormalized(x)); break;
2491 case i_gtDouble: OP_DD_B(x>y); break;
2492 case i_geDouble: OP_DD_B(x>=y); break;
2493 case i_eqDouble: OP_DD_B(x==y); break;
2494 case i_neDouble: OP_DD_B(x!=y); break;
2495 case i_ltDouble: OP_DD_B(x<y); break;
2496 case i_leDouble: OP_DD_B(x<=y) break;
2497 case i_minDouble: OP__D(DBL_MIN); break;
2498 case i_maxDouble: OP__D(DBL_MAX); break;
2499 case i_radixDouble: OP__I(FLT_RADIX); break;
2500 case i_digitsDouble: OP__I(DBL_MANT_DIG); break;
2501 case i_minExpDouble: OP__I(DBL_MIN_EXP); break;
2502 case i_maxExpDouble: OP__I(DBL_MAX_EXP); break;
2503 case i_plusDouble: OP_DD_D(x+y); break;
2504 case i_minusDouble: OP_DD_D(x-y); break;
2505 case i_timesDouble: OP_DD_D(x*y); break;
2506 case i_divideDouble:
2508 StgDouble x = PopTaggedDouble();
2509 StgDouble y = PopTaggedDouble();
2512 return (raiseDiv0("divideDouble"));
2515 PushTaggedDouble(x/y);
2518 case i_negateDouble: OP_D_D(-x); break;
2519 case i_doubleToInt: OP_D_I(x); break;
2520 case i_intToDouble: OP_I_D(x); break;
2521 case i_doubleToFloat: OP_D_F(x); break;
2522 case i_floatToDouble: OP_F_F(x); break;
2523 case i_expDouble: OP_D_D(exp(x)); break;
2524 case i_logDouble: OP_D_D(log(x)); break;
2525 case i_sqrtDouble: OP_D_D(sqrt(x)); break;
2526 case i_sinDouble: OP_D_D(sin(x)); break;
2527 case i_cosDouble: OP_D_D(cos(x)); break;
2528 case i_tanDouble: OP_D_D(tan(x)); break;
2529 case i_asinDouble: OP_D_D(asin(x)); break;
2530 case i_acosDouble: OP_D_D(acos(x)); break;
2531 case i_atanDouble: OP_D_D(atan(x)); break;
2532 case i_sinhDouble: OP_D_D(sinh(x)); break;
2533 case i_coshDouble: OP_D_D(cosh(x)); break;
2534 case i_tanhDouble: OP_D_D(tanh(x)); break;
2535 case i_powerDouble: OP_DD_D(pow(x,y)); break;
2537 #ifdef STANDALONE_INTEGER
2538 case i_encodeDoubleZ:
2540 StgPtr sig = PopPtr();
2541 StgInt exp = PopTaggedInt();
2543 B__encodeDouble(IntegerInsideByteArray(sig), exp)
2547 case i_decodeDoubleZ:
2549 StgDouble d = PopTaggedDouble();
2550 StgPtr sig = CreateByteArrayToHoldInteger(size_dblmantissa());
2552 B__decodeDouble(IntegerInsideByteArray(sig), &exp, d);
2558 #error encode/decodeDoubleZ not yet implemented for GHC ints
2560 case i_isNaNDouble: OP_D_B(isDoubleNaN(x)); break;
2561 case i_isInfiniteDouble: OP_D_B(isDoubleInfinite(x)); break;
2562 case i_isNegativeZeroDouble: OP_D_B(isDoubleNegativeZero(x)); break;
2563 case i_isDenormalizedDouble: OP_D_B(isDoubleDenormalized(x)); break;
2564 case i_isIEEEDouble:
2566 PushTaggedBool(rtsTrue);
2570 barf("Unrecognised primop1");
2577 /* For normal cases, return NULL and leave *return2 unchanged.
2578 To return the address of the next thing to enter,
2579 return the address of it and leave *return2 unchanged.
2580 To return a StgThreadReturnCode to the scheduler,
2581 set *return2 to it and return a non-NULL value.
2583 static void* enterBCO_primop2 ( int primop2code,
2584 int* /*StgThreadReturnCode* */ return2 )
2586 switch (primop2code) {
2587 case i_raise: /* raise#{err} */
2589 StgClosure* err = PopCPtr();
2590 return (raiseAnError(err));
2595 StgClosure* init = PopCPtr();
2597 = stgCast(StgMutVar*,allocate(sizeofW(StgMutVar)));
2598 SET_HDR(mv,&MUT_VAR_info,CCCS);
2600 PushPtr(stgCast(StgPtr,mv));
2605 StgMutVar* mv = stgCast(StgMutVar*,PopPtr());
2611 StgMutVar* mv = stgCast(StgMutVar*,PopPtr());
2612 StgClosure* value = PopCPtr();
2618 nat n = PopTaggedInt(); /* or Word?? */
2619 StgClosure* init = PopCPtr();
2620 StgWord size = sizeofW(StgMutArrPtrs) + n;
2623 = stgCast(StgMutArrPtrs*,allocate(size));
2624 SET_HDR(arr,&MUT_ARR_PTRS_info,CCCS);
2626 for (i = 0; i < n; ++i) {
2627 arr->payload[i] = init;
2629 PushPtr(stgCast(StgPtr,arr));
2635 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
2636 nat i = PopTaggedInt(); /* or Word?? */
2637 StgWord n = arr->ptrs;
2639 return (raiseIndex("{index,read}Array"));
2641 PushCPtr(arr->payload[i]);
2646 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
2647 nat i = PopTaggedInt(); /* or Word? */
2648 StgClosure* v = PopCPtr();
2649 StgWord n = arr->ptrs;
2651 return (raiseIndex("{index,read}Array"));
2653 arr->payload[i] = v;
2657 case i_sizeMutableArray:
2659 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
2660 PushTaggedInt(arr->ptrs);
2663 case i_unsafeFreezeArray:
2665 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
2666 SET_INFO(arr,&MUT_ARR_PTRS_FROZEN_info);
2667 PushPtr(stgCast(StgPtr,arr));
2670 case i_unsafeFreezeByteArray:
2672 /* Delightfully simple :-) */
2676 case i_sameMutableArray:
2677 case i_sameMutableByteArray:
2679 StgPtr x = PopPtr();
2680 StgPtr y = PopPtr();
2681 PushTaggedBool(x==y);
2685 case i_newByteArray:
2687 nat n = PopTaggedInt(); /* or Word?? */
2688 StgInt words = (n+sizeof(W_)-1)/sizeof(W_);
2689 StgWord size = sizeofW(StgArrWords) + words;
2690 StgArrWords* arr = stgCast(StgArrWords*,allocate(size));
2691 SET_HDR(arr,&ARR_WORDS_info,CCCS);
2695 for (i = 0; i < n; ++i) {
2696 arr->payload[i] = 0xdeadbeef;
2699 PushPtr(stgCast(StgPtr,arr));
2703 /* Most of these generate alignment warnings on Sparcs and similar architectures.
2704 * These are harmless and are caused by the cast to C* in BYTE_ARR_CTS.
2706 case i_indexCharArray:
2707 OP_mI_ty(Char,"indexCharArray", indexCharArrayzh(r,x,i)); break;
2708 case i_readCharArray:
2709 OP_mI_ty(Char,"readCharArray", readCharArrayzh(r,x,i)); break;
2710 case i_writeCharArray:
2711 OP_mIty_(Char,"writeCharArray", writeCharArrayzh(x,i,z)); break;
2713 case i_indexIntArray:
2714 OP_mI_ty(Int,"indexIntArray", indexIntArrayzh(r,x,i)); break;
2715 case i_readIntArray:
2716 OP_mI_ty(Int,"readIntArray", readIntArrayzh(r,x,i)); break;
2717 case i_writeIntArray:
2718 OP_mIty_(Int,"writeIntArray", writeIntArrayzh(x,i,z)); break;
2720 case i_indexAddrArray:
2721 OP_mI_ty(Addr,"indexAddrArray", indexAddrArrayzh(r,x,i)); break;
2722 case i_readAddrArray:
2723 OP_mI_ty(Addr,"readAddrArray", readAddrArrayzh(r,x,i)); break;
2724 case i_writeAddrArray:
2725 OP_mIty_(Addr,"writeAddrArray", writeAddrArrayzh(x,i,z)); break;
2727 case i_indexFloatArray:
2728 OP_mI_ty(Float,"indexFloatArray", indexFloatArrayzh(r,x,i)); break;
2729 case i_readFloatArray:
2730 OP_mI_ty(Float,"readFloatArray", readFloatArrayzh(r,x,i)); break;
2731 case i_writeFloatArray:
2732 OP_mIty_(Float,"writeFloatArray", writeFloatArrayzh(x,i,z)); break;
2734 case i_indexDoubleArray:
2735 OP_mI_ty(Double,"indexDoubleArray", indexDoubleArrayzh(r,x,i)); break;
2736 case i_readDoubleArray:
2737 OP_mI_ty(Double,"readDoubleArray", readDoubleArrayzh(r,x,i)); break;
2738 case i_writeDoubleArray:
2739 OP_mIty_(Double,"writeDoubleArray", writeDoubleArrayzh(x,i,z)); break;
2741 #ifdef PROVIDE_STABLE
2742 case i_indexStableArray:
2743 OP_mI_ty(StablePtr,"indexStableArray", indexStablePtrArrayzh(r,x,i)); break;
2744 case i_readStableArray:
2745 OP_mI_ty(StablePtr,"readStableArray", readStablePtrArrayzh(r,x,i)); break;
2746 case i_writeStableArray:
2747 OP_mIty_(StablePtr,"writeStableArray", writeStablePtrArrayzh(x,i,z)); break;
2753 #ifdef PROVIDE_COERCE
2754 case i_unsafeCoerce:
2756 /* Another nullop */
2760 #ifdef PROVIDE_PTREQUALITY
2761 case i_reallyUnsafePtrEquality:
2762 { /* identical to i_sameRef */
2763 StgPtr x = PopPtr();
2764 StgPtr y = PopPtr();
2765 PushTaggedBool(x==y);
2769 #ifdef PROVIDE_FOREIGN
2770 /* ForeignObj# operations */
2771 case i_makeForeignObj:
2773 StgForeignObj *result
2774 = stgCast(StgForeignObj*,allocate(sizeofW(StgForeignObj)));
2775 SET_HDR(result,&FOREIGN_info,CCCS);
2776 result -> data = PopTaggedAddr();
2777 PushPtr(stgCast(StgPtr,result));
2780 #endif /* PROVIDE_FOREIGN */
2785 = stgCast(StgWeak*,allocate(sizeofW(StgWeak)));
2786 SET_HDR(w, &WEAK_info, CCCS);
2788 w->value = PopCPtr();
2789 w->finaliser = PopCPtr();
2790 w->link = weak_ptr_list;
2792 IF_DEBUG(weak, fprintf(stderr,"New weak pointer at %p\n",w));
2793 PushPtr(stgCast(StgPtr,w));
2798 StgWeak *w = stgCast(StgWeak*,PopPtr());
2799 if (w->header.info == &WEAK_info) {
2800 PushCPtr(w->value); /* last result */
2801 PushTaggedInt(1); /* first result */
2803 PushPtr(stgCast(StgPtr,w)); /* ToDo: error thunk would be better */
2808 #endif /* PROVIDE_WEAK */
2809 #ifdef PROVIDE_STABLE
2810 /* StablePtr# operations */
2811 case i_makeStablePtr:
2812 case i_deRefStablePtr:
2813 case i_freeStablePtr:
2814 { fprintf(stderr,"Evaluator.c:stablePtrOp unimp\n" );
2819 case i_makeStablePtr:
2821 StgStablePtr stable_ptr;
2822 if (stable_ptr_free == NULL) {
2823 enlargeStablePtrTable();
2826 stable_ptr = stable_ptr_free - stable_ptr_table;
2827 stable_ptr_free = (P_*)*stable_ptr_free;
2828 stable_ptr_table[stable_ptr] = PopPtr();
2830 PushTaggedStablePtr(stable_ptr);
2833 case i_deRefStablePtr:
2835 StgStablePtr stable_ptr = PopTaggedStablePtr();
2836 PushPtr(stable_ptr_table[stable_ptr]);
2840 case i_freeStablePtr:
2842 StgStablePtr stable_ptr = PopTaggedStablePtr();
2843 stable_ptr_table[stable_ptr] = (P_)stable_ptr_free;
2844 stable_ptr_free = stable_ptr_table + stable_ptr;
2850 #endif /* PROVIDE_STABLE */
2851 #ifdef PROVIDE_CONCURRENT
2854 StgClosure* c = PopCPtr();
2855 StgTSO* t = createGenThread(RtsFlags.GcFlags.initialStkSize,c);
2856 PushPtr(stgCast(StgPtr,t));
2858 /* switch at the earliest opportunity */
2860 /* but don't automatically switch to GHC - or you'll waste your
2861 * time slice switching back.
2863 * Actually, there's more to it than that: the default
2864 * (ThreadEnterGHC) causes the thread to crash - don't
2865 * understand why. - ADR
2867 t->whatNext = ThreadEnterHugs;
2872 StgTSO* tso = stgCast(StgTSO*,PopPtr());
2874 if (tso == CurrentTSO) { /* suicide */
2875 *return2 = ThreadFinished;
2876 return (void*)(1+(NULL));
2881 { /* identical to i_sameRef */
2882 StgPtr x = PopPtr();
2883 StgPtr y = PopPtr();
2884 PushTaggedBool(x==y);
2889 StgMVar *mvar = stgCast(StgMVar*,allocate(sizeofW(StgMVar)));
2890 SET_INFO(mvar,&EMPTY_MVAR_info);
2891 mvar->head = mvar->tail = EndTSOQueue;
2892 /* ToDo: this is a little strange */
2893 mvar->value = stgCast(StgClosure*,&END_TSO_QUEUE_closure);
2894 PushPtr(stgCast(StgPtr,mvar));
2899 ToDo: another way out of the problem might be to add an explicit
2900 continuation to primTakeMVar: takeMVar v = primTakeMVar v takeMVar.
2901 The problem with this plan is that now I dont know how much to chop
2906 StgMVar *mvar = stgCast(StgMVar*,PopPtr());
2907 /* If the MVar is empty, put ourselves
2908 * on its blocking queue, and wait
2909 * until we're woken up.
2911 if (GET_INFO(mvar) != &FULL_MVAR_info) {
2912 if (mvar->head == EndTSOQueue) {
2913 mvar->head = CurrentTSO;
2915 mvar->tail->link = CurrentTSO;
2917 CurrentTSO->link = EndTSOQueue;
2918 mvar->tail = CurrentTSO;
2920 /* Hack, hack, hack.
2921 * When we block, we push a restart closure
2922 * on the stack - but which closure?
2923 * We happen to know that the BCO we're
2924 * executing looks like this:
2933 * 14: ALLOC_CONSTR 0x8213a80
2943 * so we rearrange the stack to look the
2944 * way it did when we entered this BCO
2946 * What a disgusting hack!
2952 *return2 = ThreadBlocked;
2953 return (void*)(1+(NULL));
2956 PushCPtr(mvar->value);
2957 SET_INFO(mvar,&EMPTY_MVAR_info);
2958 /* ToDo: this is a little strange */
2959 mvar->value = (StgClosure*)&END_TSO_QUEUE_closure;
2966 StgMVar* mvar = stgCast(StgMVar*,PopPtr());
2967 StgClosure* value = PopCPtr();
2968 if (GET_INFO(mvar) == &FULL_MVAR_info) {
2969 return (raisePrim("putMVar {full MVar}"));
2971 /* wake up the first thread on the
2972 * queue, it will continue with the
2973 * takeMVar operation and mark the
2976 StgTSO* tso = mvar->head;
2977 SET_INFO(mvar,&FULL_MVAR_info);
2978 mvar->value = value;
2979 if (tso != EndTSOQueue) {
2980 PUSH_ON_RUN_QUEUE(tso);
2981 mvar->head = tso->link;
2982 tso->link = EndTSOQueue;
2983 if (mvar->head == EndTSOQueue) {
2984 mvar->tail = EndTSOQueue;
2988 /* yield for better communication performance */
2995 /* As PrimOps.h says: Hmm, I'll think about these later. */
2998 #endif /* PROVIDE_CONCURRENT */
3002 CFunDescriptor* descriptor = PopTaggedAddr();
3003 StgAddr funPtr = PopTaggedAddr();
3004 ccall(descriptor,funPtr);
3008 barf("Unrecognised primop2");
3014 /* -----------------------------------------------------------------------------
3015 * ccall support code:
3016 * marshall moves args from C stack to Haskell stack
3017 * unmarshall moves args from Haskell stack to C stack
3018 * argSize calculates how much space you need on the C stack
3019 * ---------------------------------------------------------------------------*/
3021 /* Pop arguments off the C stack and Push them onto the Hugs stack.
3022 * Used when preparing for C calling Haskell or in response to
3023 * Haskell calling C.
3025 nat marshall(char arg_ty, void* arg)
3029 PushTaggedInt(*((int*)arg));
3030 return ARG_SIZE(INT_TAG);
3031 #ifdef TODO_STANDALONE_INTEGER
3033 PushTaggedInteger(*((mpz_ptr*)arg));
3034 return ARG_SIZE(INTEGER_TAG);
3037 PushTaggedWord(*((unsigned int*)arg));
3038 return ARG_SIZE(WORD_TAG);
3040 PushTaggedChar(*((char*)arg));
3041 return ARG_SIZE(CHAR_TAG);
3043 PushTaggedFloat(*((float*)arg));
3044 return ARG_SIZE(FLOAT_TAG);
3046 PushTaggedDouble(*((double*)arg));
3047 return ARG_SIZE(DOUBLE_TAG);
3049 PushTaggedAddr(*((void**)arg));
3050 return ARG_SIZE(ADDR_TAG);
3051 #ifdef PROVIDE_STABLE
3053 PushTaggedStablePtr(*((StgStablePtr*)arg));
3054 return ARG_SIZE(STABLE_TAG);
3056 #ifdef PROVIDE_FOREIGN
3058 /* Not allowed in this direction - you have to
3059 * call makeForeignPtr explicitly
3061 barf("marshall: ForeignPtr#\n");
3066 /* Not allowed in this direction */
3067 barf("marshall: [Mutable]ByteArray#\n");
3070 barf("marshall: unrecognised arg type %d\n",arg_ty);
3075 /* Pop arguments off the Hugs stack and Push them onto the C stack.
3076 * Used when preparing for Haskell calling C or in response to
3077 * C calling Haskell.
3079 nat unmarshall(char res_ty, void* res)
3083 *((int*)res) = PopTaggedInt();
3084 return ARG_SIZE(INT_TAG);
3085 #ifdef TODO_STANDALONE_INTEGER
3087 *((mpz_ptr*)res) = PopTaggedInteger();
3088 return ARG_SIZE(INTEGER_TAG);
3091 *((unsigned int*)res) = PopTaggedWord();
3092 return ARG_SIZE(WORD_TAG);
3094 *((int*)res) = PopTaggedChar();
3095 return ARG_SIZE(CHAR_TAG);
3097 *((float*)res) = PopTaggedFloat();
3098 return ARG_SIZE(FLOAT_TAG);
3100 *((double*)res) = PopTaggedDouble();
3101 return ARG_SIZE(DOUBLE_TAG);
3103 *((void**)res) = PopTaggedAddr();
3104 return ARG_SIZE(ADDR_TAG);
3105 #ifdef PROVIDE_STABLE
3107 *((StgStablePtr*)res) = PopTaggedStablePtr();
3108 return ARG_SIZE(STABLE_TAG);
3110 #ifdef PROVIDE_FOREIGN
3113 StgForeignObj *result = stgCast(StgForeignObj*,PopPtr());
3114 *((void**)res) = result->data;
3115 return sizeofW(StgPtr);
3121 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
3122 *((void**)res) = stgCast(void*,&(arr->payload));
3123 return sizeofW(StgPtr);
3126 barf("unmarshall: unrecognised result type %d\n",res_ty);
3130 nat argSize( const char* ks )
3133 for( ; *ks != '\0'; ++ks) {
3136 sz += sizeof(StgWord) * ARG_SIZE(INT_TAG);
3138 #ifdef TODO_STANDALONE_INTEGER
3140 sz += sizeof(StgWord) * ARG_SIZE(INTEGER_TAG);
3144 sz += sizeof(StgWord) * ARG_SIZE(WORD_TAG);
3147 sz += sizeof(StgWord) * ARG_SIZE(CHAR_TAG);
3150 sz += sizeof(StgWord) * ARG_SIZE(FLOAT_TAG);
3153 sz += sizeof(StgWord) * ARG_SIZE(DOUBLE_TAG);
3156 sz += sizeof(StgWord) * ARG_SIZE(ADDR_TAG);
3158 #ifdef PROVIDE_STABLE
3160 sz += sizeof(StgWord) * ARG_SIZE(STABLE_TAG);
3163 #ifdef PROVIDE_FOREIGN
3168 sz += sizeof(StgPtr);
3171 barf("argSize: unrecognised result type %d\n",*ks);
3179 /* -----------------------------------------------------------------------------
3180 * encode/decode Float/Double code for standalone Hugs
3181 * Code based on the HBC code (lib/fltcode.c) and more recently GHC
3182 * (ghc/rts/StgPrimFloat.c)
3183 * ---------------------------------------------------------------------------*/
3185 #ifdef STANDALONE_INTEGER
3187 #if IEEE_FLOATING_POINT
3188 #define MY_DMINEXP ((DBL_MIN_EXP) - (DBL_MANT_DIG) - 1)
3189 /* DMINEXP is defined in values.h on Linux (for example) */
3190 #define DHIGHBIT 0x00100000
3191 #define DMSBIT 0x80000000
3193 #define MY_FMINEXP ((FLT_MIN_EXP) - (FLT_MANT_DIG) - 1)
3194 #define FHIGHBIT 0x00800000
3195 #define FMSBIT 0x80000000
3197 #error The following code doesnt work in a non-IEEE FP environment
3200 #ifdef WORDS_BIGENDIAN
3209 StgDouble B__encodeDouble (B* s, I_ e) /* result = s * 2^e */
3214 /* Convert a B to a double; knows a lot about internal rep! */
3215 for(r = 0.0, i = s->used-1; i >= 0; i--)
3216 r = (r * B_BASE_FLT) + s->stuff[i];
3218 /* Now raise to the exponent */
3219 if ( r != 0.0 ) /* Lennart suggests this avoids a bug in MIPS's ldexp */
3222 /* handle the sign */
3223 if (s->sign < 0) r = -r;
3230 #if ! FLOATS_AS_DOUBLES
3231 StgFloat B__encodeFloat (B* s, I_ e) /* result = s * 2^e */
3236 /* Convert a B to a float; knows a lot about internal rep! */
3237 for(r = 0.0, i = s->used-1; i >= 0; i--)
3238 r = (r * B_BASE_FLT) + s->stuff[i];
3240 /* Now raise to the exponent */
3241 if ( r != 0.0 ) /* Lennart suggests this avoids a bug in MIPS's ldexp */
3244 /* handle the sign */
3245 if (s->sign < 0) r = -r;
3249 #endif /* FLOATS_AS_DOUBLES */
3253 /* This only supports IEEE floating point */
3254 void B__decodeDouble (B* man, I_* exp, StgDouble dbl)
3256 /* Do some bit fiddling on IEEE */
3257 nat low, high; /* assuming 32 bit ints */
3259 union { double d; int i[2]; } u; /* assuming 32 bit ints, 64 bit double */
3261 u.d = dbl; /* grab chunks of the double */
3265 ASSERT(B_BASE == 256);
3267 /* Assume that the supplied B is the right size */
3270 if (low == 0 && (high & ~DMSBIT) == 0) {
3271 man->sign = man->used = 0;
3276 iexp = ((high >> 20) & 0x7ff) + MY_DMINEXP;
3280 if (iexp != MY_DMINEXP) /* don't add hidden bit to denorms */
3284 /* A denorm, normalize the mantissa */
3285 while (! (high & DHIGHBIT)) {
3295 man->stuff[7] = (((W_)high) >> 24) & 0xff;
3296 man->stuff[6] = (((W_)high) >> 16) & 0xff;
3297 man->stuff[5] = (((W_)high) >> 8) & 0xff;
3298 man->stuff[4] = (((W_)high) ) & 0xff;
3300 man->stuff[3] = (((W_)low) >> 24) & 0xff;
3301 man->stuff[2] = (((W_)low) >> 16) & 0xff;
3302 man->stuff[1] = (((W_)low) >> 8) & 0xff;
3303 man->stuff[0] = (((W_)low) ) & 0xff;
3305 if (sign < 0) man->sign = -1;
3307 do_renormalise(man);
3311 #if ! FLOATS_AS_DOUBLES
3312 void B__decodeFloat (B* man, I_* exp, StgFloat flt)
3314 /* Do some bit fiddling on IEEE */
3315 int high, sign; /* assuming 32 bit ints */
3316 union { float f; int i; } u; /* assuming 32 bit float and int */
3318 u.f = flt; /* grab the float */
3321 ASSERT(B_BASE == 256);
3323 /* Assume that the supplied B is the right size */
3326 if ((high & ~FMSBIT) == 0) {
3327 man->sign = man->used = 0;
3332 *exp = ((high >> 23) & 0xff) + MY_FMINEXP;
3336 if (*exp != MY_FMINEXP) /* don't add hidden bit to denorms */
3340 /* A denorm, normalize the mantissa */
3341 while (! (high & FHIGHBIT)) {
3346 man->stuff[3] = (((W_)high) >> 24) & 0xff;
3347 man->stuff[2] = (((W_)high) >> 16) & 0xff;
3348 man->stuff[1] = (((W_)high) >> 8) & 0xff;
3349 man->stuff[0] = (((W_)high) ) & 0xff;
3351 if (sign < 0) man->sign = -1;
3353 do_renormalise(man);
3356 #endif /* FLOATS_AS_DOUBLES */
3358 #endif /* STANDALONE_INTEGER */
3362 #endif /* INTERPRETER */