2 /* -----------------------------------------------------------------------------
5 * Copyright (c) 1994-1998.
7 * $RCSfile: Evaluator.c,v $
9 * $Date: 2000/04/27 16:35:30 $
10 * ---------------------------------------------------------------------------*/
20 #include "SchedAPI.h" /* for createGenThread */
21 #include "Schedule.h" /* for context_switch */
22 #include "Bytecodes.h"
23 #include "Assembler.h" /* for CFun stuff */
24 #include "ForeignCall.h"
25 #include "PrimOps.h" /* for __{encode,decode}{Float,Double} */
28 #include "Evaluator.h"
29 #include "sainteger.h"
33 #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 */
46 /* Allegedly useful macro, taken from ClosureMacros.h */
47 #define payloadWord( c, i ) (*stgCast(StgWord*, ((c)->payload+(i))))
48 #define payloadPtr( c, i ) (*stgCast(StgPtr*, ((c)->payload+(i))))
50 /* An incredibly useful abbreviation.
51 * Interestingly, there are some uses of END_TSO_QUEUE_closure that
52 * can't use it because they use the closure at type StgClosure* or
53 * even StgPtr*. I suspect they should be changed. -- ADR
55 #define EndTSOQueue stgCast(StgTSO*,(void*)&END_TSO_QUEUE_closure)
57 /* These macros are rather delicate - read a good ANSI C book carefully
61 #define mycat(x,y) x##y
62 #define mycat2(x,y) mycat(x,y)
63 #define mycat3(x,y,z) mycat2(x,mycat2(y,z))
65 #if defined(__GNUC__) && !defined(DEBUG)
66 #define USE_GCC_LABELS 1
68 #define USE_GCC_LABELS 0
71 /* Make it possible for the evaluator to get hold of bytecode
72 for a given function by name. Useful but a hack. Sigh.
74 extern void* /* StgClosure* */ getHugs_BCO_cptr_for ( char* s );
75 extern int /* Bool */ combined;
77 /* --------------------------------------------------------------------------
78 * Crude profiling stuff (mainly to assess effect of optimiser)
79 * ------------------------------------------------------------------------*/
81 #ifdef CRUDE_PROFILING
90 struct { int /*StgVar*/ who;
98 CPRecord cpTab[M_CPTAB];
100 void cp_init ( void )
105 for (i = 0; i < M_CPTAB; i++)
106 cpTab[i].who = CP_NIL;
111 void cp_enter ( StgBCO* b )
115 int /*StgVar*/ v = b->stgexpr;
116 if ((void*)v == NULL) return;
125 h = (-v) % M_CPTAB; else
128 assert (h >= 0 && h < M_CPTAB);
129 while (cpTab[h].who != v && cpTab[h].who != CP_NIL) {
130 h++; if (h == M_CPTAB) h = 0;
133 if (cpTab[cpCurr].who == CP_NIL) {
134 cpTab[cpCurr].who = v;
135 if (!is_ret_cont) cpTab[cpCurr].enters = 1;
136 cpTab[cpCurr].bytes = cpTab[cpCurr].insns = 0;
138 if (cpInUse * 2 > M_CPTAB) {
139 fprintf(stderr, "\nCRUDE_PROFILING hash table is too full\n" );
143 if (!is_ret_cont) cpTab[cpCurr].enters++;
149 void cp_bill_words ( int nw )
151 if (cpCurr == CP_NIL) return;
152 cpTab[cpCurr].bytes += sizeof(StgWord)*nw;
156 void cp_bill_insns ( int ni )
158 if (cpCurr == CP_NIL) return;
159 cpTab[cpCurr].insns += ni;
163 static double percent ( double a, double b )
165 return (100.0 * a) / b;
169 void cp_show ( void )
171 int i, j, max, maxN, totE, totB, totI, cumE, cumB, cumI;
174 if (cpInUse == -1) return;
176 fflush(stdout);fflush(stderr);
179 totE = totB = totI = 0;
180 for (i = 0; i < M_CPTAB; i++) {
181 cpTab[i].twho = cpTab[i].who;
182 if (cpTab[i].who != CP_NIL) {
183 totE += cpTab[i].enters;
184 totB += cpTab[i].bytes;
185 totI += cpTab[i].insns;
190 "%6d (%7.3f M) enters, "
191 "%6d (%7.3f M) insns, "
192 "%6d (%7.3f M) bytes\n\n",
193 totE, totE/1000000.0, totI, totI/1000000.0, totB, totB/1000000.0 );
195 cumE = cumB = cumI = 0;
196 for (j = 0; j < 32; j++) {
199 for (i = 0; i < M_CPTAB; i++)
200 if (cpTab[i].who != CP_NIL &&
201 cpTab[i].enters > maxN) {
202 maxN = cpTab[i].enters;
205 if (max == -1) break;
207 cumE += cpTab[max].enters;
208 cumB += cpTab[max].bytes;
209 cumI += cpTab[max].insns;
211 strcpy(nm, maybeName(cpTab[max].who));
212 if (strcmp(nm, "(unknown)")==0)
213 sprintf ( nm, "id%d", -cpTab[max].who);
215 printf ( "%20s %7d es (%4.1f%%, %4.1f%% c) "
216 "%7d bs (%4.1f%%, %4.1f%% c) "
217 "%7d is (%4.1f%%, %4.1f%% c)\n",
219 cpTab[max].enters, percent(cpTab[max].enters,totE), percent(cumE,totE),
220 cpTab[max].bytes, percent(cpTab[max].bytes,totB), percent(cumB,totB),
221 cpTab[max].insns, percent(cpTab[max].insns,totI), percent(cumI,totI)
224 cpTab[max].twho = cpTab[max].who;
225 cpTab[max].who = CP_NIL;
228 for (i = 0; i < M_CPTAB; i++)
229 cpTab[i].who = cpTab[i].twho;
237 /* --------------------------------------------------------------------------
238 * Hugs Hooks - a bit of a hack
239 * ------------------------------------------------------------------------*/
241 void setRtsFlags( int x );
242 void setRtsFlags( int x )
244 unsigned int w = 0x12345678;
245 unsigned char* pw = (unsigned char *)&w;
248 *(int*)(&(RtsFlags.DebugFlags)) = x;
253 w2 |= (w1 && 0xFF); w2 <<= 8; w1 >>= 8;
254 w2 |= (w1 && 0xFF); w2 <<= 8; w1 >>= 8;
255 w2 |= (w1 && 0xFF); w2 <<= 8; w1 >>= 8;
256 w2 |= (w1 && 0xFF); w2 <<= 8; w1 >>= 8;
257 *(int*)(&(RtsFlags.DebugFlags)) = (int)w2;
263 StgTSOBlockReason reason;
268 /* --------------------------------------------------------------------------
269 * Entering-objects and bytecode interpreter part of evaluator
270 * ------------------------------------------------------------------------*/
272 /* The primop (and all other) parts of this evaluator operate upon the
273 machine state which lives in MainRegTable. enter is different:
274 to make its closure- and bytecode-interpreting loops go fast, some of that
275 state is pulled out into local vars (viz, registers, if we are lucky).
276 That means that we need to save(load) the local state at every exit(reentry)
277 into enter. That is, around every procedure call it makes. Blargh!
278 If you modify this code, __be warned__ it will fail in mysterious ways if
279 you fail to preserve this property.
281 Currently the pulled-out state is Sp in xSp, Su in xSu and SpLim in xSpLim.
282 The SSS macros saves the state back in MainRegTable, and LLL loads it from
283 MainRegTable. RETURN(v) does SSS and then returns v; all exits should
284 be via RETURN and not plain return.
286 Since xSp, xSu and xSpLim are local vars in enter, they are not visible
287 in procedures called from enter. To fix this, either (1) turn the
288 procedures into macros, so they get copied inline, or (2) bracket
289 the procedure call with SSS and LLL so that the local and global
290 machine states are synchronised for the duration of the call.
294 /* Forward decls ... */
295 static void* enterBCO_primop1 ( int );
296 static void* enterBCO_primop2 ( int , int* /*StgThreadReturnCode* */,
297 StgBCO**, Capability*, HugsBlock * );
298 static inline void PopUpdateFrame ( StgClosure* obj );
299 static inline void PopCatchFrame ( void );
300 static inline void PopSeqFrame ( void );
301 static inline void PopStopFrame( StgClosure* obj );
302 static inline void PushTaggedRealWorld( void );
303 /* static inline void PushTaggedInteger ( mpz_ptr ); */
304 static inline StgPtr grabHpUpd( nat size );
305 static inline StgPtr grabHpNonUpd( nat size );
306 static StgClosure* raiseAnError ( StgClosure* exception );
308 static int enterCountI = 0;
310 StgDouble B__encodeDouble (B* s, I_ e);
311 void B__decodeDouble (B* man, I_* exp, StgDouble dbl);
312 #if ! FLOATS_AS_DOUBLES
313 StgFloat B__encodeFloat (B* s, I_ e);
314 void B__decodeFloat (B* man, I_* exp, StgFloat flt);
315 StgPtr CreateByteArrayToHoldInteger ( int );
316 B* IntegerInsideByteArray ( StgPtr );
317 void SloppifyIntegerEnd ( StgPtr );
323 #define gSp MainRegTable.rSp
324 #define gSu MainRegTable.rSu
325 #define gSpLim MainRegTable.rSpLim
328 /* Macros to save/load local state. */
330 #define SSS { tSp=gSp = xSp; tSu=gSu = xSu; tSpLim=gSpLim = xSpLim; }
331 #define LLL { tSp=xSp = gSp; tSu=xSu = gSu; tSpLim=xSpLim = gSpLim; }
333 #define SSS { gSp = xSp; gSu = xSu; gSpLim = xSpLim; }
334 #define LLL { xSp = gSp; xSu = gSu; xSpLim = gSpLim; }
337 #define RETURN(vvv) { \
338 StgThreadReturnCode retVal=(vvv); \
340 cap->rCurrentTSO->sp = gSp; \
341 cap->rCurrentTSO->su = gSu; \
342 cap->rCurrentTSO->splim = gSpLim; \
347 /* Macros to operate directly on the pulled-out machine state.
348 These mirror some of the small procedures used in the primop code
349 below, except you have to be careful about side effects,
350 ie xPushPtr(xStackPtr(n)) won't work! It certainly isn't the
351 same as PushPtr(StackPtr(n)). Also note that (1) some of
352 the macros, in particular xPopTagged*, do not make the tag
353 sanity checks that their non-x cousins do, and (2) some of
354 the macros depend critically on the semantics of C comma
355 expressions to work properly.
357 #define xPushPtr(ppp) { xSp--; *xSp=(StgWord)(ppp); }
358 #define xPopPtr() ((StgPtr)(*xSp++))
360 #define xPushCPtr(ppp) { xSp--; *xSp=(StgWord)(ppp); }
361 #define xPopCPtr() ((StgClosure*)(*xSp++))
363 #define xPushWord(ppp) { xSp--; *xSp=(StgWord)(ppp); }
364 #define xPopWord() ((StgWord)(*xSp++))
366 #define xStackPtr(nnn) ((StgPtr)(*(xSp+(nnn))))
367 #define xStackWord(nnn) ((StgWord)(*(xSp+(nnn))))
368 #define xSetStackWord(iii,www) xSp[iii]=(StgWord)(www)
370 #define xPushTag(ttt) { xSp--; *xSp=(StgWord)(ttt); }
371 #define xPopTag(ttt) { StackTag t = (StackTag)(*xSp++); \
374 #define xPushTaggedInt(xxx) { xSp -= sizeofW(StgInt); \
375 *xSp = (xxx); xPushTag(INT_TAG); }
376 #define xTaggedStackInt(iii) ((StgInt)(*(xSp+1+(iii))))
377 #define xPopTaggedInt() ((xSp++,xSp+=sizeofW(StgInt), \
378 (StgInt)(*(xSp-sizeofW(StgInt)))))
380 #define xPushTaggedWord(xxx) { xSp -= sizeofW(StgWord); \
381 *xSp = (xxx); xPushTag(WORD_TAG); }
382 #define xTaggedStackWord(iii) ((StgWord)(*(xSp+1+(iii))))
383 #define xPopTaggedWord() ((xSp++,xSp+=sizeofW(StgWord), \
384 (StgWord)(*(xSp-sizeofW(StgWord)))))
386 #define xPushTaggedAddr(xxx) { xSp -= sizeofW(StgAddr); \
387 *xSp = (StgWord)(xxx); xPushTag(ADDR_TAG); }
388 #define xTaggedStackAddr(iii) ((StgAddr)(*(xSp+1+(iii))))
389 #define xPopTaggedAddr() ((xSp++,xSp+=sizeofW(StgAddr), \
390 (StgAddr)(*(xSp-sizeofW(StgAddr)))))
392 #define xPushTaggedStable(xxx) { xSp -= sizeofW(StgStablePtr); \
393 *xSp = (StgWord)(xxx); xPushTag(STABLE_TAG); }
394 #define xTaggedStackStable(iii) ((StgStablePtr)(*(xSp+1+(iii))))
395 #define xPopTaggedStable() ((xSp++,xSp+=sizeofW(StgStablePtr), \
396 (StgStablePtr)(*(xSp-sizeofW(StgStablePtr)))))
398 #define xPushTaggedChar(xxx) { xSp -= sizeofW(StgChar); \
399 *xSp = (StgWord)(xxx); xPushTag(CHAR_TAG); }
400 #define xTaggedStackChar(iii) ((StgChar)(*(xSp+1+(iii))))
401 #define xPopTaggedChar() ((xSp++,xSp+=sizeofW(StgChar), \
402 (StgChar)(*(xSp-sizeofW(StgChar)))))
404 #define xPushTaggedFloat(xxx) { xSp -= sizeofW(StgFloat); \
405 ASSIGN_FLT(xSp,xxx); xPushTag(FLOAT_TAG); }
406 #define xTaggedStackFloat(iii) PK_FLT(xSp+1+(iii))
407 #define xPopTaggedFloat() ((xSp++,xSp+=sizeofW(StgFloat), \
408 PK_FLT(xSp-sizeofW(StgFloat))))
410 #define xPushTaggedDouble(xxx) { xSp -= sizeofW(StgDouble); \
411 ASSIGN_DBL(xSp,xxx); xPushTag(DOUBLE_TAG); }
412 #define xTaggedStackDouble(iii) PK_DBL(xSp+1+(iii))
413 #define xPopTaggedDouble() ((xSp++,xSp+=sizeofW(StgDouble), \
414 PK_DBL(xSp-sizeofW(StgDouble))))
417 #define xPushUpdateFrame(target, xSp_offset) \
419 StgUpdateFrame *__frame; \
420 __frame = (StgUpdateFrame *)(xSp + (xSp_offset)) - 1; \
421 SET_INFO(__frame, (StgInfoTable *)&Upd_frame_info); \
422 __frame->link = xSu; \
423 __frame->updatee = (StgClosure *)(target); \
427 #define xPopUpdateFrame(ooo) \
429 /* NB: doesn't assume that Sp == Su */ \
430 IF_DEBUG(evaluator, \
431 fprintf(stderr, "Updating "); \
432 printPtr(stgCast(StgPtr,xSu->updatee)); \
433 fprintf(stderr, " with "); \
435 fprintf(stderr,"xSp = %p\txSu = %p\n\n", xSp, xSu); \
437 UPD_IND(xSu->updatee,ooo); \
438 xSp = stgCast(StgStackPtr,xSu) + sizeofW(StgUpdateFrame); \
444 /* Instruction stream macros */
445 #define BCO_INSTR_8 *bciPtr++
446 #define BCO_INSTR_16 ((bciPtr += 2, (*(bciPtr-2) << 8) + *(bciPtr-1)))
447 #define PC (bciPtr - &(bcoInstr(bco,0)))
450 /* State on entry to enter():
451 * - current thread is in cap->rCurrentTSO;
452 * - allocation area is in cap->rCurrentNursery & cap->rNursery
455 StgThreadReturnCode enter( Capability* cap, StgClosure* obj0 )
457 /* use of register here is primarily to make it clear to compilers
458 that these entities are non-aliasable.
460 register StgPtr xSp; /* local state -- stack pointer */
461 register StgUpdateFrame* xSu; /* local state -- frame pointer */
462 register StgPtr xSpLim; /* local state -- stack lim pointer */
463 register StgClosure* obj; /* object currently under evaluation */
464 char eCount; /* enter counter, for context switching */
467 HugsBlock hugsBlock = { NotBlocked, 0 };
471 StgPtr tSp; StgUpdateFrame* tSu; StgPtr tSpLim;
474 gSp = cap->rCurrentTSO->sp;
475 gSu = cap->rCurrentTSO->su;
476 gSpLim = cap->rCurrentTSO->splim;
479 /* use the t values to check that Su/Sp/SpLim do not change unexpectedly */
480 tSp = gSp; tSu = gSu; tSpLim = gSpLim;
486 /* Load the local state from global state, and Party On, Dudes! */
487 /* From here onwards, we operate with the local state and
488 save/reload it as necessary.
499 assert(gSpLim == tSpLim);
503 ASSERT(xSpLim <= xSp && xSp <= stgCast(StgPtr,xSu));
505 "\n---------------------------------------------------------------\n");
506 fprintf(stderr,"(%d) Entering: ",enterCountI); printObj(obj);
507 fprintf(stderr,"xSp = %p\txSu = %p\n", xSp, xSu);
508 fprintf(stderr, "\n" );
509 printStack(xSp,cap->rCurrentTSO->stack+cap->rCurrentTSO->stack_size,xSu);
510 fprintf(stderr, "\n\n");
517 ((++eCount) & 0x0F) == 0
522 if (context_switch) {
523 switch(hugsBlock.reason) {
525 xPushCPtr(obj); /* code to restart with */
526 RETURN(ThreadYielding);
528 case BlockedOnDelay: /* fall through */
529 case BlockedOnRead: /* fall through */
530 case BlockedOnWrite: {
531 ASSERT(cap->rCurrentTSO->why_blocked == NotBlocked);
532 cap->rCurrentTSO->why_blocked = BlockedOnDelay;
533 ACQUIRE_LOCK(&sched_mutex);
535 #if defined(HAVE_SETITIMER) || defined(mingw32_TARGET_OS)
536 cap->rCurrentTSO->block_info.delay
537 = hugsBlock.delay + ticks_since_select;
539 cap->rCurrentTSO->block_info.target
540 = hugsBlock.delay + getourtimeofday();
542 APPEND_TO_BLOCKED_QUEUE(cap->rCurrentTSO);
544 RELEASE_LOCK(&sched_mutex);
546 xPushCPtr(obj); /* code to restart with */
547 RETURN(ThreadBlocked);
550 barf("Unknown context switch reasoning");
555 switch ( get_itbl(obj)->type ) {
557 barf("Invalid object %p",obj);
561 /* ---------------------------------------------------- */
562 /* Start of the bytecode evaluator */
563 /* ---------------------------------------------------- */
566 # define Ins(x) &&l##x
567 static void *labs[] = { INSTRLIST };
569 # define LoopTopLabel
570 # define Case(x) l##x
571 # define Continue goto *labs[BCO_INSTR_8]
572 # define Dispatch Continue;
575 # define LoopTopLabel insnloop:
576 # define Case(x) case x
577 # define Continue goto insnloop
578 # define Dispatch switch (BCO_INSTR_8) {
579 # define EndDispatch }
582 register StgWord8* bciPtr; /* instruction pointer */
583 register StgBCO* bco = (StgBCO*)obj;
586 /* Don't need to SSS ... LLL around doYouWantToGC */
587 wantToGC = doYouWantToGC();
589 xPushCPtr((StgClosure*)bco); /* code to restart with */
590 RETURN(HeapOverflow);
598 bciPtr = &(bcoInstr(bco,0));
602 ASSERT((StgWord)(PC) < bco->n_instrs);
604 fprintf(stderr,"Sp = %p\tSu = %p\tpc = %d\t", xSp, xSu, PC);
608 fprintf(stderr,"\n");
609 for (i = 8; i >= 0; i--)
610 fprintf(stderr, "%d %p\n", i, (StgPtr)(*(gSp+i)));
612 fprintf(stderr,"\n");
617 SSS; cp_bill_insns(1); LLL;
622 Case(i_INTERNAL_ERROR):
623 barf("INTERNAL_ERROR at %p:%d",bco,PC-1);
625 barf("PANIC at %p:%d",bco,PC-1);
629 if (xSp - n < xSpLim) {
630 xPushCPtr((StgClosure*)bco); /* code to restart with */
631 RETURN(StackOverflow);
635 Case(i_STK_CHECK_big):
637 int n = BCO_INSTR_16;
638 if (xSp - n < xSpLim) {
639 xPushCPtr((StgClosure*)bco); /* code to restart with */
640 RETURN(StackOverflow);
647 if ((StgPtr*)(xSp + n) > (StgPtr*)xSu) {
648 StgWord words = (P_)xSu - xSp;
650 /* first build a PAP */
651 ASSERT((P_)xSu >= xSp); /* was (words >= 0) but that's always true */
652 if (words == 0) { /* optimisation */
653 /* Skip building the PAP and update with an indirection. */
656 /* In the evaluator, we avoid the need to do
657 * a heap check here by including the size of
658 * the PAP in the heap check we performed
659 * when we entered the BCO.
663 SSS; pap = (StgPAP*)grabHpNonUpd(PAP_sizeW(words)); LLL;
664 SET_HDR(pap,&PAP_info,CC_pap);
667 for (i = 0; i < (I_)words; ++i) {
668 payloadWord(pap,i) = xSp[i];
671 obj = stgCast(StgClosure*,pap);
674 /* now deal with "update frame" */
675 /* as an optimisation, we process all on top of stack */
676 /* instead of just the top one */
677 ASSERT(xSp==(P_)xSu);
679 switch (get_itbl(xSu)->type) {
681 /* Hit a catch frame during an arg satisfaction check,
682 * so the thing returning (1) has not thrown an
683 * exception, and (2) is of functional type. Just
684 * zap the catch frame and carry on down the stack
685 * (looking for more arguments, basically).
687 SSS; PopCatchFrame(); LLL;
690 xPopUpdateFrame(obj);
693 barf("STOP frame during pap update");
695 cap->rCurrentTSO->what_next = ThreadComplete;
696 SSS; PopStopFrame(obj); LLL;
697 RETURN(ThreadFinished);
700 SSS; PopSeqFrame(); LLL;
701 ASSERT(xSp != (P_)xSu);
702 /* Hit a SEQ frame during an arg satisfaction check.
703 * So now return to bco_info which is under the
704 * SEQ frame. The following code is copied from a
705 * case RET_BCO further down. (The reason why we're
706 * here is that something of functional type has
707 * been seq-d on, and we're now returning to the
708 * algebraic-case-continuation which forced the
709 * evaluation in the first place.)
721 barf("Invalid update frame during argcheck");
723 } while (xSp==(P_)xSu);
731 int words = BCO_INSTR_8;
732 SSS; p = grabHpUpd(AP_sizeW(words)); LLL;
736 Case(i_ALLOC_CONSTR):
739 StgInfoTable* info = bcoConstAddr(bco,BCO_INSTR_8);
740 SSS; p = grabHpNonUpd(sizeW_fromITBL(info)); LLL;
741 SET_HDR((StgClosure*)p,info,??);
745 Case(i_ALLOC_CONSTR_big):
748 int x = BCO_INSTR_16;
749 StgInfoTable* info = bcoConstAddr(bco,x);
750 SSS; p = grabHpNonUpd(sizeW_fromITBL(info)); LLL;
751 SET_HDR((StgClosure*)p,info,??);
757 int x = BCO_INSTR_8; /* ToDo: Word not Int! */
759 StgAP_UPD* o = stgCast(StgAP_UPD*,xStackPtr(x));
760 SET_HDR(o,&AP_UPD_info,??);
762 o->fun = stgCast(StgClosure*,xPopPtr());
763 for(x=0; x < y; ++x) {
764 payloadWord(o,x) = xPopWord();
767 fprintf(stderr,"\tBuilt ");
769 printObj(stgCast(StgClosure*,o));
780 o = stgCast(StgAP_UPD*,xStackPtr(x));
781 SET_HDR(o,&AP_UPD_info,??);
783 o->fun = stgCast(StgClosure*,xPopPtr());
784 for(x=0; x < y; ++x) {
785 payloadWord(o,x) = xPopWord();
788 fprintf(stderr,"\tBuilt ");
790 printObj(stgCast(StgClosure*,o));
799 StgPAP* o = stgCast(StgPAP*,xStackPtr(x));
800 SET_HDR(o,&PAP_info,??);
802 o->fun = stgCast(StgClosure*,xPopPtr());
803 for(x=0; x < y; ++x) {
804 payloadWord(o,x) = xPopWord();
807 fprintf(stderr,"\tBuilt ");
809 printObj(stgCast(StgClosure*,o));
816 int offset = BCO_INSTR_8;
817 StgClosure* o = stgCast(StgClosure*,xStackPtr(offset));
818 const StgInfoTable* info = get_itbl(o);
819 nat p = info->layout.payload.ptrs;
820 nat np = info->layout.payload.nptrs;
822 for(i=0; i < p; ++i) {
823 o->payload[i] = xPopCPtr();
825 for(i=0; i < np; ++i) {
826 payloadWord(o,p+i) = 0xdeadbeef;
829 fprintf(stderr,"\tBuilt ");
831 printObj(stgCast(StgClosure*,o));
838 int offset = BCO_INSTR_16;
839 StgClosure* o = stgCast(StgClosure*,xStackPtr(offset));
840 const StgInfoTable* info = get_itbl(o);
841 nat p = info->layout.payload.ptrs;
842 nat np = info->layout.payload.nptrs;
844 for(i=0; i < p; ++i) {
845 o->payload[i] = xPopCPtr();
847 for(i=0; i < np; ++i) {
848 payloadWord(o,p+i) = 0xdeadbeef;
851 fprintf(stderr,"\tBuilt ");
853 printObj(stgCast(StgClosure*,o));
862 ASSERT(xSp+x+y <= stgCast(StgPtr,xSu));
863 /* a_1, .. a_x, b_1, .. b_y, s => a_1, .. a_x, s */
865 xSetStackWord(x+y,xStackWord(x));
875 ASSERT(xSp+x+y <= stgCast(StgPtr,xSu));
876 /* a_1, .. a_x, b_1, .. b_y, s => a_1, .. a_x, s */
878 xSetStackWord(x+y,xStackWord(x));
890 xPushPtr(bcoConstPtr(bco,BCO_INSTR_8));
891 xPushPtr(stgCast(StgPtr,&ret_bco_info));
896 int tag = BCO_INSTR_8;
897 StgWord offset = BCO_INSTR_16;
898 if (constrTag( (StgClosure*)xStackPtr(0) ) != tag) {
905 StgClosure* o = stgCast(StgClosure*,xStackPtr(0));
906 const StgInfoTable* itbl = get_itbl(o);
907 int i = itbl->layout.payload.ptrs;
908 ASSERT( itbl->type == CONSTR
909 || itbl->type == CONSTR_STATIC
910 || itbl->type == CONSTR_NOCAF_STATIC
911 || itbl->type == CONSTR_1_0
912 || itbl->type == CONSTR_0_1
913 || itbl->type == CONSTR_2_0
914 || itbl->type == CONSTR_1_1
915 || itbl->type == CONSTR_0_2
918 xPushCPtr(o->payload[i]);
924 int n = BCO_INSTR_16;
925 StgPtr p = xStackPtr(n);
931 StgPtr p = xStackPtr(BCO_INSTR_8);
937 xPushPtr(stgCast(StgPtr,bcoConstPtr(bco,BCO_INSTR_8)));
942 int n = BCO_INSTR_16;
943 xPushPtr(stgCast(StgPtr,bcoConstPtr(bco,n)));
948 SSS; PushTaggedRealWorld(); LLL;
953 StgInt i = xTaggedStackInt(BCO_INSTR_8);
959 xPushTaggedInt(bcoConstInt(bco,BCO_INSTR_8));
962 Case(i_CONST_INT_big):
964 int n = BCO_INSTR_16;
965 xPushTaggedInt(bcoConstInt(bco,n));
971 SSS; o = (StgClosure*)grabHpNonUpd(Izh_sizeW); LLL;
972 SET_HDR(o,Izh_con_info,??);
973 payloadWord(o,0) = xPopTaggedInt();
975 fprintf(stderr,"\tBuilt ");
977 printObj(stgCast(StgClosure*,o));
980 xPushPtr(stgCast(StgPtr,o));
985 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
986 /* ASSERT(isIntLike(con)); */
987 xPushTaggedInt(payloadWord(con,0));
992 StgWord offset = BCO_INSTR_16;
993 StgInt x = xPopTaggedInt();
994 StgInt y = xPopTaggedInt();
1000 Case(i_CONST_INTEGER):
1004 char* s = bcoConstAddr(bco,BCO_INSTR_8);
1006 n = size_fromStr(s);
1007 p = CreateByteArrayToHoldInteger(n);
1008 do_fromStr ( s, n, IntegerInsideByteArray(p));
1009 SloppifyIntegerEnd(p);
1016 StgWord w = xTaggedStackWord(BCO_INSTR_8);
1022 xPushTaggedWord(bcoConstWord(bco,BCO_INSTR_8));
1028 SSS; o = (StgClosure*)grabHpNonUpd(Wzh_sizeW); LLL;
1029 SET_HDR(o,Wzh_con_info,??);
1030 payloadWord(o,0) = xPopTaggedWord();
1032 fprintf(stderr,"\tBuilt ");
1034 printObj(stgCast(StgClosure*,o));
1037 xPushPtr(stgCast(StgPtr,o));
1040 Case(i_UNPACK_WORD):
1042 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1043 /* ASSERT(isWordLike(con)); */
1044 xPushTaggedWord(payloadWord(con,0));
1049 StgAddr a = xTaggedStackAddr(BCO_INSTR_8);
1055 xPushTaggedAddr(bcoConstAddr(bco,BCO_INSTR_8));
1058 Case(i_CONST_ADDR_big):
1060 int n = BCO_INSTR_16;
1061 xPushTaggedAddr(bcoConstAddr(bco,n));
1067 SSS; o = (StgClosure*)grabHpNonUpd(Azh_sizeW); LLL;
1068 SET_HDR(o,Azh_con_info,??);
1069 payloadPtr(o,0) = xPopTaggedAddr();
1071 fprintf(stderr,"\tBuilt ");
1073 printObj(stgCast(StgClosure*,o));
1076 xPushPtr(stgCast(StgPtr,o));
1079 Case(i_UNPACK_ADDR):
1081 StgClosure* con = (StgClosure*)xStackPtr(0);
1082 /* ASSERT(isAddrLike(con)); */
1083 xPushTaggedAddr(payloadPtr(con,0));
1088 StgChar c = xTaggedStackChar(BCO_INSTR_8);
1094 xPushTaggedChar(bcoConstChar(bco,BCO_INSTR_8));
1100 SSS; o = (StgClosure*)grabHpNonUpd(Czh_sizeW); LLL;
1101 SET_HDR(o,Czh_con_info,??);
1102 payloadWord(o,0) = xPopTaggedChar();
1103 xPushPtr(stgCast(StgPtr,o));
1105 fprintf(stderr,"\tBuilt ");
1107 printObj(stgCast(StgClosure*,o));
1112 Case(i_UNPACK_CHAR):
1114 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1115 /* ASSERT(isCharLike(con)); */
1116 xPushTaggedChar(payloadWord(con,0));
1121 StgFloat f = xTaggedStackFloat(BCO_INSTR_8);
1122 xPushTaggedFloat(f);
1125 Case(i_CONST_FLOAT):
1127 xPushTaggedFloat(bcoConstFloat(bco,BCO_INSTR_8));
1133 SSS; o = (StgClosure*)grabHpNonUpd(Fzh_sizeW); LLL;
1134 SET_HDR(o,Fzh_con_info,??);
1135 ASSIGN_FLT(&payloadWord(o,0),xPopTaggedFloat());
1137 fprintf(stderr,"\tBuilt ");
1139 printObj(stgCast(StgClosure*,o));
1142 xPushPtr(stgCast(StgPtr,o));
1145 Case(i_UNPACK_FLOAT):
1147 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1148 /* ASSERT(isFloatLike(con)); */
1149 xPushTaggedFloat(PK_FLT(&payloadWord(con,0)));
1154 StgDouble d = xTaggedStackDouble(BCO_INSTR_8);
1155 xPushTaggedDouble(d);
1158 Case(i_CONST_DOUBLE):
1160 xPushTaggedDouble(bcoConstDouble(bco,BCO_INSTR_8));
1163 Case(i_CONST_DOUBLE_big):
1165 int n = BCO_INSTR_16;
1166 xPushTaggedDouble(bcoConstDouble(bco,n));
1169 Case(i_PACK_DOUBLE):
1172 SSS; o = (StgClosure*)grabHpNonUpd(Dzh_sizeW); LLL;
1173 SET_HDR(o,Dzh_con_info,??);
1174 ASSIGN_DBL(&payloadWord(o,0),xPopTaggedDouble());
1176 fprintf(stderr,"\tBuilt ");
1177 printObj(stgCast(StgClosure*,o));
1179 xPushPtr(stgCast(StgPtr,o));
1182 Case(i_UNPACK_DOUBLE):
1184 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1185 /* ASSERT(isDoubleLike(con)); */
1186 xPushTaggedDouble(PK_DBL(&payloadWord(con,0)));
1191 StgStablePtr s = xTaggedStackStable(BCO_INSTR_8);
1192 xPushTaggedStable(s);
1195 Case(i_PACK_STABLE):
1198 SSS; o = (StgClosure*)grabHpNonUpd(Stablezh_sizeW); LLL;
1199 SET_HDR(o,StablePtr_con_info,??);
1200 payloadWord(o,0) = xPopTaggedStable();
1202 fprintf(stderr,"\tBuilt ");
1204 printObj(stgCast(StgClosure*,o));
1207 xPushPtr(stgCast(StgPtr,o));
1210 Case(i_UNPACK_STABLE):
1212 StgClosure* con = (StgClosure*)xStackPtr(0);
1213 /* ASSERT(isStableLike(con)); */
1214 xPushTaggedStable(payloadWord(con,0));
1222 SSS; p = enterBCO_primop1 ( i ); LLL;
1223 if (p) { obj = p; goto enterLoop; };
1228 int i, trc, pc_saved;
1231 trc = 12345678; /* Assume != any StgThreadReturnCode */
1236 p = enterBCO_primop2 ( i, &trc, &bco_tmp, cap,
1240 bciPtr = &(bcoInstr(bco,pc_saved));
1242 if (trc == 12345678) {
1243 /* we want to enter p */
1244 obj = p; goto enterLoop;
1246 /* trc is the the StgThreadReturnCode for
1248 RETURN((StgThreadReturnCode)trc);
1254 /* combined insns, created by peephole opt */
1257 int x = BCO_INSTR_8;
1258 int y = BCO_INSTR_8;
1259 ASSERT(xSp+x+y <= stgCast(StgPtr,xSu));
1260 /* a_1, .. a_x, b_1, .. b_y, s => a_1, .. a_x, s */
1267 xSetStackWord(x+y,xStackWord(x));
1277 p = xStackPtr(BCO_INSTR_8);
1279 p = xStackPtr(BCO_INSTR_8);
1286 xPushPtr(bcoConstPtr(bco,BCO_INSTR_8));
1287 xPushPtr(stgCast(StgPtr,&ret_bco_info));
1288 p = xStackPtr(BCO_INSTR_8);
1294 StgPtr retaddr = bcoConstPtr(bco,BCO_INSTR_8);
1295 StgPtr ptr = xStackPtr(BCO_INSTR_8);
1297 /* A shortcut. We're going to push the address of a
1298 return continuation, and then enter a variable, so
1299 that when the var is evaluated, we return to the
1300 continuation. The shortcut is: if the var is a
1301 constructor, don't bother to enter it. Instead,
1302 push the variable on the stack (since this is what
1303 the continuation expects) and jump directly to the
1306 if (get_itbl((StgClosure*)ptr)->type == CONSTR) {
1308 obj = (StgClosure*)retaddr;
1310 fprintf(stderr, "object to enter is a constructor -- "
1311 "jumping directly to return continuation\n" );
1316 /* This is the normal, non-short-cut route */
1318 xPushPtr(stgCast(StgPtr,&ret_bco_info));
1319 obj = (StgClosure*)ptr;
1324 Case(i_VAR_DOUBLE_big):
1325 Case(i_CONST_FLOAT_big):
1326 Case(i_VAR_FLOAT_big):
1327 Case(i_CONST_CHAR_big):
1328 Case(i_VAR_CHAR_big):
1329 Case(i_VAR_ADDR_big):
1330 Case(i_VAR_STABLE_big):
1331 Case(i_CONST_INTEGER_big):
1332 Case(i_VAR_INT_big):
1333 Case(i_VAR_WORD_big):
1334 Case(i_RETADDR_big):
1338 disInstr ( bco, PC );
1339 barf("\nUnrecognised instruction");
1343 barf("enterBCO: ran off end of loop");
1347 # undef LoopTopLabel
1353 /* ---------------------------------------------------- */
1354 /* End of the bytecode evaluator */
1355 /* ---------------------------------------------------- */
1359 StgBlockingQueue* bh;
1360 StgCAF* caf = (StgCAF*)obj;
1361 if (xSp - sizeofW(StgUpdateFrame) < xSpLim) {
1362 xPushCPtr(obj); /* code to restart with */
1363 RETURN(StackOverflow);
1365 SSS; bh = (StgBlockingQueue*)grabHpUpd(BLACKHOLE_sizeW()); LLL;
1366 SET_INFO(bh,&CAF_BLACKHOLE_info);
1367 bh->blocking_queue = EndTSOQueue;
1369 fprintf(stderr,"Created CAF_BLACKHOLE %p for CAF %p"
1370 " in evaluator\n",bh,caf));
1371 SET_INFO(caf,&CAF_ENTERED_info);
1372 caf->value = (StgClosure*)bh;
1374 SSS; newCAF_made_by_Hugs(caf); LLL;
1376 xPushUpdateFrame(bh,0);
1377 xSp -= sizeofW(StgUpdateFrame);
1383 StgCAF* caf = (StgCAF*)obj;
1384 obj = caf->value; /* it's just a fancy indirection */
1390 case SE_CAF_BLACKHOLE:
1392 /* Let the scheduler figure out what to do :-) */
1393 cap->rCurrentTSO->what_next = ThreadEnterGHC;
1395 RETURN(ThreadYielding);
1399 StgAP_UPD* ap = stgCast(StgAP_UPD*,obj);
1401 if (xSp - (i + sizeofW(StgUpdateFrame)) < xSpLim) {
1402 xPushCPtr(obj); /* code to restart with */
1403 RETURN(StackOverflow);
1405 /* ToDo: look for xSp==xSu && stackInt(0) == UPD_FRAME
1406 and insert an indirection immediately */
1407 xPushUpdateFrame(ap,0);
1408 xSp -= sizeofW(StgUpdateFrame);
1410 xPushWord(payloadWord(ap,i));
1413 #ifdef EAGER_BLACKHOLING
1414 #warn LAZY_BLACKHOLING is default for StgHugs
1415 #error Dont know if EAGER_BLACKHOLING works in StgHugs
1417 /* superfluous - but makes debugging easier */
1418 StgBlackHole* bh = stgCast(StgBlackHole*,ap);
1419 SET_INFO(bh,&BLACKHOLE_info);
1420 bh->blocking_queue = EndTSOQueue;
1422 fprintf(stderr,"Eagerly blackholed AP_UPD %p in evaluator\n",bh));
1425 #endif /* EAGER_BLACKHOLING */
1430 StgPAP* pap = stgCast(StgPAP*,obj);
1431 int i = pap->n_args; /* ToDo: stack check */
1432 /* ToDo: if PAP is in whnf, we can update any update frames
1436 xPushWord(payloadWord(pap,i));
1443 obj = stgCast(StgInd*,obj)->indirectee;
1448 obj = stgCast(StgIndOldGen*,obj)->indirectee;
1457 case CONSTR_INTLIKE:
1458 case CONSTR_CHARLIKE:
1460 case CONSTR_NOCAF_STATIC:
1463 switch (get_itbl(stgCast(StgClosure*,xSp))->type) {
1465 SSS; PopCatchFrame(); LLL;
1468 xPopUpdateFrame(obj);
1471 SSS; PopSeqFrame(); LLL;
1475 ASSERT(xSp==(P_)xSu);
1478 fprintf(stderr, "hit a STOP_FRAME\n");
1480 fprintf(stderr,"xSp = %p\txSu = %p\n", xSp, xSu);
1481 printStack(xSp,cap->rCurrentTSO->stack
1482 + cap->rCurrentTSO->stack_size,xSu);
1485 cap->rCurrentTSO->what_next = ThreadComplete;
1486 SSS; PopStopFrame(obj); LLL;
1488 RETURN(ThreadFinished);
1498 /* was: goto enterLoop;
1499 But we know that obj must be a bco now, so jump directly.
1502 case RET_SMALL: /* return to GHC */
1506 cap->rCurrentTSO->what_next = ThreadEnterGHC;
1508 RETURN(ThreadYielding);
1510 belch("entered CONSTR with invalid continuation on stack");
1513 printObj(stgCast(StgClosure*,xSp));
1516 barf("bailing out");
1523 //fprintf(stderr, "enterCountI = %d\n", enterCountI);
1524 //fprintf(stderr, "entering unknown closure -- yielding to sched\n");
1527 cap->rCurrentTSO->what_next = ThreadEnterGHC;
1528 xPushCPtr(obj); /* code to restart with */
1529 RETURN(ThreadYielding);
1532 barf("Ran off the end of enter - yoiks");
1549 #undef xSetStackWord
1552 #undef xPushTaggedInt
1553 #undef xPopTaggedInt
1554 #undef xTaggedStackInt
1555 #undef xPushTaggedWord
1556 #undef xPopTaggedWord
1557 #undef xTaggedStackWord
1558 #undef xPushTaggedAddr
1559 #undef xTaggedStackAddr
1560 #undef xPopTaggedAddr
1561 #undef xPushTaggedStable
1562 #undef xTaggedStackStable
1563 #undef xPopTaggedStable
1564 #undef xPushTaggedChar
1565 #undef xTaggedStackChar
1566 #undef xPopTaggedChar
1567 #undef xPushTaggedFloat
1568 #undef xTaggedStackFloat
1569 #undef xPopTaggedFloat
1570 #undef xPushTaggedDouble
1571 #undef xTaggedStackDouble
1572 #undef xPopTaggedDouble
1573 #undef xPopUpdateFrame
1574 #undef xPushUpdateFrame
1577 /* --------------------------------------------------------------------------
1578 * Supporting routines for primops
1579 * ------------------------------------------------------------------------*/
1581 static inline void PushTag ( StackTag t )
1583 inline void PushPtr ( StgPtr x )
1584 { *(--stgCast(StgPtr*,gSp)) = x; }
1585 static inline void PushCPtr ( StgClosure* x )
1586 { *(--stgCast(StgClosure**,gSp)) = x; }
1587 static inline void PushInt ( StgInt x )
1588 { *(--stgCast(StgInt*,gSp)) = x; }
1589 static inline void PushWord ( StgWord x )
1590 { *(--stgCast(StgWord*,gSp)) = x; }
1593 static inline void checkTag ( StackTag t1, StackTag t2 )
1594 { ASSERT(t1 == t2);}
1595 static inline void PopTag ( StackTag t )
1596 { checkTag(t,*(gSp++)); }
1597 inline StgPtr PopPtr ( void )
1598 { return *stgCast(StgPtr*,gSp)++; }
1599 static inline StgClosure* PopCPtr ( void )
1600 { return *stgCast(StgClosure**,gSp)++; }
1601 static inline StgInt PopInt ( void )
1602 { return *stgCast(StgInt*,gSp)++; }
1603 static inline StgWord PopWord ( void )
1604 { return *stgCast(StgWord*,gSp)++; }
1606 static inline StgPtr stackPtr ( StgStackOffset i )
1607 { return *stgCast(StgPtr*, gSp+i); }
1608 static inline StgInt stackInt ( StgStackOffset i )
1609 { return *stgCast(StgInt*, gSp+i); }
1610 static inline StgWord stackWord ( StgStackOffset i )
1611 { return *stgCast(StgWord*,gSp+i); }
1613 static inline void setStackWord ( StgStackOffset i, StgWord w )
1616 static inline void PushTaggedRealWorld( void )
1617 { PushTag(REALWORLD_TAG); }
1618 inline void PushTaggedInt ( StgInt x )
1619 { gSp -= sizeofW(StgInt); *gSp = x; PushTag(INT_TAG); }
1620 inline void PushTaggedWord ( StgWord x )
1621 { gSp -= sizeofW(StgWord); *gSp = x; PushTag(WORD_TAG); }
1622 inline void PushTaggedAddr ( StgAddr x )
1623 { gSp -= sizeofW(StgAddr); *gSp = (W_)x; PushTag(ADDR_TAG); }
1624 inline void PushTaggedChar ( StgChar x )
1625 { gSp -= sizeofW(StgChar); *gSp = stgCast(StgWord,x); PushTag(CHAR_TAG); }
1626 inline void PushTaggedFloat ( StgFloat x )
1627 { gSp -= sizeofW(StgFloat); ASSIGN_FLT(gSp,x); PushTag(FLOAT_TAG); }
1628 inline void PushTaggedDouble ( StgDouble x )
1629 { gSp -= sizeofW(StgDouble); ASSIGN_DBL(gSp,x); PushTag(DOUBLE_TAG); }
1630 inline void PushTaggedStablePtr ( StgStablePtr x )
1631 { gSp -= sizeofW(StgStablePtr); *gSp = x; PushTag(STABLE_TAG); }
1632 static inline void PushTaggedBool ( int x )
1633 { PushTaggedInt(x); }
1637 static inline void PopTaggedRealWorld ( void )
1638 { PopTag(REALWORLD_TAG); }
1639 inline StgInt PopTaggedInt ( void )
1640 { StgInt r; PopTag(INT_TAG); r = *stgCast(StgInt*, gSp);
1641 gSp += sizeofW(StgInt); return r;}
1642 inline StgWord PopTaggedWord ( void )
1643 { StgWord r; PopTag(WORD_TAG); r = *stgCast(StgWord*, gSp);
1644 gSp += sizeofW(StgWord); return r;}
1645 inline StgAddr PopTaggedAddr ( void )
1646 { StgAddr r; PopTag(ADDR_TAG); r = *stgCast(StgAddr*, gSp);
1647 gSp += sizeofW(StgAddr); return r;}
1648 inline StgChar PopTaggedChar ( void )
1649 { StgChar r; PopTag(CHAR_TAG); r = stgCast(StgChar, *gSp);
1650 gSp += sizeofW(StgChar); return r;}
1651 inline StgFloat PopTaggedFloat ( void )
1652 { StgFloat r; PopTag(FLOAT_TAG); r = PK_FLT(gSp);
1653 gSp += sizeofW(StgFloat); return r;}
1654 inline StgDouble PopTaggedDouble ( void )
1655 { StgDouble r; PopTag(DOUBLE_TAG); r = PK_DBL(gSp);
1656 gSp += sizeofW(StgDouble); return r;}
1657 inline StgStablePtr PopTaggedStablePtr ( void )
1658 { StgInt r; PopTag(STABLE_TAG); r = *stgCast(StgStablePtr*, gSp);
1659 gSp += sizeofW(StgStablePtr); return r;}
1663 static inline StgInt taggedStackInt ( StgStackOffset i )
1664 { checkTag(INT_TAG,gSp[i]); return *stgCast(StgInt*, gSp+1+i); }
1665 static inline StgWord taggedStackWord ( StgStackOffset i )
1666 { checkTag(WORD_TAG,gSp[i]); return *stgCast(StgWord*, gSp+1+i); }
1667 static inline StgAddr taggedStackAddr ( StgStackOffset i )
1668 { checkTag(ADDR_TAG,gSp[i]); return *stgCast(StgAddr*, gSp+1+i); }
1669 static inline StgChar taggedStackChar ( StgStackOffset i )
1670 { checkTag(CHAR_TAG,gSp[i]); return stgCast(StgChar, *(gSp+1+i)) ; }
1671 static inline StgFloat taggedStackFloat ( StgStackOffset i )
1672 { checkTag(FLOAT_TAG,gSp[i]); return PK_FLT(gSp+1+i); }
1673 static inline StgDouble taggedStackDouble ( StgStackOffset i )
1674 { checkTag(DOUBLE_TAG,gSp[i]); return PK_DBL(gSp+1+i); }
1675 static inline StgStablePtr taggedStackStable ( StgStackOffset i )
1676 { checkTag(STABLE_TAG,gSp[i]); return *stgCast(StgStablePtr*, gSp+1+i); }
1679 /* --------------------------------------------------------------------------
1682 * Should we allocate from a nursery or use the
1683 * doYouWantToGC/allocate interface? We'd already implemented a
1684 * nursery-style scheme when the doYouWantToGC/allocate interface
1686 * One reason to prefer the doYouWantToGC/allocate interface is to
1687 * support operations which allocate an unknown amount in the heap
1688 * (array ops, gmp ops, etc)
1689 * ------------------------------------------------------------------------*/
1691 static inline StgPtr grabHpUpd( nat size )
1693 ASSERT( size >= MIN_UPD_SIZE + sizeofW(StgHeader) );
1694 #ifdef CRUDE_PROFILING
1695 cp_bill_words ( size );
1697 return allocate(size);
1700 static inline StgPtr grabHpNonUpd( nat size )
1702 ASSERT( size >= MIN_NONUPD_SIZE + sizeofW(StgHeader) );
1703 #ifdef CRUDE_PROFILING
1704 cp_bill_words ( size );
1706 return allocate(size);
1709 /* --------------------------------------------------------------------------
1710 * Manipulate "update frame" list:
1711 * o Update frames (based on stg_do_update and friends in Updates.hc)
1712 * o Error handling/catching (based on catchzh_fast and friends in Prims.hc)
1713 * o Seq frames (based on seq_frame_entry in Prims.hc)
1715 * ------------------------------------------------------------------------*/
1717 static inline void PopUpdateFrame ( StgClosure* obj )
1719 /* NB: doesn't assume that gSp == gSu */
1721 fprintf(stderr, "Updating ");
1722 printPtr(stgCast(StgPtr,gSu->updatee));
1723 fprintf(stderr, " with ");
1725 fprintf(stderr,"gSp = %p\tgSu = %p\n\n", gSp, gSu);
1727 #ifdef EAGER_BLACKHOLING
1728 #warn LAZY_BLACKHOLING is default for StgHugs
1729 #error Dont know if EAGER_BLACKHOLING works in StgHugs
1730 ASSERT(get_itbl(gSu->updatee)->type == BLACKHOLE
1731 || get_itbl(gSu->updatee)->type == SE_BLACKHOLE
1732 || get_itbl(gSu->updatee)->type == CAF_BLACKHOLE
1733 || get_itbl(gSu->updatee)->type == SE_CAF_BLACKHOLE
1735 #endif /* EAGER_BLACKHOLING */
1736 UPD_IND(gSu->updatee,obj);
1737 gSp = stgCast(StgStackPtr,gSu) + sizeofW(StgUpdateFrame);
1741 static inline void PopStopFrame ( StgClosure* obj )
1743 /* Move gSu just off the end of the stack, we're about to gSpam the
1744 * STOP_FRAME with the return value.
1746 gSu = stgCast(StgUpdateFrame*,gSp+1);
1747 *stgCast(StgClosure**,gSp) = obj;
1750 static inline void PushCatchFrame ( StgClosure* handler )
1753 /* ToDo: stack check! */
1754 gSp -= sizeofW(StgCatchFrame);
1755 fp = stgCast(StgCatchFrame*,gSp);
1756 SET_HDR(fp,(StgInfoTable*)&catch_frame_info,CCCS);
1757 fp->handler = handler;
1759 gSu = stgCast(StgUpdateFrame*,fp);
1762 static inline void PopCatchFrame ( void )
1764 /* NB: doesn't assume that gSp == gSu */
1765 /* fprintf(stderr,"Popping catch frame\n"); */
1766 gSp = stgCast(StgStackPtr,gSu) + sizeofW(StgCatchFrame);
1767 gSu = stgCast(StgCatchFrame*,gSu)->link;
1770 static inline void PushSeqFrame ( void )
1773 /* ToDo: stack check! */
1774 gSp -= sizeofW(StgSeqFrame);
1775 fp = stgCast(StgSeqFrame*,gSp);
1776 SET_HDR(fp,(StgInfoTable*)&seq_frame_info,CCCS);
1778 gSu = stgCast(StgUpdateFrame*,fp);
1781 static inline void PopSeqFrame ( void )
1783 /* NB: doesn't assume that gSp == gSu */
1784 gSp = stgCast(StgStackPtr,gSu) + sizeofW(StgSeqFrame);
1785 gSu = stgCast(StgSeqFrame*,gSu)->link;
1788 static inline StgClosure* raiseAnError ( StgClosure* exception )
1790 /* This closure represents the expression 'primRaise E' where E
1791 * is the exception raised (:: Exception).
1792 * It is used to overwrite all the
1793 * thunks which are currently under evaluation.
1795 HaskellObj primRaiseClosure
1796 = getHugs_BCO_cptr_for("primRaise");
1797 HaskellObj reraiseClosure
1798 = rts_apply ( primRaiseClosure, exception );
1801 switch (get_itbl(gSu)->type) {
1803 UPD_IND(gSu->updatee,reraiseClosure);
1804 gSp = stgCast(StgStackPtr,gSu) + sizeofW(StgUpdateFrame);
1810 case CATCH_FRAME: /* found it! */
1812 StgCatchFrame* fp = stgCast(StgCatchFrame*,gSu);
1813 StgClosure *handler = fp->handler;
1815 gSp += sizeofW(StgCatchFrame); /* Pop */
1816 PushCPtr(exception);
1820 barf("raiseError: uncaught exception: STOP_FRAME");
1822 barf("raiseError: weird activation record");
1828 static StgClosure* makeErrorCall ( const char* msg )
1830 /* Note! the msg string should be allocated in a
1831 place which will not get freed -- preferably
1832 read-only data of the program. That's because
1833 the thunk we build here may linger indefinitely.
1834 (thinks: probably not so, but anyway ...)
1837 = getHugs_BCO_cptr_for("error");
1839 = getHugs_BCO_cptr_for("hugsprimUnpackString");
1841 = rts_apply ( unpack, rts_mkAddr ( (void*)msg ) );
1843 = rts_apply ( error, thunk );
1845 (StgClosure*) thunk;
1848 #define raiseIndex(where) makeErrorCall("Array index out of range in " where)
1849 #define raiseDiv0(where) makeErrorCall("Division by zero in " where)
1851 /* --------------------------------------------------------------------------
1853 * ------------------------------------------------------------------------*/
1855 #define OP_CC_B(e) \
1857 unsigned char x = PopTaggedChar(); \
1858 unsigned char y = PopTaggedChar(); \
1859 PushTaggedBool(e); \
1864 unsigned char x = PopTaggedChar(); \
1873 #define OP_IW_I(e) \
1875 StgInt x = PopTaggedInt(); \
1876 StgWord y = PopTaggedWord(); \
1880 #define OP_II_I(e) \
1882 StgInt x = PopTaggedInt(); \
1883 StgInt y = PopTaggedInt(); \
1887 #define OP_II_B(e) \
1889 StgInt x = PopTaggedInt(); \
1890 StgInt y = PopTaggedInt(); \
1891 PushTaggedBool(e); \
1896 PushTaggedAddr(e); \
1901 StgInt x = PopTaggedInt(); \
1902 PushTaggedAddr(e); \
1907 StgInt x = PopTaggedInt(); \
1913 PushTaggedChar(e); \
1918 StgInt x = PopTaggedInt(); \
1919 PushTaggedChar(e); \
1924 PushTaggedWord(e); \
1929 StgInt x = PopTaggedInt(); \
1930 PushTaggedWord(e); \
1935 StgInt x = PopTaggedInt(); \
1936 PushTaggedStablePtr(e); \
1941 PushTaggedFloat(e); \
1946 StgInt x = PopTaggedInt(); \
1947 PushTaggedFloat(e); \
1952 PushTaggedDouble(e); \
1957 StgInt x = PopTaggedInt(); \
1958 PushTaggedDouble(e); \
1961 #define OP_WW_B(e) \
1963 StgWord x = PopTaggedWord(); \
1964 StgWord y = PopTaggedWord(); \
1965 PushTaggedBool(e); \
1968 #define OP_WW_W(e) \
1970 StgWord x = PopTaggedWord(); \
1971 StgWord y = PopTaggedWord(); \
1972 PushTaggedWord(e); \
1977 StgWord x = PopTaggedWord(); \
1983 StgStablePtr x = PopTaggedStablePtr(); \
1989 StgWord x = PopTaggedWord(); \
1990 PushTaggedWord(e); \
1993 #define OP_AA_B(e) \
1995 StgAddr x = PopTaggedAddr(); \
1996 StgAddr y = PopTaggedAddr(); \
1997 PushTaggedBool(e); \
2001 StgAddr x = PopTaggedAddr(); \
2004 #define OP_AI_C(s) \
2006 StgAddr x = PopTaggedAddr(); \
2007 int y = PopTaggedInt(); \
2010 PushTaggedChar(r); \
2012 #define OP_AI_I(s) \
2014 StgAddr x = PopTaggedAddr(); \
2015 int y = PopTaggedInt(); \
2020 #define OP_AI_A(s) \
2022 StgAddr x = PopTaggedAddr(); \
2023 int y = PopTaggedInt(); \
2026 PushTaggedAddr(s); \
2028 #define OP_AI_F(s) \
2030 StgAddr x = PopTaggedAddr(); \
2031 int y = PopTaggedInt(); \
2034 PushTaggedFloat(r); \
2036 #define OP_AI_D(s) \
2038 StgAddr x = PopTaggedAddr(); \
2039 int y = PopTaggedInt(); \
2042 PushTaggedDouble(r); \
2044 #define OP_AI_s(s) \
2046 StgAddr x = PopTaggedAddr(); \
2047 int y = PopTaggedInt(); \
2050 PushTaggedStablePtr(r); \
2052 #define OP_AIC_(s) \
2054 StgAddr x = PopTaggedAddr(); \
2055 int y = PopTaggedInt(); \
2056 StgChar z = PopTaggedChar(); \
2059 #define OP_AII_(s) \
2061 StgAddr x = PopTaggedAddr(); \
2062 int y = PopTaggedInt(); \
2063 StgInt z = PopTaggedInt(); \
2066 #define OP_AIA_(s) \
2068 StgAddr x = PopTaggedAddr(); \
2069 int y = PopTaggedInt(); \
2070 StgAddr z = PopTaggedAddr(); \
2073 #define OP_AIF_(s) \
2075 StgAddr x = PopTaggedAddr(); \
2076 int y = PopTaggedInt(); \
2077 StgFloat z = PopTaggedFloat(); \
2080 #define OP_AID_(s) \
2082 StgAddr x = PopTaggedAddr(); \
2083 int y = PopTaggedInt(); \
2084 StgDouble z = PopTaggedDouble(); \
2087 #define OP_AIs_(s) \
2089 StgAddr x = PopTaggedAddr(); \
2090 int y = PopTaggedInt(); \
2091 StgStablePtr z = PopTaggedStablePtr(); \
2096 #define OP_FF_B(e) \
2098 StgFloat x = PopTaggedFloat(); \
2099 StgFloat y = PopTaggedFloat(); \
2100 PushTaggedBool(e); \
2103 #define OP_FF_F(e) \
2105 StgFloat x = PopTaggedFloat(); \
2106 StgFloat y = PopTaggedFloat(); \
2107 PushTaggedFloat(e); \
2112 StgFloat x = PopTaggedFloat(); \
2113 PushTaggedFloat(e); \
2118 StgFloat x = PopTaggedFloat(); \
2119 PushTaggedBool(e); \
2124 StgFloat x = PopTaggedFloat(); \
2130 StgFloat x = PopTaggedFloat(); \
2131 PushTaggedDouble(e); \
2134 #define OP_DD_B(e) \
2136 StgDouble x = PopTaggedDouble(); \
2137 StgDouble y = PopTaggedDouble(); \
2138 PushTaggedBool(e); \
2141 #define OP_DD_D(e) \
2143 StgDouble x = PopTaggedDouble(); \
2144 StgDouble y = PopTaggedDouble(); \
2145 PushTaggedDouble(e); \
2150 StgDouble x = PopTaggedDouble(); \
2151 PushTaggedBool(e); \
2156 StgDouble x = PopTaggedDouble(); \
2157 PushTaggedDouble(e); \
2162 StgDouble x = PopTaggedDouble(); \
2168 StgDouble x = PopTaggedDouble(); \
2169 PushTaggedFloat(e); \
2173 StgPtr CreateByteArrayToHoldInteger ( int nbytes )
2175 StgWord words = (nbytes+sizeof(W_)-1)/sizeof(W_);
2176 StgWord size = sizeofW(StgArrWords) + words;
2177 StgArrWords* arr = (StgArrWords*)allocate(size);
2178 SET_HDR(arr,&ARR_WORDS_info,CCCS);
2180 ASSERT((W_)nbytes <= arr->words * sizeof(W_));
2183 for (i = 0; i < words; ++i) {
2184 arr->payload[i] = 0xdeadbeef;
2186 { B* b = (B*) &(arr->payload[0]);
2187 b->used = b->sign = 0;
2193 B* IntegerInsideByteArray ( StgPtr arr0 )
2196 StgArrWords* arr = (StgArrWords*)arr0;
2197 ASSERT(GET_INFO(arr) == &ARR_WORDS_info);
2198 b = (B*) &(arr->payload[0]);
2202 void SloppifyIntegerEnd ( StgPtr arr0 )
2204 StgArrWords* arr = (StgArrWords*)arr0;
2205 B* b = (B*) & (arr->payload[0]);
2206 I_ nwunused = arr->words - sizeofW(B) - (b->used+sizeof(W_)-1)/sizeof(W_);
2207 if (nwunused >= ((I_)sizeofW(StgArrWords))) {
2209 b->size -= nwunused * sizeof(W_);
2210 if (b->size < b->used) b->size = b->used;
2213 arr->words -= nwunused;
2214 slop = (StgArrWords*)&(arr->payload[arr->words]);
2215 SET_HDR(slop,&ARR_WORDS_info,CCCS);
2216 slop->words = nwunused - sizeofW(StgArrWords);
2217 ASSERT( &(slop->payload[slop->words]) ==
2218 &(arr->payload[arr->words + nwunused]) );
2222 #define OP_Z_Z(op) \
2224 B* x = IntegerInsideByteArray(PopPtr()); \
2225 int n = mycat2(size_,op)(x); \
2226 StgPtr p = CreateByteArrayToHoldInteger(n); \
2227 mycat2(do_,op)(x,n,IntegerInsideByteArray(p)); \
2228 SloppifyIntegerEnd(p); \
2231 #define OP_ZZ_Z(op) \
2233 B* x = IntegerInsideByteArray(PopPtr()); \
2234 B* y = IntegerInsideByteArray(PopPtr()); \
2235 int n = mycat2(size_,op)(x,y); \
2236 StgPtr p = CreateByteArrayToHoldInteger(n); \
2237 mycat2(do_,op)(x,y,n,IntegerInsideByteArray(p)); \
2238 SloppifyIntegerEnd(p); \
2245 #define HEADER_mI(ty,where) \
2246 StgArrWords* x = stgCast(StgArrWords*,PopPtr()); \
2247 nat i = PopTaggedInt(); \
2248 if (i * sizeof(ty) + (sizeof(ty)) > sizeof(StgWord) * x->words) { \
2249 return (raiseIndex(where)); \
2251 #define OP_mI_ty(ty,where,s) \
2253 HEADER_mI(mycat2(Stg,ty),where) \
2254 { mycat2(Stg,ty) r; \
2256 mycat2(PushTagged,ty)(r); \
2259 #define OP_mIty_(ty,where,s) \
2261 HEADER_mI(mycat2(Stg,ty),where) \
2263 mycat2(Stg,ty) z = mycat2(PopTagged,ty)(); \
2269 static void myStackCheck ( Capability* cap )
2271 /* fprintf(stderr, "myStackCheck\n"); */
2272 if (!(gSpLim <= gSp && gSp <= stgCast(StgPtr,gSu))) {
2273 fprintf(stderr, "myStackCheck: invalid initial gSp/gSu \n" );
2277 if (!( (P_)gSu >= (P_)cap->rCurrentTSO->stack
2279 (P_)gSu <= (P_)(cap->rCurrentTSO->stack
2280 + cap->rCurrentTSO->stack_size))) {
2281 fprintf ( stderr, "myStackCheck: gSu out of stack\n" );
2284 switch (get_itbl(stgCast(StgClosure*,gSu))->type) {
2286 gSu = (StgUpdateFrame*) ((StgCatchFrame*)(gSu))->link;
2289 gSu = (StgUpdateFrame*) ((StgUpdateFrame*)(gSu))->link;
2292 gSu = (StgUpdateFrame*) ((StgSeqFrame*)(gSu))->link;
2297 fprintf(stderr, "myStackCheck: invalid activation record\n"); assert(0);
2304 /* --------------------------------------------------------------------------
2305 * Primop stuff for bytecode interpreter
2306 * ------------------------------------------------------------------------*/
2308 /* Returns & of the next thing to enter (if throwing an exception),
2309 or NULL in the normal case.
2311 static void* enterBCO_primop1 ( int primop1code )
2314 barf("enterBCO_primop1 in combined mode");
2316 switch (primop1code) {
2317 case i_pushseqframe:
2319 StgClosure* c = PopCPtr();
2324 case i_pushcatchframe:
2326 StgClosure* e = PopCPtr();
2327 StgClosure* h = PopCPtr();
2333 case i_gtChar: OP_CC_B(x>y); break;
2334 case i_geChar: OP_CC_B(x>=y); break;
2335 case i_eqChar: OP_CC_B(x==y); break;
2336 case i_neChar: OP_CC_B(x!=y); break;
2337 case i_ltChar: OP_CC_B(x<y); break;
2338 case i_leChar: OP_CC_B(x<=y); break;
2339 case i_charToInt: OP_C_I(x); break;
2340 case i_intToChar: OP_I_C(x); break;
2342 case i_gtInt: OP_II_B(x>y); break;
2343 case i_geInt: OP_II_B(x>=y); break;
2344 case i_eqInt: OP_II_B(x==y); break;
2345 case i_neInt: OP_II_B(x!=y); break;
2346 case i_ltInt: OP_II_B(x<y); break;
2347 case i_leInt: OP_II_B(x<=y); break;
2348 case i_minInt: OP__I(INT_MIN); break;
2349 case i_maxInt: OP__I(INT_MAX); break;
2350 case i_plusInt: OP_II_I(x+y); break;
2351 case i_minusInt: OP_II_I(x-y); break;
2352 case i_timesInt: OP_II_I(x*y); break;
2355 int x = PopTaggedInt();
2356 int y = PopTaggedInt();
2358 return (raiseDiv0("quotInt"));
2360 /* ToDo: protect against minInt / -1 errors
2361 * (repeat for all other division primops) */
2367 int x = PopTaggedInt();
2368 int y = PopTaggedInt();
2370 return (raiseDiv0("remInt"));
2377 StgInt x = PopTaggedInt();
2378 StgInt y = PopTaggedInt();
2380 return (raiseDiv0("quotRemInt"));
2382 PushTaggedInt(x%y); /* last result */
2383 PushTaggedInt(x/y); /* first result */
2386 case i_negateInt: OP_I_I(-x); break;
2388 case i_andInt: OP_II_I(x&y); break;
2389 case i_orInt: OP_II_I(x|y); break;
2390 case i_xorInt: OP_II_I(x^y); break;
2391 case i_notInt: OP_I_I(~x); break;
2392 case i_shiftLInt: OP_II_I(x<<y); break;
2393 case i_shiftRAInt: OP_II_I(x>>y); break; /* ToDo */
2394 case i_shiftRLInt: OP_II_I(x>>y); break; /* ToDo */
2396 case i_gtWord: OP_WW_B(x>y); break;
2397 case i_geWord: OP_WW_B(x>=y); break;
2398 case i_eqWord: OP_WW_B(x==y); break;
2399 case i_neWord: OP_WW_B(x!=y); break;
2400 case i_ltWord: OP_WW_B(x<y); break;
2401 case i_leWord: OP_WW_B(x<=y); break;
2402 case i_minWord: OP__W(0); break;
2403 case i_maxWord: OP__W(UINT_MAX); break;
2404 case i_plusWord: OP_WW_W(x+y); break;
2405 case i_minusWord: OP_WW_W(x-y); break;
2406 case i_timesWord: OP_WW_W(x*y); break;
2409 StgWord x = PopTaggedWord();
2410 StgWord y = PopTaggedWord();
2412 return (raiseDiv0("quotWord"));
2414 PushTaggedWord(x/y);
2419 StgWord x = PopTaggedWord();
2420 StgWord y = PopTaggedWord();
2422 return (raiseDiv0("remWord"));
2424 PushTaggedWord(x%y);
2429 StgWord x = PopTaggedWord();
2430 StgWord y = PopTaggedWord();
2432 return (raiseDiv0("quotRemWord"));
2434 PushTaggedWord(x%y); /* last result */
2435 PushTaggedWord(x/y); /* first result */
2438 case i_negateWord: OP_W_W(-x); break;
2439 case i_andWord: OP_WW_W(x&y); break;
2440 case i_orWord: OP_WW_W(x|y); break;
2441 case i_xorWord: OP_WW_W(x^y); break;
2442 case i_notWord: OP_W_W(~x); break;
2443 case i_shiftLWord: OP_WW_W(x<<y); break;
2444 case i_shiftRAWord: OP_WW_W(x>>y); break; /* ToDo */
2445 case i_shiftRLWord: OP_WW_W(x>>y); break; /* ToDo */
2446 case i_intToWord: OP_I_W(x); break;
2447 case i_wordToInt: OP_W_I(x); break;
2449 case i_gtAddr: OP_AA_B(x>y); break;
2450 case i_geAddr: OP_AA_B(x>=y); break;
2451 case i_eqAddr: OP_AA_B(x==y); break;
2452 case i_neAddr: OP_AA_B(x!=y); break;
2453 case i_ltAddr: OP_AA_B(x<y); break;
2454 case i_leAddr: OP_AA_B(x<=y); break;
2455 case i_intToAddr: OP_I_A((StgAddr)x); break; /* ToDo */
2456 case i_addrToInt: OP_A_I((StgInt)x); break; /* ToDo */
2458 case i_intToStable: OP_I_s(x); break;
2459 case i_stableToInt: OP_s_I(x); break;
2461 case i_indexCharOffAddr: OP_AI_C(indexCharOffAddrzh(r,x,y)); break;
2462 case i_readCharOffAddr: OP_AI_C(indexCharOffAddrzh(r,x,y)); break;
2463 case i_writeCharOffAddr: OP_AIC_(writeCharOffAddrzh(x,y,z)); break;
2465 case i_indexIntOffAddr: OP_AI_I(indexIntOffAddrzh(r,x,y)); break;
2466 case i_readIntOffAddr: OP_AI_I(indexIntOffAddrzh(r,x,y)); break;
2467 case i_writeIntOffAddr: OP_AII_(writeIntOffAddrzh(x,y,z)); break;
2469 case i_indexAddrOffAddr: OP_AI_A(indexAddrOffAddrzh(r,x,y)); break;
2470 case i_readAddrOffAddr: OP_AI_A(indexAddrOffAddrzh(r,x,y)); break;
2471 case i_writeAddrOffAddr: OP_AIA_(writeAddrOffAddrzh(x,y,z)); break;
2473 case i_indexFloatOffAddr: OP_AI_F(indexFloatOffAddrzh(r,x,y)); break;
2474 case i_readFloatOffAddr: OP_AI_F(indexFloatOffAddrzh(r,x,y)); break;
2475 case i_writeFloatOffAddr: OP_AIF_(writeFloatOffAddrzh(x,y,z)); break;
2477 case i_indexDoubleOffAddr: OP_AI_D(indexDoubleOffAddrzh(r,x,y)); break;
2478 case i_readDoubleOffAddr: OP_AI_D(indexDoubleOffAddrzh(r,x,y)); break;
2479 case i_writeDoubleOffAddr: OP_AID_(writeDoubleOffAddrzh(x,y,z)); break;
2481 case i_indexStableOffAddr: OP_AI_s(indexStablePtrOffAddrzh(r,x,y)); break;
2482 case i_readStableOffAddr: OP_AI_s(indexStablePtrOffAddrzh(r,x,y)); break;
2483 case i_writeStableOffAddr: OP_AIs_(writeStablePtrOffAddrzh(x,y,z)); break;
2485 case i_compareInteger:
2487 B* x = IntegerInsideByteArray(PopPtr());
2488 B* y = IntegerInsideByteArray(PopPtr());
2489 StgInt r = do_cmp(x,y);
2490 PushTaggedInt(r<0 ? -1 : (r>0 ? 1 : 0));
2493 case i_negateInteger: OP_Z_Z(neg); break;
2494 case i_plusInteger: OP_ZZ_Z(add); break;
2495 case i_minusInteger: OP_ZZ_Z(sub); break;
2496 case i_timesInteger: OP_ZZ_Z(mul); break;
2497 case i_quotRemInteger:
2499 B* x = IntegerInsideByteArray(PopPtr());
2500 B* y = IntegerInsideByteArray(PopPtr());
2501 int n = size_qrm(x,y);
2502 StgPtr q = CreateByteArrayToHoldInteger(n);
2503 StgPtr r = CreateByteArrayToHoldInteger(n);
2504 if (do_getsign(y)==0)
2505 return (raiseDiv0("quotRemInteger"));
2506 do_qrm(x,y,n,IntegerInsideByteArray(q),
2507 IntegerInsideByteArray(r));
2508 SloppifyIntegerEnd(q);
2509 SloppifyIntegerEnd(r);
2514 case i_intToInteger:
2516 int n = size_fromInt();
2517 StgPtr p = CreateByteArrayToHoldInteger(n);
2518 do_fromInt( PopTaggedInt(), n, IntegerInsideByteArray(p));
2522 case i_wordToInteger:
2524 int n = size_fromWord();
2525 StgPtr p = CreateByteArrayToHoldInteger(n);
2526 do_fromWord( PopTaggedWord(), n, IntegerInsideByteArray(p));
2530 case i_integerToInt: PushTaggedInt(do_toInt(
2531 IntegerInsideByteArray(PopPtr())
2535 case i_integerToWord: PushTaggedWord(do_toWord(
2536 IntegerInsideByteArray(PopPtr())
2540 case i_integerToFloat: PushTaggedFloat(do_toFloat(
2541 IntegerInsideByteArray(PopPtr())
2545 case i_integerToDouble: PushTaggedDouble(do_toDouble(
2546 IntegerInsideByteArray(PopPtr())
2550 case i_gtFloat: OP_FF_B(x>y); break;
2551 case i_geFloat: OP_FF_B(x>=y); break;
2552 case i_eqFloat: OP_FF_B(x==y); break;
2553 case i_neFloat: OP_FF_B(x!=y); break;
2554 case i_ltFloat: OP_FF_B(x<y); break;
2555 case i_leFloat: OP_FF_B(x<=y); break;
2556 case i_minFloat: OP__F(FLT_MIN); break;
2557 case i_maxFloat: OP__F(FLT_MAX); break;
2558 case i_radixFloat: OP__I(FLT_RADIX); break;
2559 case i_digitsFloat: OP__I(FLT_MANT_DIG); break;
2560 case i_minExpFloat: OP__I(FLT_MIN_EXP); break;
2561 case i_maxExpFloat: OP__I(FLT_MAX_EXP); break;
2562 case i_plusFloat: OP_FF_F(x+y); break;
2563 case i_minusFloat: OP_FF_F(x-y); break;
2564 case i_timesFloat: OP_FF_F(x*y); break;
2567 StgFloat x = PopTaggedFloat();
2568 StgFloat y = PopTaggedFloat();
2569 PushTaggedFloat(x/y);
2572 case i_negateFloat: OP_F_F(-x); break;
2573 case i_floatToInt: OP_F_I(x); break;
2574 case i_intToFloat: OP_I_F(x); break;
2575 case i_expFloat: OP_F_F(exp(x)); break;
2576 case i_logFloat: OP_F_F(log(x)); break;
2577 case i_sqrtFloat: OP_F_F(sqrt(x)); break;
2578 case i_sinFloat: OP_F_F(sin(x)); break;
2579 case i_cosFloat: OP_F_F(cos(x)); break;
2580 case i_tanFloat: OP_F_F(tan(x)); break;
2581 case i_asinFloat: OP_F_F(asin(x)); break;
2582 case i_acosFloat: OP_F_F(acos(x)); break;
2583 case i_atanFloat: OP_F_F(atan(x)); break;
2584 case i_sinhFloat: OP_F_F(sinh(x)); break;
2585 case i_coshFloat: OP_F_F(cosh(x)); break;
2586 case i_tanhFloat: OP_F_F(tanh(x)); break;
2587 case i_powerFloat: OP_FF_F(pow(x,y)); break;
2589 case i_encodeFloatZ:
2591 StgPtr sig = PopPtr();
2592 StgInt exp = PopTaggedInt();
2594 B__encodeFloat(IntegerInsideByteArray(sig), exp)
2598 case i_decodeFloatZ:
2600 StgFloat f = PopTaggedFloat();
2601 StgPtr sig = CreateByteArrayToHoldInteger(size_fltmantissa());
2603 B__decodeFloat(IntegerInsideByteArray(sig), &exp, f);
2609 case i_isNaNFloat: OP_F_B(isFloatNaN(x)); break;
2610 case i_isInfiniteFloat: OP_F_B(isFloatInfinite(x)); break;
2611 case i_isNegativeZeroFloat: OP_F_B(isFloatNegativeZero(x)); break;
2612 case i_isDenormalizedFloat: OP_F_B(isFloatDenormalized(x)); break;
2613 case i_gtDouble: OP_DD_B(x>y); break;
2614 case i_geDouble: OP_DD_B(x>=y); break;
2615 case i_eqDouble: OP_DD_B(x==y); break;
2616 case i_neDouble: OP_DD_B(x!=y); break;
2617 case i_ltDouble: OP_DD_B(x<y); break;
2618 case i_leDouble: OP_DD_B(x<=y) break;
2619 case i_minDouble: OP__D(DBL_MIN); break;
2620 case i_maxDouble: OP__D(DBL_MAX); break;
2621 case i_radixDouble: OP__I(FLT_RADIX); break;
2622 case i_digitsDouble: OP__I(DBL_MANT_DIG); break;
2623 case i_minExpDouble: OP__I(DBL_MIN_EXP); break;
2624 case i_maxExpDouble: OP__I(DBL_MAX_EXP); break;
2625 case i_plusDouble: OP_DD_D(x+y); break;
2626 case i_minusDouble: OP_DD_D(x-y); break;
2627 case i_timesDouble: OP_DD_D(x*y); break;
2628 case i_divideDouble:
2630 StgDouble x = PopTaggedDouble();
2631 StgDouble y = PopTaggedDouble();
2632 PushTaggedDouble(x/y);
2635 case i_negateDouble: OP_D_D(-x); break;
2636 case i_doubleToInt: OP_D_I(x); break;
2637 case i_intToDouble: OP_I_D(x); break;
2638 case i_doubleToFloat: OP_D_F(x); break;
2639 case i_floatToDouble: OP_F_F(x); break;
2640 case i_expDouble: OP_D_D(exp(x)); break;
2641 case i_logDouble: OP_D_D(log(x)); break;
2642 case i_sqrtDouble: OP_D_D(sqrt(x)); break;
2643 case i_sinDouble: OP_D_D(sin(x)); break;
2644 case i_cosDouble: OP_D_D(cos(x)); break;
2645 case i_tanDouble: OP_D_D(tan(x)); break;
2646 case i_asinDouble: OP_D_D(asin(x)); break;
2647 case i_acosDouble: OP_D_D(acos(x)); break;
2648 case i_atanDouble: OP_D_D(atan(x)); break;
2649 case i_sinhDouble: OP_D_D(sinh(x)); break;
2650 case i_coshDouble: OP_D_D(cosh(x)); break;
2651 case i_tanhDouble: OP_D_D(tanh(x)); break;
2652 case i_powerDouble: OP_DD_D(pow(x,y)); break;
2654 case i_encodeDoubleZ:
2656 StgPtr sig = PopPtr();
2657 StgInt exp = PopTaggedInt();
2659 B__encodeDouble(IntegerInsideByteArray(sig), exp)
2663 case i_decodeDoubleZ:
2665 StgDouble d = PopTaggedDouble();
2666 StgPtr sig = CreateByteArrayToHoldInteger(size_dblmantissa());
2668 B__decodeDouble(IntegerInsideByteArray(sig), &exp, d);
2674 case i_isNaNDouble: OP_D_B(isDoubleNaN(x)); break;
2675 case i_isInfiniteDouble: OP_D_B(isDoubleInfinite(x)); break;
2676 case i_isNegativeZeroDouble: OP_D_B(isDoubleNegativeZero(x)); break;
2677 case i_isDenormalizedDouble: OP_D_B(isDoubleDenormalized(x)); break;
2678 case i_isIEEEDouble:
2680 PushTaggedBool(rtsTrue);
2684 barf("Unrecognised primop1");
2691 /* For normal cases, return NULL and leave *return2 unchanged.
2692 To return the address of the next thing to enter,
2693 return the address of it and leave *return2 unchanged.
2694 To return a StgThreadReturnCode to the scheduler,
2695 set *return2 to it and return a non-NULL value.
2696 To cause a context switch, set context_switch (its a global),
2697 and optionally set hugsBlock to your rational.
2699 static void* enterBCO_primop2 ( int primop2code,
2700 int* /*StgThreadReturnCode* */ return2,
2703 HugsBlock *hugsBlock )
2706 /* A small concession: we need to allow ccalls,
2707 even in combined mode.
2709 if (primop2code != i_ccall_ccall_IO &&
2710 primop2code != i_ccall_stdcall_IO)
2711 barf("enterBCO_primop2 in combined mode");
2714 switch (primop2code) {
2715 case i_raise: /* raise#{err} */
2717 StgClosure* err = PopCPtr();
2718 return (raiseAnError(err));
2723 StgClosure* init = PopCPtr();
2725 = stgCast(StgMutVar*,allocate(sizeofW(StgMutVar)));
2726 SET_HDR(mv,&MUT_VAR_info,CCCS);
2728 PushPtr(stgCast(StgPtr,mv));
2733 StgMutVar* mv = stgCast(StgMutVar*,PopPtr());
2739 StgMutVar* mv = stgCast(StgMutVar*,PopPtr());
2740 StgClosure* value = PopCPtr();
2746 nat n = PopTaggedInt(); /* or Word?? */
2747 StgClosure* init = PopCPtr();
2748 StgWord size = sizeofW(StgMutArrPtrs) + n;
2751 = stgCast(StgMutArrPtrs*,allocate(size));
2752 SET_HDR(arr,&MUT_ARR_PTRS_info,CCCS);
2754 for (i = 0; i < n; ++i) {
2755 arr->payload[i] = init;
2757 PushPtr(stgCast(StgPtr,arr));
2763 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
2764 nat i = PopTaggedInt(); /* or Word?? */
2765 StgWord n = arr->ptrs;
2767 return (raiseIndex("{index,read}Array"));
2769 PushCPtr(arr->payload[i]);
2774 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
2775 nat i = PopTaggedInt(); /* or Word? */
2776 StgClosure* v = PopCPtr();
2777 StgWord n = arr->ptrs;
2779 return (raiseIndex("{index,read}Array"));
2781 arr->payload[i] = v;
2785 case i_sizeMutableArray:
2787 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
2788 PushTaggedInt(arr->ptrs);
2791 case i_unsafeFreezeArray:
2793 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
2794 SET_INFO(arr,&MUT_ARR_PTRS_FROZEN_info);
2795 PushPtr(stgCast(StgPtr,arr));
2798 case i_unsafeFreezeByteArray:
2800 /* Delightfully simple :-) */
2804 case i_sameMutableArray:
2805 case i_sameMutableByteArray:
2807 StgPtr x = PopPtr();
2808 StgPtr y = PopPtr();
2809 PushTaggedBool(x==y);
2813 case i_newByteArray:
2815 nat n = PopTaggedInt(); /* or Word?? */
2816 StgInt words = (n+sizeof(W_)-1)/sizeof(W_);
2817 StgWord size = sizeofW(StgArrWords) + words;
2818 StgArrWords* arr = stgCast(StgArrWords*,allocate(size));
2819 SET_HDR(arr,&ARR_WORDS_info,CCCS);
2823 for (i = 0; i < n; ++i) {
2824 arr->payload[i] = 0xdeadbeef;
2827 PushPtr(stgCast(StgPtr,arr));
2831 /* Most of these generate alignment warnings on Sparcs and similar architectures.
2832 * These are harmless and are caused by the cast to C* in BYTE_ARR_CTS.
2834 case i_indexCharArray:
2835 OP_mI_ty(Char,"indexCharArray", indexCharArrayzh(r,x,i)); break;
2836 case i_readCharArray:
2837 OP_mI_ty(Char,"readCharArray", readCharArrayzh(r,x,i)); break;
2838 case i_writeCharArray:
2839 OP_mIty_(Char,"writeCharArray", writeCharArrayzh(x,i,z)); break;
2841 case i_indexIntArray:
2842 OP_mI_ty(Int,"indexIntArray", indexIntArrayzh(r,x,i)); break;
2843 case i_readIntArray:
2844 OP_mI_ty(Int,"readIntArray", readIntArrayzh(r,x,i)); break;
2845 case i_writeIntArray:
2846 OP_mIty_(Int,"writeIntArray", writeIntArrayzh(x,i,z)); break;
2848 case i_indexAddrArray:
2849 OP_mI_ty(Addr,"indexAddrArray", indexAddrArrayzh(r,x,i)); break;
2850 case i_readAddrArray:
2851 OP_mI_ty(Addr,"readAddrArray", readAddrArrayzh(r,x,i)); break;
2852 case i_writeAddrArray:
2853 OP_mIty_(Addr,"writeAddrArray", writeAddrArrayzh(x,i,z)); break;
2855 case i_indexFloatArray:
2856 OP_mI_ty(Float,"indexFloatArray", indexFloatArrayzh(r,x,i)); break;
2857 case i_readFloatArray:
2858 OP_mI_ty(Float,"readFloatArray", readFloatArrayzh(r,x,i)); break;
2859 case i_writeFloatArray:
2860 OP_mIty_(Float,"writeFloatArray", writeFloatArrayzh(x,i,z)); break;
2862 case i_indexDoubleArray:
2863 OP_mI_ty(Double,"indexDoubleArray", indexDoubleArrayzh(r,x,i)); break;
2864 case i_readDoubleArray:
2865 OP_mI_ty(Double,"readDoubleArray", readDoubleArrayzh(r,x,i)); break;
2866 case i_writeDoubleArray:
2867 OP_mIty_(Double,"writeDoubleArray", writeDoubleArrayzh(x,i,z)); break;
2870 #ifdef PROVIDE_STABLE
2871 case i_indexStableArray:
2872 OP_mI_ty(StablePtr,"indexStableArray", indexStablePtrArrayzh(r,x,i)); break;
2873 case i_readStableArray:
2874 OP_mI_ty(StablePtr,"readStableArray", readStablePtrArrayzh(r,x,i)); break;
2875 case i_writeStableArray:
2876 OP_mIty_(StablePtr,"writeStableArray", writeStablePtrArrayzh(x,i,z)); break;
2882 #ifdef PROVIDE_COERCE
2883 case i_unsafeCoerce:
2885 /* Another nullop */
2889 #ifdef PROVIDE_PTREQUALITY
2890 case i_reallyUnsafePtrEquality:
2891 { /* identical to i_sameRef */
2892 StgPtr x = PopPtr();
2893 StgPtr y = PopPtr();
2894 PushTaggedBool(x==y);
2898 #ifdef PROVIDE_FOREIGN
2899 /* ForeignObj# operations */
2900 case i_mkForeignObj:
2902 StgForeignObj *result
2903 = stgCast(StgForeignObj*,allocate(sizeofW(StgForeignObj)));
2904 SET_HDR(result,&FOREIGN_info,CCCS);
2905 result -> data = PopTaggedAddr();
2906 PushPtr(stgCast(StgPtr,result));
2909 #endif /* PROVIDE_FOREIGN */
2914 = stgCast(StgWeak*,allocate(sizeofW(StgWeak)));
2915 SET_HDR(w, &WEAK_info, CCCS);
2917 w->value = PopCPtr();
2918 w->finaliser = PopCPtr();
2919 w->link = weak_ptr_list;
2921 IF_DEBUG(weak, fprintf(stderr,"New weak pointer at %p\n",w));
2922 PushPtr(stgCast(StgPtr,w));
2927 StgWeak *w = stgCast(StgWeak*,PopPtr());
2928 if (w->header.info == &WEAK_info) {
2929 PushCPtr(w->value); /* last result */
2930 PushTaggedInt(1); /* first result */
2932 PushPtr(stgCast(StgPtr,w));
2933 /* ToDo: error thunk would be better */
2938 #endif /* PROVIDE_WEAK */
2940 case i_makeStablePtr:
2942 StgPtr p = PopPtr();
2943 StgStablePtr sp = getStablePtr ( p );
2944 PushTaggedStablePtr(sp);
2947 case i_deRefStablePtr:
2950 StgStablePtr sp = PopTaggedStablePtr();
2951 p = deRefStablePtr(sp);
2955 case i_freeStablePtr:
2957 StgStablePtr sp = PopTaggedStablePtr();
2962 case i_createAdjThunkARCH:
2964 StgStablePtr stableptr = PopTaggedStablePtr();
2965 StgAddr typestr = PopTaggedAddr();
2966 StgChar callconv = PopTaggedChar();
2967 StgAddr adj_thunk = createAdjThunk(stableptr,typestr,callconv);
2968 PushTaggedAddr(adj_thunk);
2974 StgInt n = prog_argc;
2980 StgInt n = PopTaggedInt();
2981 StgAddr a = (StgAddr)prog_argv[n];
2988 StgMVar *mvar = stgCast(StgMVar*,allocate(sizeofW(StgMVar)));
2989 SET_INFO(mvar,&EMPTY_MVAR_info);
2990 mvar->head = mvar->tail = (StgTSO *)&END_TSO_QUEUE_closure;
2991 mvar->value = stgCast(StgClosure*,&END_TSO_QUEUE_closure);
2992 PushPtr(stgCast(StgPtr,mvar));
2997 StgMVar *mvar = (StgMVar*)PopCPtr();
2998 if (GET_INFO(mvar) == &EMPTY_MVAR_info) {
3000 /* The MVar is empty. Attach ourselves to the TSO's
3003 if (mvar->head == (StgTSO *)&END_TSO_QUEUE_closure) {
3004 mvar->head = cap->rCurrentTSO;
3006 mvar->tail->link = cap->rCurrentTSO;
3008 cap->rCurrentTSO->link = (StgTSO *)&END_TSO_QUEUE_closure;
3009 cap->rCurrentTSO->why_blocked = BlockedOnMVar;
3010 cap->rCurrentTSO->block_info.closure = (StgClosure *)mvar;
3011 mvar->tail = cap->rCurrentTSO;
3013 /* At this point, the top-of-stack holds the MVar,
3014 and underneath is the world token (). So the
3015 stack is in the same state as when primTakeMVar
3016 was entered (primTakeMVar is handwritten bytecode).
3017 Push obj, which is this BCO, and return to the
3018 scheduler. When the MVar is filled, the scheduler
3019 will re-enter primTakeMVar, with the args still on
3020 the top of the stack.
3022 PushCPtr((StgClosure*)(*bco));
3023 *return2 = ThreadBlocked;
3024 return (void*)(1+(char*)(NULL));
3027 PushCPtr(mvar->value);
3028 mvar->value = (StgClosure *)&END_TSO_QUEUE_closure;
3029 SET_INFO(mvar,&EMPTY_MVAR_info);
3035 StgMVar* mvar = stgCast(StgMVar*,PopPtr());
3036 StgClosure* value = PopCPtr();
3037 if (GET_INFO(mvar) == &FULL_MVAR_info) {
3038 return (makeErrorCall("putMVar {full MVar}"));
3040 /* wake up the first thread on the
3041 * queue, it will continue with the
3042 * takeMVar operation and mark the
3045 mvar->value = value;
3047 if (mvar->head != (StgTSO *)&END_TSO_QUEUE_closure) {
3048 ASSERT(mvar->head->why_blocked == BlockedOnMVar);
3049 mvar->head = unblockOne(mvar->head);
3050 if (mvar->head == (StgTSO *)&END_TSO_QUEUE_closure) {
3051 mvar->tail = (StgTSO *)&END_TSO_QUEUE_closure;
3055 /* unlocks the MVar in the SMP case */
3056 SET_INFO(mvar,&FULL_MVAR_info);
3058 /* yield for better communication performance */
3064 { /* identical to i_sameRef */
3065 StgMVar* x = (StgMVar*)PopPtr();
3066 StgMVar* y = (StgMVar*)PopPtr();
3067 PushTaggedBool(x==y);
3070 #ifdef PROVIDE_CONCURRENT
3073 StgClosure* closure;
3076 closure = PopCPtr();
3077 tso = createGenThread (RtsFlags.GcFlags.initialStkSize,closure);
3079 scheduleThread(tso);
3081 /* Later: Change to use tso as the ThreadId */
3082 PushTaggedWord(tid);
3088 StgWord n = PopTaggedWord();
3092 // Map from ThreadId to Thread Structure */
3093 for (t = all_threads; t != END_TSO_QUEUE; t = t->global_link) {
3102 while (tso->what_next == ThreadRelocated) {
3107 if (tso == cap->rCurrentTSO) { /* suicide */
3108 *return2 = ThreadFinished;
3109 return (void*)(1+(NULL));
3113 case i_raiseInThread:
3114 ASSERT(0); /* not (yet) supported */
3117 StgInt n = PopTaggedInt();
3119 hugsBlock->reason = BlockedOnDelay;
3120 hugsBlock->delay = n;
3125 StgInt n = PopTaggedInt();
3127 hugsBlock->reason = BlockedOnRead;
3128 hugsBlock->delay = n;
3133 StgInt n = PopTaggedInt();
3135 hugsBlock->reason = BlockedOnWrite;
3136 hugsBlock->delay = n;
3141 /* The definition of yield include an enter right after
3142 * the primYield, at which time context_switch is tested.
3149 StgWord tid = cap->rCurrentTSO->id;
3150 PushTaggedWord(tid);
3153 case i_cmpThreadIds:
3155 StgWord tid1 = PopTaggedWord();
3156 StgWord tid2 = PopTaggedWord();
3157 if (tid1 < tid2) PushTaggedInt(-1);
3158 else if (tid1 > tid2) PushTaggedInt(1);
3159 else PushTaggedInt(0);
3162 #endif /* PROVIDE_CONCURRENT */
3164 case i_ccall_ccall_Id:
3165 case i_ccall_ccall_IO:
3166 case i_ccall_stdcall_Id:
3167 case i_ccall_stdcall_IO:
3170 CFunDescriptor* descriptor;
3171 void (*funPtr)(void);
3173 descriptor = PopTaggedAddr();
3174 funPtr = PopTaggedAddr();
3175 cc = (primop2code == i_ccall_stdcall_Id ||
3176 primop2code == i_ccall_stdcall_IO)
3178 r = ccall(descriptor,funPtr,bco,cc,cap);
3181 return makeErrorCall(
3182 "unhandled type or too many args/results in ccall");
3184 barf("ccall not configured correctly for this platform");
3185 barf("unknown return code from ccall");
3188 barf("Unrecognised primop2");
3194 /* -----------------------------------------------------------------------------
3195 * ccall support code:
3196 * marshall moves args from C stack to Haskell stack
3197 * unmarshall moves args from Haskell stack to C stack
3198 * argSize calculates how much gSpace you need on the C stack
3199 * ---------------------------------------------------------------------------*/
3201 /* Pop arguments off the C stack and Push them onto the Hugs stack.
3202 * Used when preparing for C calling Haskell or in regSponse to
3203 * Haskell calling C.
3205 nat marshall(char arg_ty, void* arg)
3209 PushTaggedInt(*((int*)arg));
3210 return ARG_SIZE(INT_TAG);
3213 PushTaggedInteger(*((mpz_ptr*)arg));
3214 return ARG_SIZE(INTEGER_TAG);
3217 PushTaggedWord(*((unsigned int*)arg));
3218 return ARG_SIZE(WORD_TAG);
3220 PushTaggedChar(*((char*)arg));
3221 return ARG_SIZE(CHAR_TAG);
3223 PushTaggedFloat(*((float*)arg));
3224 return ARG_SIZE(FLOAT_TAG);
3226 PushTaggedDouble(*((double*)arg));
3227 return ARG_SIZE(DOUBLE_TAG);
3229 PushTaggedAddr(*((void**)arg));
3230 return ARG_SIZE(ADDR_TAG);
3232 PushTaggedStablePtr(*((StgStablePtr*)arg));
3233 return ARG_SIZE(STABLE_TAG);
3234 #ifdef PROVIDE_FOREIGN
3236 /* Not allowed in this direction - you have to
3237 * call makeForeignPtr explicitly
3239 barf("marshall: ForeignPtr#\n");
3244 /* Not allowed in this direction */
3245 barf("marshall: [Mutable]ByteArray#\n");
3248 barf("marshall: unrecognised arg type %d\n",arg_ty);
3253 /* Pop arguments off the Hugs stack and Push them onto the C stack.
3254 * Used when preparing for Haskell calling C or in regSponse to
3255 * C calling Haskell.
3257 nat unmarshall(char res_ty, void* res)
3261 *((int*)res) = PopTaggedInt();
3262 return ARG_SIZE(INT_TAG);
3265 *((mpz_ptr*)res) = PopTaggedInteger();
3266 return ARG_SIZE(INTEGER_TAG);
3269 *((unsigned int*)res) = PopTaggedWord();
3270 return ARG_SIZE(WORD_TAG);
3272 *((int*)res) = PopTaggedChar();
3273 return ARG_SIZE(CHAR_TAG);
3275 *((float*)res) = PopTaggedFloat();
3276 return ARG_SIZE(FLOAT_TAG);
3278 *((double*)res) = PopTaggedDouble();
3279 return ARG_SIZE(DOUBLE_TAG);
3281 *((void**)res) = PopTaggedAddr();
3282 return ARG_SIZE(ADDR_TAG);
3284 *((StgStablePtr*)res) = PopTaggedStablePtr();
3285 return ARG_SIZE(STABLE_TAG);
3286 #ifdef PROVIDE_FOREIGN
3289 StgForeignObj *result = stgCast(StgForeignObj*,PopPtr());
3290 *((void**)res) = result->data;
3291 return sizeofW(StgPtr);
3297 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
3298 *((void**)res) = stgCast(void*,&(arr->payload));
3299 return sizeofW(StgPtr);
3302 barf("unmarshall: unrecognised result type %d\n",res_ty);
3306 nat argSize( const char* ks )
3309 for( ; *ks != '\0'; ++ks) {
3312 sz += sizeof(StgWord) * ARG_SIZE(INT_TAG);
3316 sz += sizeof(StgWord) * ARG_SIZE(INTEGER_TAG);
3320 sz += sizeof(StgWord) * ARG_SIZE(WORD_TAG);
3323 sz += sizeof(StgWord) * ARG_SIZE(CHAR_TAG);
3326 sz += sizeof(StgWord) * ARG_SIZE(FLOAT_TAG);
3329 sz += sizeof(StgWord) * ARG_SIZE(DOUBLE_TAG);
3332 sz += sizeof(StgWord) * ARG_SIZE(ADDR_TAG);
3335 sz += sizeof(StgWord) * ARG_SIZE(STABLE_TAG);
3337 #ifdef PROVIDE_FOREIGN
3342 sz += sizeof(StgPtr);
3345 barf("argSize: unrecognised result type %d\n",*ks);
3353 /* -----------------------------------------------------------------------------
3354 * encode/decode Float/Double code for standalone Hugs
3355 * Code based on the HBC code (lib/fltcode.c) and more recently GHC
3356 * (ghc/rts/StgPrimFloat.c)
3357 * ---------------------------------------------------------------------------*/
3359 #if IEEE_FLOATING_POINT
3360 #define MY_DMINEXP ((DBL_MIN_EXP) - (DBL_MANT_DIG) - 1)
3361 /* DMINEXP is defined in values.h on Linux (for example) */
3362 #define DHIGHBIT 0x00100000
3363 #define DMSBIT 0x80000000
3365 #define MY_FMINEXP ((FLT_MIN_EXP) - (FLT_MANT_DIG) - 1)
3366 #define FHIGHBIT 0x00800000
3367 #define FMSBIT 0x80000000
3369 #error The following code doesnt work in a non-IEEE FP environment
3372 #ifdef WORDS_BIGENDIAN
3381 StgDouble B__encodeDouble (B* s, I_ e) /* result = s * 2^e */
3386 /* Convert a B to a double; knows a lot about internal rep! */
3387 for(r = 0.0, i = s->used-1; i >= 0; i--)
3388 r = (r * B_BASE_FLT) + s->stuff[i];
3390 /* Now raise to the exponent */
3391 if ( r != 0.0 ) /* Lennart suggests this avoids a bug in MIPS's ldexp */
3394 /* handle the sign */
3395 if (s->sign < 0) r = -r;
3402 #if ! FLOATS_AS_DOUBLES
3403 StgFloat B__encodeFloat (B* s, I_ e) /* result = s * 2^e */
3408 /* Convert a B to a float; knows a lot about internal rep! */
3409 for(r = 0.0, i = s->used-1; i >= 0; i--)
3410 r = (r * B_BASE_FLT) + s->stuff[i];
3412 /* Now raise to the exponent */
3413 if ( r != 0.0 ) /* Lennart suggests this avoids a bug in MIPS's ldexp */
3416 /* handle the sign */
3417 if (s->sign < 0) r = -r;
3421 #endif /* FLOATS_AS_DOUBLES */
3425 /* This only supports IEEE floating point */
3426 void B__decodeDouble (B* man, I_* exp, StgDouble dbl)
3428 /* Do some bit fiddling on IEEE */
3429 nat low, high; /* assuming 32 bit ints */
3431 union { double d; int i[2]; } u; /* assuming 32 bit ints, 64 bit double */
3433 u.d = dbl; /* grab chunks of the double */
3437 ASSERT(B_BASE == 256);
3439 /* Assume that the supplied B is the right size */
3442 if (low == 0 && (high & ~DMSBIT) == 0) {
3443 man->sign = man->used = 0;
3448 iexp = ((high >> 20) & 0x7ff) + MY_DMINEXP;
3452 if (iexp != MY_DMINEXP) /* don't add hidden bit to denorms */
3456 /* A denorm, normalize the mantissa */
3457 while (! (high & DHIGHBIT)) {
3467 man->stuff[7] = (((W_)high) >> 24) & 0xff;
3468 man->stuff[6] = (((W_)high) >> 16) & 0xff;
3469 man->stuff[5] = (((W_)high) >> 8) & 0xff;
3470 man->stuff[4] = (((W_)high) ) & 0xff;
3472 man->stuff[3] = (((W_)low) >> 24) & 0xff;
3473 man->stuff[2] = (((W_)low) >> 16) & 0xff;
3474 man->stuff[1] = (((W_)low) >> 8) & 0xff;
3475 man->stuff[0] = (((W_)low) ) & 0xff;
3477 if (sign < 0) man->sign = -1;
3479 do_renormalise(man);
3483 #if ! FLOATS_AS_DOUBLES
3484 void B__decodeFloat (B* man, I_* exp, StgFloat flt)
3486 /* Do some bit fiddling on IEEE */
3487 int high, sign; /* assuming 32 bit ints */
3488 union { float f; int i; } u; /* assuming 32 bit float and int */
3490 u.f = flt; /* grab the float */
3493 ASSERT(B_BASE == 256);
3495 /* Assume that the supplied B is the right size */
3498 if ((high & ~FMSBIT) == 0) {
3499 man->sign = man->used = 0;
3504 *exp = ((high >> 23) & 0xff) + MY_FMINEXP;
3508 if (*exp != MY_FMINEXP) /* don't add hidden bit to denorms */
3512 /* A denorm, normalize the mantissa */
3513 while (! (high & FHIGHBIT)) {
3518 man->stuff[3] = (((W_)high) >> 24) & 0xff;
3519 man->stuff[2] = (((W_)high) >> 16) & 0xff;
3520 man->stuff[1] = (((W_)high) >> 8) & 0xff;
3521 man->stuff[0] = (((W_)high) ) & 0xff;
3523 if (sign < 0) man->sign = -1;
3525 do_renormalise(man);
3528 #endif /* FLOATS_AS_DOUBLES */
3529 #endif /* INTERPRETER */