2 /* -----------------------------------------------------------------------------
5 * Copyright (c) 1994-1998.
7 * $RCSfile: Evaluator.c,v $
9 * $Date: 2000/04/25 17:47:42 $
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* getHugs_AsmObject_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 SSS; PopStopFrame(obj); LLL;
694 RETURN(ThreadFinished);
696 SSS; PopSeqFrame(); LLL;
697 ASSERT(xSp != (P_)xSu);
698 /* Hit a SEQ frame during an arg satisfaction check.
699 * So now return to bco_info which is under the
700 * SEQ frame. The following code is copied from a
701 * case RET_BCO further down. (The reason why we're
702 * here is that something of functional type has
703 * been seq-d on, and we're now returning to the
704 * algebraic-case-continuation which forced the
705 * evaluation in the first place.)
717 barf("Invalid update frame during argcheck");
719 } while (xSp==(P_)xSu);
727 int words = BCO_INSTR_8;
728 SSS; p = grabHpUpd(AP_sizeW(words)); LLL;
732 Case(i_ALLOC_CONSTR):
735 StgInfoTable* info = bcoConstAddr(bco,BCO_INSTR_8);
736 SSS; p = grabHpNonUpd(sizeW_fromITBL(info)); LLL;
737 SET_HDR((StgClosure*)p,info,??);
741 Case(i_ALLOC_CONSTR_big):
744 int x = BCO_INSTR_16;
745 StgInfoTable* info = bcoConstAddr(bco,x);
746 SSS; p = grabHpNonUpd(sizeW_fromITBL(info)); LLL;
747 SET_HDR((StgClosure*)p,info,??);
753 int x = BCO_INSTR_8; /* ToDo: Word not Int! */
755 StgAP_UPD* o = stgCast(StgAP_UPD*,xStackPtr(x));
756 SET_HDR(o,&AP_UPD_info,??);
758 o->fun = stgCast(StgClosure*,xPopPtr());
759 for(x=0; x < y; ++x) {
760 payloadWord(o,x) = xPopWord();
763 fprintf(stderr,"\tBuilt ");
765 printObj(stgCast(StgClosure*,o));
776 o = stgCast(StgAP_UPD*,xStackPtr(x));
777 SET_HDR(o,&AP_UPD_info,??);
779 o->fun = stgCast(StgClosure*,xPopPtr());
780 for(x=0; x < y; ++x) {
781 payloadWord(o,x) = xPopWord();
784 fprintf(stderr,"\tBuilt ");
786 printObj(stgCast(StgClosure*,o));
795 StgPAP* o = stgCast(StgPAP*,xStackPtr(x));
796 SET_HDR(o,&PAP_info,??);
798 o->fun = stgCast(StgClosure*,xPopPtr());
799 for(x=0; x < y; ++x) {
800 payloadWord(o,x) = xPopWord();
803 fprintf(stderr,"\tBuilt ");
805 printObj(stgCast(StgClosure*,o));
812 int offset = BCO_INSTR_8;
813 StgClosure* o = stgCast(StgClosure*,xStackPtr(offset));
814 const StgInfoTable* info = get_itbl(o);
815 nat p = info->layout.payload.ptrs;
816 nat np = info->layout.payload.nptrs;
818 for(i=0; i < p; ++i) {
819 o->payload[i] = xPopCPtr();
821 for(i=0; i < np; ++i) {
822 payloadWord(o,p+i) = 0xdeadbeef;
825 fprintf(stderr,"\tBuilt ");
827 printObj(stgCast(StgClosure*,o));
834 int offset = BCO_INSTR_16;
835 StgClosure* o = stgCast(StgClosure*,xStackPtr(offset));
836 const StgInfoTable* info = get_itbl(o);
837 nat p = info->layout.payload.ptrs;
838 nat np = info->layout.payload.nptrs;
840 for(i=0; i < p; ++i) {
841 o->payload[i] = xPopCPtr();
843 for(i=0; i < np; ++i) {
844 payloadWord(o,p+i) = 0xdeadbeef;
847 fprintf(stderr,"\tBuilt ");
849 printObj(stgCast(StgClosure*,o));
858 ASSERT(xSp+x+y <= stgCast(StgPtr,xSu));
859 /* a_1, .. a_x, b_1, .. b_y, s => a_1, .. a_x, s */
861 xSetStackWord(x+y,xStackWord(x));
871 ASSERT(xSp+x+y <= stgCast(StgPtr,xSu));
872 /* a_1, .. a_x, b_1, .. b_y, s => a_1, .. a_x, s */
874 xSetStackWord(x+y,xStackWord(x));
886 xPushPtr(bcoConstPtr(bco,BCO_INSTR_8));
887 xPushPtr(stgCast(StgPtr,&ret_bco_info));
892 int tag = BCO_INSTR_8;
893 StgWord offset = BCO_INSTR_16;
894 if (constrTag( (StgClosure*)xStackPtr(0) ) != tag) {
901 StgClosure* o = stgCast(StgClosure*,xStackPtr(0));
902 const StgInfoTable* itbl = get_itbl(o);
903 int i = itbl->layout.payload.ptrs;
904 ASSERT( itbl->type == CONSTR
905 || itbl->type == CONSTR_STATIC
906 || itbl->type == CONSTR_NOCAF_STATIC
907 || itbl->type == CONSTR_1_0
908 || itbl->type == CONSTR_0_1
909 || itbl->type == CONSTR_2_0
910 || itbl->type == CONSTR_1_1
911 || itbl->type == CONSTR_0_2
914 xPushCPtr(o->payload[i]);
920 int n = BCO_INSTR_16;
921 StgPtr p = xStackPtr(n);
927 StgPtr p = xStackPtr(BCO_INSTR_8);
933 xPushPtr(stgCast(StgPtr,bcoConstPtr(bco,BCO_INSTR_8)));
938 int n = BCO_INSTR_16;
939 xPushPtr(stgCast(StgPtr,bcoConstPtr(bco,n)));
944 SSS; PushTaggedRealWorld(); LLL;
949 StgInt i = xTaggedStackInt(BCO_INSTR_8);
955 xPushTaggedInt(bcoConstInt(bco,BCO_INSTR_8));
958 Case(i_CONST_INT_big):
960 int n = BCO_INSTR_16;
961 xPushTaggedInt(bcoConstInt(bco,n));
967 SSS; o = (StgClosure*)grabHpNonUpd(Izh_sizeW); LLL;
968 SET_HDR(o,Izh_con_info,??);
969 payloadWord(o,0) = xPopTaggedInt();
971 fprintf(stderr,"\tBuilt ");
973 printObj(stgCast(StgClosure*,o));
976 xPushPtr(stgCast(StgPtr,o));
981 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
982 /* ASSERT(isIntLike(con)); */
983 xPushTaggedInt(payloadWord(con,0));
988 StgWord offset = BCO_INSTR_16;
989 StgInt x = xPopTaggedInt();
990 StgInt y = xPopTaggedInt();
996 Case(i_CONST_INTEGER):
1000 char* s = bcoConstAddr(bco,BCO_INSTR_8);
1002 n = size_fromStr(s);
1003 p = CreateByteArrayToHoldInteger(n);
1004 do_fromStr ( s, n, IntegerInsideByteArray(p));
1005 SloppifyIntegerEnd(p);
1012 StgWord w = xTaggedStackWord(BCO_INSTR_8);
1018 xPushTaggedWord(bcoConstWord(bco,BCO_INSTR_8));
1024 SSS; o = (StgClosure*)grabHpNonUpd(Wzh_sizeW); LLL;
1025 SET_HDR(o,Wzh_con_info,??);
1026 payloadWord(o,0) = xPopTaggedWord();
1028 fprintf(stderr,"\tBuilt ");
1030 printObj(stgCast(StgClosure*,o));
1033 xPushPtr(stgCast(StgPtr,o));
1036 Case(i_UNPACK_WORD):
1038 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1039 /* ASSERT(isWordLike(con)); */
1040 xPushTaggedWord(payloadWord(con,0));
1045 StgAddr a = xTaggedStackAddr(BCO_INSTR_8);
1051 xPushTaggedAddr(bcoConstAddr(bco,BCO_INSTR_8));
1054 Case(i_CONST_ADDR_big):
1056 int n = BCO_INSTR_16;
1057 xPushTaggedAddr(bcoConstAddr(bco,n));
1063 SSS; o = (StgClosure*)grabHpNonUpd(Azh_sizeW); LLL;
1064 SET_HDR(o,Azh_con_info,??);
1065 payloadPtr(o,0) = xPopTaggedAddr();
1067 fprintf(stderr,"\tBuilt ");
1069 printObj(stgCast(StgClosure*,o));
1072 xPushPtr(stgCast(StgPtr,o));
1075 Case(i_UNPACK_ADDR):
1077 StgClosure* con = (StgClosure*)xStackPtr(0);
1078 /* ASSERT(isAddrLike(con)); */
1079 xPushTaggedAddr(payloadPtr(con,0));
1084 StgChar c = xTaggedStackChar(BCO_INSTR_8);
1090 xPushTaggedChar(bcoConstChar(bco,BCO_INSTR_8));
1096 SSS; o = (StgClosure*)grabHpNonUpd(Czh_sizeW); LLL;
1097 SET_HDR(o,Czh_con_info,??);
1098 payloadWord(o,0) = xPopTaggedChar();
1099 xPushPtr(stgCast(StgPtr,o));
1101 fprintf(stderr,"\tBuilt ");
1103 printObj(stgCast(StgClosure*,o));
1108 Case(i_UNPACK_CHAR):
1110 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1111 /* ASSERT(isCharLike(con)); */
1112 xPushTaggedChar(payloadWord(con,0));
1117 StgFloat f = xTaggedStackFloat(BCO_INSTR_8);
1118 xPushTaggedFloat(f);
1121 Case(i_CONST_FLOAT):
1123 xPushTaggedFloat(bcoConstFloat(bco,BCO_INSTR_8));
1129 SSS; o = (StgClosure*)grabHpNonUpd(Fzh_sizeW); LLL;
1130 SET_HDR(o,Fzh_con_info,??);
1131 ASSIGN_FLT(&payloadWord(o,0),xPopTaggedFloat());
1133 fprintf(stderr,"\tBuilt ");
1135 printObj(stgCast(StgClosure*,o));
1138 xPushPtr(stgCast(StgPtr,o));
1141 Case(i_UNPACK_FLOAT):
1143 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1144 /* ASSERT(isFloatLike(con)); */
1145 xPushTaggedFloat(PK_FLT(&payloadWord(con,0)));
1150 StgDouble d = xTaggedStackDouble(BCO_INSTR_8);
1151 xPushTaggedDouble(d);
1154 Case(i_CONST_DOUBLE):
1156 xPushTaggedDouble(bcoConstDouble(bco,BCO_INSTR_8));
1159 Case(i_CONST_DOUBLE_big):
1161 int n = BCO_INSTR_16;
1162 xPushTaggedDouble(bcoConstDouble(bco,n));
1165 Case(i_PACK_DOUBLE):
1168 SSS; o = (StgClosure*)grabHpNonUpd(Dzh_sizeW); LLL;
1169 SET_HDR(o,Dzh_con_info,??);
1170 ASSIGN_DBL(&payloadWord(o,0),xPopTaggedDouble());
1172 fprintf(stderr,"\tBuilt ");
1173 printObj(stgCast(StgClosure*,o));
1175 xPushPtr(stgCast(StgPtr,o));
1178 Case(i_UNPACK_DOUBLE):
1180 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1181 /* ASSERT(isDoubleLike(con)); */
1182 xPushTaggedDouble(PK_DBL(&payloadWord(con,0)));
1187 StgStablePtr s = xTaggedStackStable(BCO_INSTR_8);
1188 xPushTaggedStable(s);
1191 Case(i_PACK_STABLE):
1194 SSS; o = (StgClosure*)grabHpNonUpd(Stablezh_sizeW); LLL;
1195 SET_HDR(o,StablePtr_con_info,??);
1196 payloadWord(o,0) = xPopTaggedStable();
1198 fprintf(stderr,"\tBuilt ");
1200 printObj(stgCast(StgClosure*,o));
1203 xPushPtr(stgCast(StgPtr,o));
1206 Case(i_UNPACK_STABLE):
1208 StgClosure* con = (StgClosure*)xStackPtr(0);
1209 /* ASSERT(isStableLike(con)); */
1210 xPushTaggedStable(payloadWord(con,0));
1218 SSS; p = enterBCO_primop1 ( i ); LLL;
1219 if (p) { obj = p; goto enterLoop; };
1224 int i, trc, pc_saved;
1227 trc = 12345678; /* Assume != any StgThreadReturnCode */
1232 p = enterBCO_primop2 ( i, &trc, &bco_tmp, cap,
1236 bciPtr = &(bcoInstr(bco,pc_saved));
1238 if (trc == 12345678) {
1239 /* we want to enter p */
1240 obj = p; goto enterLoop;
1242 /* trc is the the StgThreadReturnCode for
1244 RETURN((StgThreadReturnCode)trc);
1250 /* combined insns, created by peephole opt */
1253 int x = BCO_INSTR_8;
1254 int y = BCO_INSTR_8;
1255 ASSERT(xSp+x+y <= stgCast(StgPtr,xSu));
1256 /* a_1, .. a_x, b_1, .. b_y, s => a_1, .. a_x, s */
1263 xSetStackWord(x+y,xStackWord(x));
1273 p = xStackPtr(BCO_INSTR_8);
1275 p = xStackPtr(BCO_INSTR_8);
1282 xPushPtr(bcoConstPtr(bco,BCO_INSTR_8));
1283 xPushPtr(stgCast(StgPtr,&ret_bco_info));
1284 p = xStackPtr(BCO_INSTR_8);
1290 StgPtr retaddr = bcoConstPtr(bco,BCO_INSTR_8);
1291 StgPtr ptr = xStackPtr(BCO_INSTR_8);
1293 /* A shortcut. We're going to push the address of a
1294 return continuation, and then enter a variable, so
1295 that when the var is evaluated, we return to the
1296 continuation. The shortcut is: if the var is a
1297 constructor, don't bother to enter it. Instead,
1298 push the variable on the stack (since this is what
1299 the continuation expects) and jump directly to the
1302 if (get_itbl((StgClosure*)ptr)->type == CONSTR) {
1304 obj = (StgClosure*)retaddr;
1306 fprintf(stderr, "object to enter is a constructor -- "
1307 "jumping directly to return continuation\n" );
1312 /* This is the normal, non-short-cut route */
1314 xPushPtr(stgCast(StgPtr,&ret_bco_info));
1315 obj = (StgClosure*)ptr;
1320 Case(i_VAR_DOUBLE_big):
1321 Case(i_CONST_FLOAT_big):
1322 Case(i_VAR_FLOAT_big):
1323 Case(i_CONST_CHAR_big):
1324 Case(i_VAR_CHAR_big):
1325 Case(i_VAR_ADDR_big):
1326 Case(i_VAR_STABLE_big):
1327 Case(i_CONST_INTEGER_big):
1328 Case(i_VAR_INT_big):
1329 Case(i_VAR_WORD_big):
1330 Case(i_RETADDR_big):
1334 disInstr ( bco, PC );
1335 barf("\nUnrecognised instruction");
1339 barf("enterBCO: ran off end of loop");
1343 # undef LoopTopLabel
1349 /* ---------------------------------------------------- */
1350 /* End of the bytecode evaluator */
1351 /* ---------------------------------------------------- */
1355 StgBlockingQueue* bh;
1356 StgCAF* caf = (StgCAF*)obj;
1357 if (xSp - sizeofW(StgUpdateFrame) < xSpLim) {
1358 xPushCPtr(obj); /* code to restart with */
1359 RETURN(StackOverflow);
1361 SSS; bh = (StgBlockingQueue*)grabHpUpd(BLACKHOLE_sizeW()); LLL;
1362 SET_INFO(bh,&CAF_BLACKHOLE_info);
1363 bh->blocking_queue = EndTSOQueue;
1365 fprintf(stderr,"Created CAF_BLACKHOLE %p for CAF %p"
1366 " in evaluator\n",bh,caf));
1367 SET_INFO(caf,&CAF_ENTERED_info);
1368 caf->value = (StgClosure*)bh;
1370 SSS; newCAF_made_by_Hugs(caf); LLL;
1372 xPushUpdateFrame(bh,0);
1373 xSp -= sizeofW(StgUpdateFrame);
1379 StgCAF* caf = (StgCAF*)obj;
1380 obj = caf->value; /* it's just a fancy indirection */
1386 case SE_CAF_BLACKHOLE:
1388 /* Let the scheduler figure out what to do :-) */
1389 cap->rCurrentTSO->what_next = ThreadEnterGHC;
1391 RETURN(ThreadYielding);
1395 StgAP_UPD* ap = stgCast(StgAP_UPD*,obj);
1397 if (xSp - (i + sizeofW(StgUpdateFrame)) < xSpLim) {
1398 xPushCPtr(obj); /* code to restart with */
1399 RETURN(StackOverflow);
1401 /* ToDo: look for xSp==xSu && stackInt(0) == UPD_FRAME
1402 and insert an indirection immediately */
1403 xPushUpdateFrame(ap,0);
1404 xSp -= sizeofW(StgUpdateFrame);
1406 xPushWord(payloadWord(ap,i));
1409 #ifdef EAGER_BLACKHOLING
1410 #warn LAZY_BLACKHOLING is default for StgHugs
1411 #error Dont know if EAGER_BLACKHOLING works in StgHugs
1413 /* superfluous - but makes debugging easier */
1414 StgBlackHole* bh = stgCast(StgBlackHole*,ap);
1415 SET_INFO(bh,&BLACKHOLE_info);
1416 bh->blocking_queue = EndTSOQueue;
1418 fprintf(stderr,"Eagerly blackholed AP_UPD %p in evaluator\n",bh));
1421 #endif /* EAGER_BLACKHOLING */
1426 StgPAP* pap = stgCast(StgPAP*,obj);
1427 int i = pap->n_args; /* ToDo: stack check */
1428 /* ToDo: if PAP is in whnf, we can update any update frames
1432 xPushWord(payloadWord(pap,i));
1439 obj = stgCast(StgInd*,obj)->indirectee;
1444 obj = stgCast(StgIndOldGen*,obj)->indirectee;
1453 case CONSTR_INTLIKE:
1454 case CONSTR_CHARLIKE:
1456 case CONSTR_NOCAF_STATIC:
1459 switch (get_itbl(stgCast(StgClosure*,xSp))->type) {
1461 SSS; PopCatchFrame(); LLL;
1464 xPopUpdateFrame(obj);
1467 SSS; PopSeqFrame(); LLL;
1471 ASSERT(xSp==(P_)xSu);
1474 fprintf(stderr, "hit a STOP_FRAME\n");
1476 fprintf(stderr,"xSp = %p\txSu = %p\n", xSp, xSu);
1477 printStack(xSp,cap->rCurrentTSO->stack
1478 + cap->rCurrentTSO->stack_size,xSu);
1481 SSS; PopStopFrame(obj); LLL;
1482 RETURN(ThreadFinished);
1492 /* was: goto enterLoop;
1493 But we know that obj must be a bco now, so jump directly.
1496 case RET_SMALL: /* return to GHC */
1500 cap->rCurrentTSO->what_next = ThreadEnterGHC;
1502 RETURN(ThreadYielding);
1504 belch("entered CONSTR with invalid continuation on stack");
1507 printObj(stgCast(StgClosure*,xSp));
1510 barf("bailing out");
1517 //fprintf(stderr, "enterCountI = %d\n", enterCountI);
1518 //fprintf(stderr, "entering unknown closure -- yielding to sched\n");
1521 cap->rCurrentTSO->what_next = ThreadEnterGHC;
1522 xPushCPtr(obj); /* code to restart with */
1523 RETURN(ThreadYielding);
1526 barf("Ran off the end of enter - yoiks");
1543 #undef xSetStackWord
1546 #undef xPushTaggedInt
1547 #undef xPopTaggedInt
1548 #undef xTaggedStackInt
1549 #undef xPushTaggedWord
1550 #undef xPopTaggedWord
1551 #undef xTaggedStackWord
1552 #undef xPushTaggedAddr
1553 #undef xTaggedStackAddr
1554 #undef xPopTaggedAddr
1555 #undef xPushTaggedStable
1556 #undef xTaggedStackStable
1557 #undef xPopTaggedStable
1558 #undef xPushTaggedChar
1559 #undef xTaggedStackChar
1560 #undef xPopTaggedChar
1561 #undef xPushTaggedFloat
1562 #undef xTaggedStackFloat
1563 #undef xPopTaggedFloat
1564 #undef xPushTaggedDouble
1565 #undef xTaggedStackDouble
1566 #undef xPopTaggedDouble
1567 #undef xPopUpdateFrame
1568 #undef xPushUpdateFrame
1571 /* --------------------------------------------------------------------------
1572 * Supporting routines for primops
1573 * ------------------------------------------------------------------------*/
1575 static inline void PushTag ( StackTag t )
1577 inline void PushPtr ( StgPtr x )
1578 { *(--stgCast(StgPtr*,gSp)) = x; }
1579 static inline void PushCPtr ( StgClosure* x )
1580 { *(--stgCast(StgClosure**,gSp)) = x; }
1581 static inline void PushInt ( StgInt x )
1582 { *(--stgCast(StgInt*,gSp)) = x; }
1583 static inline void PushWord ( StgWord x )
1584 { *(--stgCast(StgWord*,gSp)) = x; }
1587 static inline void checkTag ( StackTag t1, StackTag t2 )
1588 { ASSERT(t1 == t2);}
1589 static inline void PopTag ( StackTag t )
1590 { checkTag(t,*(gSp++)); }
1591 inline StgPtr PopPtr ( void )
1592 { return *stgCast(StgPtr*,gSp)++; }
1593 static inline StgClosure* PopCPtr ( void )
1594 { return *stgCast(StgClosure**,gSp)++; }
1595 static inline StgInt PopInt ( void )
1596 { return *stgCast(StgInt*,gSp)++; }
1597 static inline StgWord PopWord ( void )
1598 { return *stgCast(StgWord*,gSp)++; }
1600 static inline StgPtr stackPtr ( StgStackOffset i )
1601 { return *stgCast(StgPtr*, gSp+i); }
1602 static inline StgInt stackInt ( StgStackOffset i )
1603 { return *stgCast(StgInt*, gSp+i); }
1604 static inline StgWord stackWord ( StgStackOffset i )
1605 { return *stgCast(StgWord*,gSp+i); }
1607 static inline void setStackWord ( StgStackOffset i, StgWord w )
1610 static inline void PushTaggedRealWorld( void )
1611 { PushTag(REALWORLD_TAG); }
1612 inline void PushTaggedInt ( StgInt x )
1613 { gSp -= sizeofW(StgInt); *gSp = x; PushTag(INT_TAG); }
1614 inline void PushTaggedWord ( StgWord x )
1615 { gSp -= sizeofW(StgWord); *gSp = x; PushTag(WORD_TAG); }
1616 inline void PushTaggedAddr ( StgAddr x )
1617 { gSp -= sizeofW(StgAddr); *gSp = (W_)x; PushTag(ADDR_TAG); }
1618 inline void PushTaggedChar ( StgChar x )
1619 { gSp -= sizeofW(StgChar); *gSp = stgCast(StgWord,x); PushTag(CHAR_TAG); }
1620 inline void PushTaggedFloat ( StgFloat x )
1621 { gSp -= sizeofW(StgFloat); ASSIGN_FLT(gSp,x); PushTag(FLOAT_TAG); }
1622 inline void PushTaggedDouble ( StgDouble x )
1623 { gSp -= sizeofW(StgDouble); ASSIGN_DBL(gSp,x); PushTag(DOUBLE_TAG); }
1624 inline void PushTaggedStablePtr ( StgStablePtr x )
1625 { gSp -= sizeofW(StgStablePtr); *gSp = x; PushTag(STABLE_TAG); }
1626 static inline void PushTaggedBool ( int x )
1627 { PushTaggedInt(x); }
1631 static inline void PopTaggedRealWorld ( void )
1632 { PopTag(REALWORLD_TAG); }
1633 inline StgInt PopTaggedInt ( void )
1634 { StgInt r; PopTag(INT_TAG); r = *stgCast(StgInt*, gSp);
1635 gSp += sizeofW(StgInt); return r;}
1636 inline StgWord PopTaggedWord ( void )
1637 { StgWord r; PopTag(WORD_TAG); r = *stgCast(StgWord*, gSp);
1638 gSp += sizeofW(StgWord); return r;}
1639 inline StgAddr PopTaggedAddr ( void )
1640 { StgAddr r; PopTag(ADDR_TAG); r = *stgCast(StgAddr*, gSp);
1641 gSp += sizeofW(StgAddr); return r;}
1642 inline StgChar PopTaggedChar ( void )
1643 { StgChar r; PopTag(CHAR_TAG); r = stgCast(StgChar, *gSp);
1644 gSp += sizeofW(StgChar); return r;}
1645 inline StgFloat PopTaggedFloat ( void )
1646 { StgFloat r; PopTag(FLOAT_TAG); r = PK_FLT(gSp);
1647 gSp += sizeofW(StgFloat); return r;}
1648 inline StgDouble PopTaggedDouble ( void )
1649 { StgDouble r; PopTag(DOUBLE_TAG); r = PK_DBL(gSp);
1650 gSp += sizeofW(StgDouble); return r;}
1651 inline StgStablePtr PopTaggedStablePtr ( void )
1652 { StgInt r; PopTag(STABLE_TAG); r = *stgCast(StgStablePtr*, gSp);
1653 gSp += sizeofW(StgStablePtr); return r;}
1657 static inline StgInt taggedStackInt ( StgStackOffset i )
1658 { checkTag(INT_TAG,gSp[i]); return *stgCast(StgInt*, gSp+1+i); }
1659 static inline StgWord taggedStackWord ( StgStackOffset i )
1660 { checkTag(WORD_TAG,gSp[i]); return *stgCast(StgWord*, gSp+1+i); }
1661 static inline StgAddr taggedStackAddr ( StgStackOffset i )
1662 { checkTag(ADDR_TAG,gSp[i]); return *stgCast(StgAddr*, gSp+1+i); }
1663 static inline StgChar taggedStackChar ( StgStackOffset i )
1664 { checkTag(CHAR_TAG,gSp[i]); return stgCast(StgChar, *(gSp+1+i)) ; }
1665 static inline StgFloat taggedStackFloat ( StgStackOffset i )
1666 { checkTag(FLOAT_TAG,gSp[i]); return PK_FLT(gSp+1+i); }
1667 static inline StgDouble taggedStackDouble ( StgStackOffset i )
1668 { checkTag(DOUBLE_TAG,gSp[i]); return PK_DBL(gSp+1+i); }
1669 static inline StgStablePtr taggedStackStable ( StgStackOffset i )
1670 { checkTag(STABLE_TAG,gSp[i]); return *stgCast(StgStablePtr*, gSp+1+i); }
1673 /* --------------------------------------------------------------------------
1676 * Should we allocate from a nursery or use the
1677 * doYouWantToGC/allocate interface? We'd already implemented a
1678 * nursery-style scheme when the doYouWantToGC/allocate interface
1680 * One reason to prefer the doYouWantToGC/allocate interface is to
1681 * support operations which allocate an unknown amount in the heap
1682 * (array ops, gmp ops, etc)
1683 * ------------------------------------------------------------------------*/
1685 static inline StgPtr grabHpUpd( nat size )
1687 ASSERT( size >= MIN_UPD_SIZE + sizeofW(StgHeader) );
1688 #ifdef CRUDE_PROFILING
1689 cp_bill_words ( size );
1691 return allocate(size);
1694 static inline StgPtr grabHpNonUpd( nat size )
1696 ASSERT( size >= MIN_NONUPD_SIZE + sizeofW(StgHeader) );
1697 #ifdef CRUDE_PROFILING
1698 cp_bill_words ( size );
1700 return allocate(size);
1703 /* --------------------------------------------------------------------------
1704 * Manipulate "update frame" list:
1705 * o Update frames (based on stg_do_update and friends in Updates.hc)
1706 * o Error handling/catching (based on catchzh_fast and friends in Prims.hc)
1707 * o Seq frames (based on seq_frame_entry in Prims.hc)
1709 * ------------------------------------------------------------------------*/
1711 static inline void PopUpdateFrame ( StgClosure* obj )
1713 /* NB: doesn't assume that gSp == gSu */
1715 fprintf(stderr, "Updating ");
1716 printPtr(stgCast(StgPtr,gSu->updatee));
1717 fprintf(stderr, " with ");
1719 fprintf(stderr,"gSp = %p\tgSu = %p\n\n", gSp, gSu);
1721 #ifdef EAGER_BLACKHOLING
1722 #warn LAZY_BLACKHOLING is default for StgHugs
1723 #error Dont know if EAGER_BLACKHOLING works in StgHugs
1724 ASSERT(get_itbl(gSu->updatee)->type == BLACKHOLE
1725 || get_itbl(gSu->updatee)->type == SE_BLACKHOLE
1726 || get_itbl(gSu->updatee)->type == CAF_BLACKHOLE
1727 || get_itbl(gSu->updatee)->type == SE_CAF_BLACKHOLE
1729 #endif /* EAGER_BLACKHOLING */
1730 UPD_IND(gSu->updatee,obj);
1731 gSp = stgCast(StgStackPtr,gSu) + sizeofW(StgUpdateFrame);
1735 static inline void PopStopFrame ( StgClosure* obj )
1737 /* Move gSu just off the end of the stack, we're about to gSpam the
1738 * STOP_FRAME with the return value.
1740 gSu = stgCast(StgUpdateFrame*,gSp+1);
1741 *stgCast(StgClosure**,gSp) = obj;
1744 static inline void PushCatchFrame ( StgClosure* handler )
1747 /* ToDo: stack check! */
1748 gSp -= sizeofW(StgCatchFrame);
1749 fp = stgCast(StgCatchFrame*,gSp);
1750 SET_HDR(fp,(StgInfoTable*)&catch_frame_info,CCCS);
1751 fp->handler = handler;
1753 gSu = stgCast(StgUpdateFrame*,fp);
1756 static inline void PopCatchFrame ( void )
1758 /* NB: doesn't assume that gSp == gSu */
1759 /* fprintf(stderr,"Popping catch frame\n"); */
1760 gSp = stgCast(StgStackPtr,gSu) + sizeofW(StgCatchFrame);
1761 gSu = stgCast(StgCatchFrame*,gSu)->link;
1764 static inline void PushSeqFrame ( void )
1767 /* ToDo: stack check! */
1768 gSp -= sizeofW(StgSeqFrame);
1769 fp = stgCast(StgSeqFrame*,gSp);
1770 SET_HDR(fp,(StgInfoTable*)&seq_frame_info,CCCS);
1772 gSu = stgCast(StgUpdateFrame*,fp);
1775 static inline void PopSeqFrame ( void )
1777 /* NB: doesn't assume that gSp == gSu */
1778 gSp = stgCast(StgStackPtr,gSu) + sizeofW(StgSeqFrame);
1779 gSu = stgCast(StgSeqFrame*,gSu)->link;
1782 static inline StgClosure* raiseAnError ( StgClosure* exception )
1784 /* This closure represents the expression 'primRaise E' where E
1785 * is the exception raised (:: Exception).
1786 * It is used to overwrite all the
1787 * thunks which are currently under evaluation.
1789 HaskellObj primRaiseClosure
1790 = asmClosureOfObject(getHugs_AsmObject_for("primRaise"));
1791 HaskellObj reraiseClosure
1792 = rts_apply ( primRaiseClosure, exception );
1795 switch (get_itbl(gSu)->type) {
1797 UPD_IND(gSu->updatee,reraiseClosure);
1798 gSp = stgCast(StgStackPtr,gSu) + sizeofW(StgUpdateFrame);
1804 case CATCH_FRAME: /* found it! */
1806 StgCatchFrame* fp = stgCast(StgCatchFrame*,gSu);
1807 StgClosure *handler = fp->handler;
1809 gSp += sizeofW(StgCatchFrame); /* Pop */
1810 PushCPtr(exception);
1814 barf("raiseError: uncaught exception: STOP_FRAME");
1816 barf("raiseError: weird activation record");
1822 static StgClosure* makeErrorCall ( const char* msg )
1824 /* Note! the msg string should be allocated in a
1825 place which will not get freed -- preferably
1826 read-only data of the program. That's because
1827 the thunk we build here may linger indefinitely.
1828 (thinks: probably not so, but anyway ...)
1831 = asmClosureOfObject(getHugs_AsmObject_for("error"));
1833 = asmClosureOfObject(getHugs_AsmObject_for("hugsprimUnpackString"));
1835 = rts_apply ( unpack, rts_mkAddr ( (void*)msg ) );
1837 = rts_apply ( error, thunk );
1839 (StgClosure*) thunk;
1842 #define raiseIndex(where) makeErrorCall("Array index out of range in " where)
1843 #define raiseDiv0(where) makeErrorCall("Division by zero in " where)
1845 /* --------------------------------------------------------------------------
1847 * ------------------------------------------------------------------------*/
1849 #define OP_CC_B(e) \
1851 unsigned char x = PopTaggedChar(); \
1852 unsigned char y = PopTaggedChar(); \
1853 PushTaggedBool(e); \
1858 unsigned char x = PopTaggedChar(); \
1867 #define OP_IW_I(e) \
1869 StgInt x = PopTaggedInt(); \
1870 StgWord y = PopTaggedWord(); \
1874 #define OP_II_I(e) \
1876 StgInt x = PopTaggedInt(); \
1877 StgInt y = PopTaggedInt(); \
1881 #define OP_II_B(e) \
1883 StgInt x = PopTaggedInt(); \
1884 StgInt y = PopTaggedInt(); \
1885 PushTaggedBool(e); \
1890 PushTaggedAddr(e); \
1895 StgInt x = PopTaggedInt(); \
1896 PushTaggedAddr(e); \
1901 StgInt x = PopTaggedInt(); \
1907 PushTaggedChar(e); \
1912 StgInt x = PopTaggedInt(); \
1913 PushTaggedChar(e); \
1918 PushTaggedWord(e); \
1923 StgInt x = PopTaggedInt(); \
1924 PushTaggedWord(e); \
1929 StgInt x = PopTaggedInt(); \
1930 PushTaggedStablePtr(e); \
1935 PushTaggedFloat(e); \
1940 StgInt x = PopTaggedInt(); \
1941 PushTaggedFloat(e); \
1946 PushTaggedDouble(e); \
1951 StgInt x = PopTaggedInt(); \
1952 PushTaggedDouble(e); \
1955 #define OP_WW_B(e) \
1957 StgWord x = PopTaggedWord(); \
1958 StgWord y = PopTaggedWord(); \
1959 PushTaggedBool(e); \
1962 #define OP_WW_W(e) \
1964 StgWord x = PopTaggedWord(); \
1965 StgWord y = PopTaggedWord(); \
1966 PushTaggedWord(e); \
1971 StgWord x = PopTaggedWord(); \
1977 StgStablePtr x = PopTaggedStablePtr(); \
1983 StgWord x = PopTaggedWord(); \
1984 PushTaggedWord(e); \
1987 #define OP_AA_B(e) \
1989 StgAddr x = PopTaggedAddr(); \
1990 StgAddr y = PopTaggedAddr(); \
1991 PushTaggedBool(e); \
1995 StgAddr x = PopTaggedAddr(); \
1998 #define OP_AI_C(s) \
2000 StgAddr x = PopTaggedAddr(); \
2001 int y = PopTaggedInt(); \
2004 PushTaggedChar(r); \
2006 #define OP_AI_I(s) \
2008 StgAddr x = PopTaggedAddr(); \
2009 int y = PopTaggedInt(); \
2014 #define OP_AI_A(s) \
2016 StgAddr x = PopTaggedAddr(); \
2017 int y = PopTaggedInt(); \
2020 PushTaggedAddr(s); \
2022 #define OP_AI_F(s) \
2024 StgAddr x = PopTaggedAddr(); \
2025 int y = PopTaggedInt(); \
2028 PushTaggedFloat(r); \
2030 #define OP_AI_D(s) \
2032 StgAddr x = PopTaggedAddr(); \
2033 int y = PopTaggedInt(); \
2036 PushTaggedDouble(r); \
2038 #define OP_AI_s(s) \
2040 StgAddr x = PopTaggedAddr(); \
2041 int y = PopTaggedInt(); \
2044 PushTaggedStablePtr(r); \
2046 #define OP_AIC_(s) \
2048 StgAddr x = PopTaggedAddr(); \
2049 int y = PopTaggedInt(); \
2050 StgChar z = PopTaggedChar(); \
2053 #define OP_AII_(s) \
2055 StgAddr x = PopTaggedAddr(); \
2056 int y = PopTaggedInt(); \
2057 StgInt z = PopTaggedInt(); \
2060 #define OP_AIA_(s) \
2062 StgAddr x = PopTaggedAddr(); \
2063 int y = PopTaggedInt(); \
2064 StgAddr z = PopTaggedAddr(); \
2067 #define OP_AIF_(s) \
2069 StgAddr x = PopTaggedAddr(); \
2070 int y = PopTaggedInt(); \
2071 StgFloat z = PopTaggedFloat(); \
2074 #define OP_AID_(s) \
2076 StgAddr x = PopTaggedAddr(); \
2077 int y = PopTaggedInt(); \
2078 StgDouble z = PopTaggedDouble(); \
2081 #define OP_AIs_(s) \
2083 StgAddr x = PopTaggedAddr(); \
2084 int y = PopTaggedInt(); \
2085 StgStablePtr z = PopTaggedStablePtr(); \
2090 #define OP_FF_B(e) \
2092 StgFloat x = PopTaggedFloat(); \
2093 StgFloat y = PopTaggedFloat(); \
2094 PushTaggedBool(e); \
2097 #define OP_FF_F(e) \
2099 StgFloat x = PopTaggedFloat(); \
2100 StgFloat y = PopTaggedFloat(); \
2101 PushTaggedFloat(e); \
2106 StgFloat x = PopTaggedFloat(); \
2107 PushTaggedFloat(e); \
2112 StgFloat x = PopTaggedFloat(); \
2113 PushTaggedBool(e); \
2118 StgFloat x = PopTaggedFloat(); \
2124 StgFloat x = PopTaggedFloat(); \
2125 PushTaggedDouble(e); \
2128 #define OP_DD_B(e) \
2130 StgDouble x = PopTaggedDouble(); \
2131 StgDouble y = PopTaggedDouble(); \
2132 PushTaggedBool(e); \
2135 #define OP_DD_D(e) \
2137 StgDouble x = PopTaggedDouble(); \
2138 StgDouble y = PopTaggedDouble(); \
2139 PushTaggedDouble(e); \
2144 StgDouble x = PopTaggedDouble(); \
2145 PushTaggedBool(e); \
2150 StgDouble x = PopTaggedDouble(); \
2151 PushTaggedDouble(e); \
2156 StgDouble x = PopTaggedDouble(); \
2162 StgDouble x = PopTaggedDouble(); \
2163 PushTaggedFloat(e); \
2167 StgPtr CreateByteArrayToHoldInteger ( int nbytes )
2169 StgWord words = (nbytes+sizeof(W_)-1)/sizeof(W_);
2170 StgWord size = sizeofW(StgArrWords) + words;
2171 StgArrWords* arr = (StgArrWords*)allocate(size);
2172 SET_HDR(arr,&ARR_WORDS_info,CCCS);
2174 ASSERT((W_)nbytes <= arr->words * sizeof(W_));
2177 for (i = 0; i < words; ++i) {
2178 arr->payload[i] = 0xdeadbeef;
2180 { B* b = (B*) &(arr->payload[0]);
2181 b->used = b->sign = 0;
2187 B* IntegerInsideByteArray ( StgPtr arr0 )
2190 StgArrWords* arr = (StgArrWords*)arr0;
2191 ASSERT(GET_INFO(arr) == &ARR_WORDS_info);
2192 b = (B*) &(arr->payload[0]);
2196 void SloppifyIntegerEnd ( StgPtr arr0 )
2198 StgArrWords* arr = (StgArrWords*)arr0;
2199 B* b = (B*) & (arr->payload[0]);
2200 I_ nwunused = arr->words - sizeofW(B) - (b->used+sizeof(W_)-1)/sizeof(W_);
2201 if (nwunused >= ((I_)sizeofW(StgArrWords))) {
2203 b->size -= nwunused * sizeof(W_);
2204 if (b->size < b->used) b->size = b->used;
2207 arr->words -= nwunused;
2208 slop = (StgArrWords*)&(arr->payload[arr->words]);
2209 SET_HDR(slop,&ARR_WORDS_info,CCCS);
2210 slop->words = nwunused - sizeofW(StgArrWords);
2211 ASSERT( &(slop->payload[slop->words]) ==
2212 &(arr->payload[arr->words + nwunused]) );
2216 #define OP_Z_Z(op) \
2218 B* x = IntegerInsideByteArray(PopPtr()); \
2219 int n = mycat2(size_,op)(x); \
2220 StgPtr p = CreateByteArrayToHoldInteger(n); \
2221 mycat2(do_,op)(x,n,IntegerInsideByteArray(p)); \
2222 SloppifyIntegerEnd(p); \
2225 #define OP_ZZ_Z(op) \
2227 B* x = IntegerInsideByteArray(PopPtr()); \
2228 B* y = IntegerInsideByteArray(PopPtr()); \
2229 int n = mycat2(size_,op)(x,y); \
2230 StgPtr p = CreateByteArrayToHoldInteger(n); \
2231 mycat2(do_,op)(x,y,n,IntegerInsideByteArray(p)); \
2232 SloppifyIntegerEnd(p); \
2239 #define HEADER_mI(ty,where) \
2240 StgArrWords* x = stgCast(StgArrWords*,PopPtr()); \
2241 nat i = PopTaggedInt(); \
2242 if (i * sizeof(ty) + (sizeof(ty)) > sizeof(StgWord) * x->words) { \
2243 return (raiseIndex(where)); \
2245 #define OP_mI_ty(ty,where,s) \
2247 HEADER_mI(mycat2(Stg,ty),where) \
2248 { mycat2(Stg,ty) r; \
2250 mycat2(PushTagged,ty)(r); \
2253 #define OP_mIty_(ty,where,s) \
2255 HEADER_mI(mycat2(Stg,ty),where) \
2257 mycat2(Stg,ty) z = mycat2(PopTagged,ty)(); \
2263 static void myStackCheck ( Capability* cap )
2265 /* fprintf(stderr, "myStackCheck\n"); */
2266 if (!(gSpLim <= gSp && gSp <= stgCast(StgPtr,gSu))) {
2267 fprintf(stderr, "myStackCheck: invalid initial gSp/gSu \n" );
2271 if (!( (P_)gSu >= (P_)cap->rCurrentTSO->stack
2273 (P_)gSu <= (P_)(cap->rCurrentTSO->stack
2274 + cap->rCurrentTSO->stack_size))) {
2275 fprintf ( stderr, "myStackCheck: gSu out of stack\n" );
2278 switch (get_itbl(stgCast(StgClosure*,gSu))->type) {
2280 gSu = (StgUpdateFrame*) ((StgCatchFrame*)(gSu))->link;
2283 gSu = (StgUpdateFrame*) ((StgUpdateFrame*)(gSu))->link;
2286 gSu = (StgUpdateFrame*) ((StgSeqFrame*)(gSu))->link;
2291 fprintf(stderr, "myStackCheck: invalid activation record\n"); assert(0);
2298 /* --------------------------------------------------------------------------
2299 * Primop stuff for bytecode interpreter
2300 * ------------------------------------------------------------------------*/
2302 /* Returns & of the next thing to enter (if throwing an exception),
2303 or NULL in the normal case.
2305 static void* enterBCO_primop1 ( int primop1code )
2308 barf("enterBCO_primop1 in combined mode");
2310 switch (primop1code) {
2311 case i_pushseqframe:
2313 StgClosure* c = PopCPtr();
2318 case i_pushcatchframe:
2320 StgClosure* e = PopCPtr();
2321 StgClosure* h = PopCPtr();
2327 case i_gtChar: OP_CC_B(x>y); break;
2328 case i_geChar: OP_CC_B(x>=y); break;
2329 case i_eqChar: OP_CC_B(x==y); break;
2330 case i_neChar: OP_CC_B(x!=y); break;
2331 case i_ltChar: OP_CC_B(x<y); break;
2332 case i_leChar: OP_CC_B(x<=y); break;
2333 case i_charToInt: OP_C_I(x); break;
2334 case i_intToChar: OP_I_C(x); break;
2336 case i_gtInt: OP_II_B(x>y); break;
2337 case i_geInt: OP_II_B(x>=y); break;
2338 case i_eqInt: OP_II_B(x==y); break;
2339 case i_neInt: OP_II_B(x!=y); break;
2340 case i_ltInt: OP_II_B(x<y); break;
2341 case i_leInt: OP_II_B(x<=y); break;
2342 case i_minInt: OP__I(INT_MIN); break;
2343 case i_maxInt: OP__I(INT_MAX); break;
2344 case i_plusInt: OP_II_I(x+y); break;
2345 case i_minusInt: OP_II_I(x-y); break;
2346 case i_timesInt: OP_II_I(x*y); break;
2349 int x = PopTaggedInt();
2350 int y = PopTaggedInt();
2352 return (raiseDiv0("quotInt"));
2354 /* ToDo: protect against minInt / -1 errors
2355 * (repeat for all other division primops) */
2361 int x = PopTaggedInt();
2362 int y = PopTaggedInt();
2364 return (raiseDiv0("remInt"));
2371 StgInt x = PopTaggedInt();
2372 StgInt y = PopTaggedInt();
2374 return (raiseDiv0("quotRemInt"));
2376 PushTaggedInt(x%y); /* last result */
2377 PushTaggedInt(x/y); /* first result */
2380 case i_negateInt: OP_I_I(-x); break;
2382 case i_andInt: OP_II_I(x&y); break;
2383 case i_orInt: OP_II_I(x|y); break;
2384 case i_xorInt: OP_II_I(x^y); break;
2385 case i_notInt: OP_I_I(~x); break;
2386 case i_shiftLInt: OP_II_I(x<<y); break;
2387 case i_shiftRAInt: OP_II_I(x>>y); break; /* ToDo */
2388 case i_shiftRLInt: OP_II_I(x>>y); break; /* ToDo */
2390 case i_gtWord: OP_WW_B(x>y); break;
2391 case i_geWord: OP_WW_B(x>=y); break;
2392 case i_eqWord: OP_WW_B(x==y); break;
2393 case i_neWord: OP_WW_B(x!=y); break;
2394 case i_ltWord: OP_WW_B(x<y); break;
2395 case i_leWord: OP_WW_B(x<=y); break;
2396 case i_minWord: OP__W(0); break;
2397 case i_maxWord: OP__W(UINT_MAX); break;
2398 case i_plusWord: OP_WW_W(x+y); break;
2399 case i_minusWord: OP_WW_W(x-y); break;
2400 case i_timesWord: OP_WW_W(x*y); break;
2403 StgWord x = PopTaggedWord();
2404 StgWord y = PopTaggedWord();
2406 return (raiseDiv0("quotWord"));
2408 PushTaggedWord(x/y);
2413 StgWord x = PopTaggedWord();
2414 StgWord y = PopTaggedWord();
2416 return (raiseDiv0("remWord"));
2418 PushTaggedWord(x%y);
2423 StgWord x = PopTaggedWord();
2424 StgWord y = PopTaggedWord();
2426 return (raiseDiv0("quotRemWord"));
2428 PushTaggedWord(x%y); /* last result */
2429 PushTaggedWord(x/y); /* first result */
2432 case i_negateWord: OP_W_W(-x); break;
2433 case i_andWord: OP_WW_W(x&y); break;
2434 case i_orWord: OP_WW_W(x|y); break;
2435 case i_xorWord: OP_WW_W(x^y); break;
2436 case i_notWord: OP_W_W(~x); break;
2437 case i_shiftLWord: OP_WW_W(x<<y); break;
2438 case i_shiftRAWord: OP_WW_W(x>>y); break; /* ToDo */
2439 case i_shiftRLWord: OP_WW_W(x>>y); break; /* ToDo */
2440 case i_intToWord: OP_I_W(x); break;
2441 case i_wordToInt: OP_W_I(x); break;
2443 case i_gtAddr: OP_AA_B(x>y); break;
2444 case i_geAddr: OP_AA_B(x>=y); break;
2445 case i_eqAddr: OP_AA_B(x==y); break;
2446 case i_neAddr: OP_AA_B(x!=y); break;
2447 case i_ltAddr: OP_AA_B(x<y); break;
2448 case i_leAddr: OP_AA_B(x<=y); break;
2449 case i_intToAddr: OP_I_A((StgAddr)x); break; /* ToDo */
2450 case i_addrToInt: OP_A_I((StgInt)x); break; /* ToDo */
2452 case i_intToStable: OP_I_s(x); break;
2453 case i_stableToInt: OP_s_I(x); break;
2455 case i_indexCharOffAddr: OP_AI_C(indexCharOffAddrzh(r,x,y)); break;
2456 case i_readCharOffAddr: OP_AI_C(indexCharOffAddrzh(r,x,y)); break;
2457 case i_writeCharOffAddr: OP_AIC_(writeCharOffAddrzh(x,y,z)); break;
2459 case i_indexIntOffAddr: OP_AI_I(indexIntOffAddrzh(r,x,y)); break;
2460 case i_readIntOffAddr: OP_AI_I(indexIntOffAddrzh(r,x,y)); break;
2461 case i_writeIntOffAddr: OP_AII_(writeIntOffAddrzh(x,y,z)); break;
2463 case i_indexAddrOffAddr: OP_AI_A(indexAddrOffAddrzh(r,x,y)); break;
2464 case i_readAddrOffAddr: OP_AI_A(indexAddrOffAddrzh(r,x,y)); break;
2465 case i_writeAddrOffAddr: OP_AIA_(writeAddrOffAddrzh(x,y,z)); break;
2467 case i_indexFloatOffAddr: OP_AI_F(indexFloatOffAddrzh(r,x,y)); break;
2468 case i_readFloatOffAddr: OP_AI_F(indexFloatOffAddrzh(r,x,y)); break;
2469 case i_writeFloatOffAddr: OP_AIF_(writeFloatOffAddrzh(x,y,z)); break;
2471 case i_indexDoubleOffAddr: OP_AI_D(indexDoubleOffAddrzh(r,x,y)); break;
2472 case i_readDoubleOffAddr: OP_AI_D(indexDoubleOffAddrzh(r,x,y)); break;
2473 case i_writeDoubleOffAddr: OP_AID_(writeDoubleOffAddrzh(x,y,z)); break;
2475 case i_indexStableOffAddr: OP_AI_s(indexStablePtrOffAddrzh(r,x,y)); break;
2476 case i_readStableOffAddr: OP_AI_s(indexStablePtrOffAddrzh(r,x,y)); break;
2477 case i_writeStableOffAddr: OP_AIs_(writeStablePtrOffAddrzh(x,y,z)); break;
2479 case i_compareInteger:
2481 B* x = IntegerInsideByteArray(PopPtr());
2482 B* y = IntegerInsideByteArray(PopPtr());
2483 StgInt r = do_cmp(x,y);
2484 PushTaggedInt(r<0 ? -1 : (r>0 ? 1 : 0));
2487 case i_negateInteger: OP_Z_Z(neg); break;
2488 case i_plusInteger: OP_ZZ_Z(add); break;
2489 case i_minusInteger: OP_ZZ_Z(sub); break;
2490 case i_timesInteger: OP_ZZ_Z(mul); break;
2491 case i_quotRemInteger:
2493 B* x = IntegerInsideByteArray(PopPtr());
2494 B* y = IntegerInsideByteArray(PopPtr());
2495 int n = size_qrm(x,y);
2496 StgPtr q = CreateByteArrayToHoldInteger(n);
2497 StgPtr r = CreateByteArrayToHoldInteger(n);
2498 if (do_getsign(y)==0)
2499 return (raiseDiv0("quotRemInteger"));
2500 do_qrm(x,y,n,IntegerInsideByteArray(q),
2501 IntegerInsideByteArray(r));
2502 SloppifyIntegerEnd(q);
2503 SloppifyIntegerEnd(r);
2508 case i_intToInteger:
2510 int n = size_fromInt();
2511 StgPtr p = CreateByteArrayToHoldInteger(n);
2512 do_fromInt( PopTaggedInt(), n, IntegerInsideByteArray(p));
2516 case i_wordToInteger:
2518 int n = size_fromWord();
2519 StgPtr p = CreateByteArrayToHoldInteger(n);
2520 do_fromWord( PopTaggedWord(), n, IntegerInsideByteArray(p));
2524 case i_integerToInt: PushTaggedInt(do_toInt(
2525 IntegerInsideByteArray(PopPtr())
2529 case i_integerToWord: PushTaggedWord(do_toWord(
2530 IntegerInsideByteArray(PopPtr())
2534 case i_integerToFloat: PushTaggedFloat(do_toFloat(
2535 IntegerInsideByteArray(PopPtr())
2539 case i_integerToDouble: PushTaggedDouble(do_toDouble(
2540 IntegerInsideByteArray(PopPtr())
2544 case i_gtFloat: OP_FF_B(x>y); break;
2545 case i_geFloat: OP_FF_B(x>=y); break;
2546 case i_eqFloat: OP_FF_B(x==y); break;
2547 case i_neFloat: OP_FF_B(x!=y); break;
2548 case i_ltFloat: OP_FF_B(x<y); break;
2549 case i_leFloat: OP_FF_B(x<=y); break;
2550 case i_minFloat: OP__F(FLT_MIN); break;
2551 case i_maxFloat: OP__F(FLT_MAX); break;
2552 case i_radixFloat: OP__I(FLT_RADIX); break;
2553 case i_digitsFloat: OP__I(FLT_MANT_DIG); break;
2554 case i_minExpFloat: OP__I(FLT_MIN_EXP); break;
2555 case i_maxExpFloat: OP__I(FLT_MAX_EXP); break;
2556 case i_plusFloat: OP_FF_F(x+y); break;
2557 case i_minusFloat: OP_FF_F(x-y); break;
2558 case i_timesFloat: OP_FF_F(x*y); break;
2561 StgFloat x = PopTaggedFloat();
2562 StgFloat y = PopTaggedFloat();
2563 PushTaggedFloat(x/y);
2566 case i_negateFloat: OP_F_F(-x); break;
2567 case i_floatToInt: OP_F_I(x); break;
2568 case i_intToFloat: OP_I_F(x); break;
2569 case i_expFloat: OP_F_F(exp(x)); break;
2570 case i_logFloat: OP_F_F(log(x)); break;
2571 case i_sqrtFloat: OP_F_F(sqrt(x)); break;
2572 case i_sinFloat: OP_F_F(sin(x)); break;
2573 case i_cosFloat: OP_F_F(cos(x)); break;
2574 case i_tanFloat: OP_F_F(tan(x)); break;
2575 case i_asinFloat: OP_F_F(asin(x)); break;
2576 case i_acosFloat: OP_F_F(acos(x)); break;
2577 case i_atanFloat: OP_F_F(atan(x)); break;
2578 case i_sinhFloat: OP_F_F(sinh(x)); break;
2579 case i_coshFloat: OP_F_F(cosh(x)); break;
2580 case i_tanhFloat: OP_F_F(tanh(x)); break;
2581 case i_powerFloat: OP_FF_F(pow(x,y)); break;
2583 case i_encodeFloatZ:
2585 StgPtr sig = PopPtr();
2586 StgInt exp = PopTaggedInt();
2588 B__encodeFloat(IntegerInsideByteArray(sig), exp)
2592 case i_decodeFloatZ:
2594 StgFloat f = PopTaggedFloat();
2595 StgPtr sig = CreateByteArrayToHoldInteger(size_fltmantissa());
2597 B__decodeFloat(IntegerInsideByteArray(sig), &exp, f);
2603 case i_isNaNFloat: OP_F_B(isFloatNaN(x)); break;
2604 case i_isInfiniteFloat: OP_F_B(isFloatInfinite(x)); break;
2605 case i_isNegativeZeroFloat: OP_F_B(isFloatNegativeZero(x)); break;
2606 case i_isDenormalizedFloat: OP_F_B(isFloatDenormalized(x)); break;
2607 case i_gtDouble: OP_DD_B(x>y); break;
2608 case i_geDouble: OP_DD_B(x>=y); break;
2609 case i_eqDouble: OP_DD_B(x==y); break;
2610 case i_neDouble: OP_DD_B(x!=y); break;
2611 case i_ltDouble: OP_DD_B(x<y); break;
2612 case i_leDouble: OP_DD_B(x<=y) break;
2613 case i_minDouble: OP__D(DBL_MIN); break;
2614 case i_maxDouble: OP__D(DBL_MAX); break;
2615 case i_radixDouble: OP__I(FLT_RADIX); break;
2616 case i_digitsDouble: OP__I(DBL_MANT_DIG); break;
2617 case i_minExpDouble: OP__I(DBL_MIN_EXP); break;
2618 case i_maxExpDouble: OP__I(DBL_MAX_EXP); break;
2619 case i_plusDouble: OP_DD_D(x+y); break;
2620 case i_minusDouble: OP_DD_D(x-y); break;
2621 case i_timesDouble: OP_DD_D(x*y); break;
2622 case i_divideDouble:
2624 StgDouble x = PopTaggedDouble();
2625 StgDouble y = PopTaggedDouble();
2626 PushTaggedDouble(x/y);
2629 case i_negateDouble: OP_D_D(-x); break;
2630 case i_doubleToInt: OP_D_I(x); break;
2631 case i_intToDouble: OP_I_D(x); break;
2632 case i_doubleToFloat: OP_D_F(x); break;
2633 case i_floatToDouble: OP_F_F(x); break;
2634 case i_expDouble: OP_D_D(exp(x)); break;
2635 case i_logDouble: OP_D_D(log(x)); break;
2636 case i_sqrtDouble: OP_D_D(sqrt(x)); break;
2637 case i_sinDouble: OP_D_D(sin(x)); break;
2638 case i_cosDouble: OP_D_D(cos(x)); break;
2639 case i_tanDouble: OP_D_D(tan(x)); break;
2640 case i_asinDouble: OP_D_D(asin(x)); break;
2641 case i_acosDouble: OP_D_D(acos(x)); break;
2642 case i_atanDouble: OP_D_D(atan(x)); break;
2643 case i_sinhDouble: OP_D_D(sinh(x)); break;
2644 case i_coshDouble: OP_D_D(cosh(x)); break;
2645 case i_tanhDouble: OP_D_D(tanh(x)); break;
2646 case i_powerDouble: OP_DD_D(pow(x,y)); break;
2648 case i_encodeDoubleZ:
2650 StgPtr sig = PopPtr();
2651 StgInt exp = PopTaggedInt();
2653 B__encodeDouble(IntegerInsideByteArray(sig), exp)
2657 case i_decodeDoubleZ:
2659 StgDouble d = PopTaggedDouble();
2660 StgPtr sig = CreateByteArrayToHoldInteger(size_dblmantissa());
2662 B__decodeDouble(IntegerInsideByteArray(sig), &exp, d);
2668 case i_isNaNDouble: OP_D_B(isDoubleNaN(x)); break;
2669 case i_isInfiniteDouble: OP_D_B(isDoubleInfinite(x)); break;
2670 case i_isNegativeZeroDouble: OP_D_B(isDoubleNegativeZero(x)); break;
2671 case i_isDenormalizedDouble: OP_D_B(isDoubleDenormalized(x)); break;
2672 case i_isIEEEDouble:
2674 PushTaggedBool(rtsTrue);
2678 barf("Unrecognised primop1");
2685 /* For normal cases, return NULL and leave *return2 unchanged.
2686 To return the address of the next thing to enter,
2687 return the address of it and leave *return2 unchanged.
2688 To return a StgThreadReturnCode to the scheduler,
2689 set *return2 to it and return a non-NULL value.
2690 To cause a context switch, set context_switch (its a global),
2691 and optionally set hugsBlock to your rational.
2693 static void* enterBCO_primop2 ( int primop2code,
2694 int* /*StgThreadReturnCode* */ return2,
2697 HugsBlock *hugsBlock )
2700 /* A small concession: we need to allow ccalls,
2701 even in combined mode.
2703 if (primop2code != i_ccall_ccall_IO &&
2704 primop2code != i_ccall_stdcall_IO)
2705 barf("enterBCO_primop2 in combined mode");
2708 switch (primop2code) {
2709 case i_raise: /* raise#{err} */
2711 StgClosure* err = PopCPtr();
2712 return (raiseAnError(err));
2717 StgClosure* init = PopCPtr();
2719 = stgCast(StgMutVar*,allocate(sizeofW(StgMutVar)));
2720 SET_HDR(mv,&MUT_VAR_info,CCCS);
2722 PushPtr(stgCast(StgPtr,mv));
2727 StgMutVar* mv = stgCast(StgMutVar*,PopPtr());
2733 StgMutVar* mv = stgCast(StgMutVar*,PopPtr());
2734 StgClosure* value = PopCPtr();
2740 nat n = PopTaggedInt(); /* or Word?? */
2741 StgClosure* init = PopCPtr();
2742 StgWord size = sizeofW(StgMutArrPtrs) + n;
2745 = stgCast(StgMutArrPtrs*,allocate(size));
2746 SET_HDR(arr,&MUT_ARR_PTRS_info,CCCS);
2748 for (i = 0; i < n; ++i) {
2749 arr->payload[i] = init;
2751 PushPtr(stgCast(StgPtr,arr));
2757 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
2758 nat i = PopTaggedInt(); /* or Word?? */
2759 StgWord n = arr->ptrs;
2761 return (raiseIndex("{index,read}Array"));
2763 PushCPtr(arr->payload[i]);
2768 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
2769 nat i = PopTaggedInt(); /* or Word? */
2770 StgClosure* v = PopCPtr();
2771 StgWord n = arr->ptrs;
2773 return (raiseIndex("{index,read}Array"));
2775 arr->payload[i] = v;
2779 case i_sizeMutableArray:
2781 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
2782 PushTaggedInt(arr->ptrs);
2785 case i_unsafeFreezeArray:
2787 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
2788 SET_INFO(arr,&MUT_ARR_PTRS_FROZEN_info);
2789 PushPtr(stgCast(StgPtr,arr));
2792 case i_unsafeFreezeByteArray:
2794 /* Delightfully simple :-) */
2798 case i_sameMutableArray:
2799 case i_sameMutableByteArray:
2801 StgPtr x = PopPtr();
2802 StgPtr y = PopPtr();
2803 PushTaggedBool(x==y);
2807 case i_newByteArray:
2809 nat n = PopTaggedInt(); /* or Word?? */
2810 StgInt words = (n+sizeof(W_)-1)/sizeof(W_);
2811 StgWord size = sizeofW(StgArrWords) + words;
2812 StgArrWords* arr = stgCast(StgArrWords*,allocate(size));
2813 SET_HDR(arr,&ARR_WORDS_info,CCCS);
2817 for (i = 0; i < n; ++i) {
2818 arr->payload[i] = 0xdeadbeef;
2821 PushPtr(stgCast(StgPtr,arr));
2825 /* Most of these generate alignment warnings on Sparcs and similar architectures.
2826 * These are harmless and are caused by the cast to C* in BYTE_ARR_CTS.
2828 case i_indexCharArray:
2829 OP_mI_ty(Char,"indexCharArray", indexCharArrayzh(r,x,i)); break;
2830 case i_readCharArray:
2831 OP_mI_ty(Char,"readCharArray", readCharArrayzh(r,x,i)); break;
2832 case i_writeCharArray:
2833 OP_mIty_(Char,"writeCharArray", writeCharArrayzh(x,i,z)); break;
2835 case i_indexIntArray:
2836 OP_mI_ty(Int,"indexIntArray", indexIntArrayzh(r,x,i)); break;
2837 case i_readIntArray:
2838 OP_mI_ty(Int,"readIntArray", readIntArrayzh(r,x,i)); break;
2839 case i_writeIntArray:
2840 OP_mIty_(Int,"writeIntArray", writeIntArrayzh(x,i,z)); break;
2842 case i_indexAddrArray:
2843 OP_mI_ty(Addr,"indexAddrArray", indexAddrArrayzh(r,x,i)); break;
2844 case i_readAddrArray:
2845 OP_mI_ty(Addr,"readAddrArray", readAddrArrayzh(r,x,i)); break;
2846 case i_writeAddrArray:
2847 OP_mIty_(Addr,"writeAddrArray", writeAddrArrayzh(x,i,z)); break;
2849 case i_indexFloatArray:
2850 OP_mI_ty(Float,"indexFloatArray", indexFloatArrayzh(r,x,i)); break;
2851 case i_readFloatArray:
2852 OP_mI_ty(Float,"readFloatArray", readFloatArrayzh(r,x,i)); break;
2853 case i_writeFloatArray:
2854 OP_mIty_(Float,"writeFloatArray", writeFloatArrayzh(x,i,z)); break;
2856 case i_indexDoubleArray:
2857 OP_mI_ty(Double,"indexDoubleArray", indexDoubleArrayzh(r,x,i)); break;
2858 case i_readDoubleArray:
2859 OP_mI_ty(Double,"readDoubleArray", readDoubleArrayzh(r,x,i)); break;
2860 case i_writeDoubleArray:
2861 OP_mIty_(Double,"writeDoubleArray", writeDoubleArrayzh(x,i,z)); break;
2864 #ifdef PROVIDE_STABLE
2865 case i_indexStableArray:
2866 OP_mI_ty(StablePtr,"indexStableArray", indexStablePtrArrayzh(r,x,i)); break;
2867 case i_readStableArray:
2868 OP_mI_ty(StablePtr,"readStableArray", readStablePtrArrayzh(r,x,i)); break;
2869 case i_writeStableArray:
2870 OP_mIty_(StablePtr,"writeStableArray", writeStablePtrArrayzh(x,i,z)); break;
2876 #ifdef PROVIDE_COERCE
2877 case i_unsafeCoerce:
2879 /* Another nullop */
2883 #ifdef PROVIDE_PTREQUALITY
2884 case i_reallyUnsafePtrEquality:
2885 { /* identical to i_sameRef */
2886 StgPtr x = PopPtr();
2887 StgPtr y = PopPtr();
2888 PushTaggedBool(x==y);
2892 #ifdef PROVIDE_FOREIGN
2893 /* ForeignObj# operations */
2894 case i_mkForeignObj:
2896 StgForeignObj *result
2897 = stgCast(StgForeignObj*,allocate(sizeofW(StgForeignObj)));
2898 SET_HDR(result,&FOREIGN_info,CCCS);
2899 result -> data = PopTaggedAddr();
2900 PushPtr(stgCast(StgPtr,result));
2903 #endif /* PROVIDE_FOREIGN */
2908 = stgCast(StgWeak*,allocate(sizeofW(StgWeak)));
2909 SET_HDR(w, &WEAK_info, CCCS);
2911 w->value = PopCPtr();
2912 w->finaliser = PopCPtr();
2913 w->link = weak_ptr_list;
2915 IF_DEBUG(weak, fprintf(stderr,"New weak pointer at %p\n",w));
2916 PushPtr(stgCast(StgPtr,w));
2921 StgWeak *w = stgCast(StgWeak*,PopPtr());
2922 if (w->header.info == &WEAK_info) {
2923 PushCPtr(w->value); /* last result */
2924 PushTaggedInt(1); /* first result */
2926 PushPtr(stgCast(StgPtr,w));
2927 /* ToDo: error thunk would be better */
2932 #endif /* PROVIDE_WEAK */
2934 case i_makeStablePtr:
2936 StgPtr p = PopPtr();
2937 StgStablePtr sp = getStablePtr ( p );
2938 PushTaggedStablePtr(sp);
2941 case i_deRefStablePtr:
2944 StgStablePtr sp = PopTaggedStablePtr();
2945 p = deRefStablePtr(sp);
2949 case i_freeStablePtr:
2951 StgStablePtr sp = PopTaggedStablePtr();
2956 case i_createAdjThunkARCH:
2958 StgStablePtr stableptr = PopTaggedStablePtr();
2959 StgAddr typestr = PopTaggedAddr();
2960 StgChar callconv = PopTaggedChar();
2961 StgAddr adj_thunk = createAdjThunk(stableptr,typestr,callconv);
2962 PushTaggedAddr(adj_thunk);
2968 StgInt n = prog_argc;
2974 StgInt n = PopTaggedInt();
2975 StgAddr a = (StgAddr)prog_argv[n];
2982 StgMVar *mvar = stgCast(StgMVar*,allocate(sizeofW(StgMVar)));
2983 SET_INFO(mvar,&EMPTY_MVAR_info);
2984 mvar->head = mvar->tail = (StgTSO *)&END_TSO_QUEUE_closure;
2985 mvar->value = stgCast(StgClosure*,&END_TSO_QUEUE_closure);
2986 PushPtr(stgCast(StgPtr,mvar));
2991 StgMVar *mvar = (StgMVar*)PopCPtr();
2992 if (GET_INFO(mvar) == &EMPTY_MVAR_info) {
2994 /* The MVar is empty. Attach ourselves to the TSO's
2997 if (mvar->head == (StgTSO *)&END_TSO_QUEUE_closure) {
2998 mvar->head = cap->rCurrentTSO;
3000 mvar->tail->link = cap->rCurrentTSO;
3002 cap->rCurrentTSO->link = (StgTSO *)&END_TSO_QUEUE_closure;
3003 cap->rCurrentTSO->why_blocked = BlockedOnMVar;
3004 cap->rCurrentTSO->block_info.closure = (StgClosure *)mvar;
3005 mvar->tail = cap->rCurrentTSO;
3007 /* At this point, the top-of-stack holds the MVar,
3008 and underneath is the world token (). So the
3009 stack is in the same state as when primTakeMVar
3010 was entered (primTakeMVar is handwritten bytecode).
3011 Push obj, which is this BCO, and return to the
3012 scheduler. When the MVar is filled, the scheduler
3013 will re-enter primTakeMVar, with the args still on
3014 the top of the stack.
3016 PushCPtr((StgClosure*)(*bco));
3017 *return2 = ThreadBlocked;
3018 return (void*)(1+(char*)(NULL));
3021 PushCPtr(mvar->value);
3022 mvar->value = (StgClosure *)&END_TSO_QUEUE_closure;
3023 SET_INFO(mvar,&EMPTY_MVAR_info);
3029 StgMVar* mvar = stgCast(StgMVar*,PopPtr());
3030 StgClosure* value = PopCPtr();
3031 if (GET_INFO(mvar) == &FULL_MVAR_info) {
3032 return (makeErrorCall("putMVar {full MVar}"));
3034 /* wake up the first thread on the
3035 * queue, it will continue with the
3036 * takeMVar operation and mark the
3039 mvar->value = value;
3041 if (mvar->head != (StgTSO *)&END_TSO_QUEUE_closure) {
3042 ASSERT(mvar->head->why_blocked == BlockedOnMVar);
3043 mvar->head = unblockOne(mvar->head);
3044 if (mvar->head == (StgTSO *)&END_TSO_QUEUE_closure) {
3045 mvar->tail = (StgTSO *)&END_TSO_QUEUE_closure;
3049 /* unlocks the MVar in the SMP case */
3050 SET_INFO(mvar,&FULL_MVAR_info);
3052 /* yield for better communication performance */
3058 { /* identical to i_sameRef */
3059 StgMVar* x = (StgMVar*)PopPtr();
3060 StgMVar* y = (StgMVar*)PopPtr();
3061 PushTaggedBool(x==y);
3064 #ifdef PROVIDE_CONCURRENT
3067 StgClosure* closure;
3070 closure = PopCPtr();
3071 tso = createGenThread (RtsFlags.GcFlags.initialStkSize,closure);
3073 scheduleThread(tso);
3075 /* Later: Change to use tso as the ThreadId */
3076 PushTaggedWord(tid);
3082 StgWord n = PopTaggedWord();
3086 // Map from ThreadId to Thread Structure */
3087 for (t = all_threads; t != END_TSO_QUEUE; t = t->global_link) {
3096 while (tso->what_next == ThreadRelocated) {
3101 if (tso == cap->rCurrentTSO) { /* suicide */
3102 *return2 = ThreadFinished;
3103 return (void*)(1+(NULL));
3107 case i_raiseInThread:
3108 ASSERT(0); /* not (yet) supported */
3111 StgInt n = PopTaggedInt();
3113 hugsBlock->reason = BlockedOnDelay;
3114 hugsBlock->delay = n;
3119 StgInt n = PopTaggedInt();
3121 hugsBlock->reason = BlockedOnRead;
3122 hugsBlock->delay = n;
3127 StgInt n = PopTaggedInt();
3129 hugsBlock->reason = BlockedOnWrite;
3130 hugsBlock->delay = n;
3135 /* The definition of yield include an enter right after
3136 * the primYield, at which time context_switch is tested.
3143 StgWord tid = cap->rCurrentTSO->id;
3144 PushTaggedWord(tid);
3147 case i_cmpThreadIds:
3149 StgWord tid1 = PopTaggedWord();
3150 StgWord tid2 = PopTaggedWord();
3151 if (tid1 < tid2) PushTaggedInt(-1);
3152 else if (tid1 > tid2) PushTaggedInt(1);
3153 else PushTaggedInt(0);
3156 #endif /* PROVIDE_CONCURRENT */
3158 case i_ccall_ccall_Id:
3159 case i_ccall_ccall_IO:
3160 case i_ccall_stdcall_Id:
3161 case i_ccall_stdcall_IO:
3164 CFunDescriptor* descriptor;
3165 void (*funPtr)(void);
3167 descriptor = PopTaggedAddr();
3168 funPtr = PopTaggedAddr();
3169 cc = (primop2code == i_ccall_stdcall_Id ||
3170 primop2code == i_ccall_stdcall_IO)
3172 r = ccall(descriptor,funPtr,bco,cc,cap);
3175 return makeErrorCall(
3176 "unhandled type or too many args/results in ccall");
3178 barf("ccall not configured correctly for this platform");
3179 barf("unknown return code from ccall");
3182 barf("Unrecognised primop2");
3188 /* -----------------------------------------------------------------------------
3189 * ccall support code:
3190 * marshall moves args from C stack to Haskell stack
3191 * unmarshall moves args from Haskell stack to C stack
3192 * argSize calculates how much gSpace you need on the C stack
3193 * ---------------------------------------------------------------------------*/
3195 /* Pop arguments off the C stack and Push them onto the Hugs stack.
3196 * Used when preparing for C calling Haskell or in regSponse to
3197 * Haskell calling C.
3199 nat marshall(char arg_ty, void* arg)
3203 PushTaggedInt(*((int*)arg));
3204 return ARG_SIZE(INT_TAG);
3207 PushTaggedInteger(*((mpz_ptr*)arg));
3208 return ARG_SIZE(INTEGER_TAG);
3211 PushTaggedWord(*((unsigned int*)arg));
3212 return ARG_SIZE(WORD_TAG);
3214 PushTaggedChar(*((char*)arg));
3215 return ARG_SIZE(CHAR_TAG);
3217 PushTaggedFloat(*((float*)arg));
3218 return ARG_SIZE(FLOAT_TAG);
3220 PushTaggedDouble(*((double*)arg));
3221 return ARG_SIZE(DOUBLE_TAG);
3223 PushTaggedAddr(*((void**)arg));
3224 return ARG_SIZE(ADDR_TAG);
3226 PushTaggedStablePtr(*((StgStablePtr*)arg));
3227 return ARG_SIZE(STABLE_TAG);
3228 #ifdef PROVIDE_FOREIGN
3230 /* Not allowed in this direction - you have to
3231 * call makeForeignPtr explicitly
3233 barf("marshall: ForeignPtr#\n");
3238 /* Not allowed in this direction */
3239 barf("marshall: [Mutable]ByteArray#\n");
3242 barf("marshall: unrecognised arg type %d\n",arg_ty);
3247 /* Pop arguments off the Hugs stack and Push them onto the C stack.
3248 * Used when preparing for Haskell calling C or in regSponse to
3249 * C calling Haskell.
3251 nat unmarshall(char res_ty, void* res)
3255 *((int*)res) = PopTaggedInt();
3256 return ARG_SIZE(INT_TAG);
3259 *((mpz_ptr*)res) = PopTaggedInteger();
3260 return ARG_SIZE(INTEGER_TAG);
3263 *((unsigned int*)res) = PopTaggedWord();
3264 return ARG_SIZE(WORD_TAG);
3266 *((int*)res) = PopTaggedChar();
3267 return ARG_SIZE(CHAR_TAG);
3269 *((float*)res) = PopTaggedFloat();
3270 return ARG_SIZE(FLOAT_TAG);
3272 *((double*)res) = PopTaggedDouble();
3273 return ARG_SIZE(DOUBLE_TAG);
3275 *((void**)res) = PopTaggedAddr();
3276 return ARG_SIZE(ADDR_TAG);
3278 *((StgStablePtr*)res) = PopTaggedStablePtr();
3279 return ARG_SIZE(STABLE_TAG);
3280 #ifdef PROVIDE_FOREIGN
3283 StgForeignObj *result = stgCast(StgForeignObj*,PopPtr());
3284 *((void**)res) = result->data;
3285 return sizeofW(StgPtr);
3291 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
3292 *((void**)res) = stgCast(void*,&(arr->payload));
3293 return sizeofW(StgPtr);
3296 barf("unmarshall: unrecognised result type %d\n",res_ty);
3300 nat argSize( const char* ks )
3303 for( ; *ks != '\0'; ++ks) {
3306 sz += sizeof(StgWord) * ARG_SIZE(INT_TAG);
3310 sz += sizeof(StgWord) * ARG_SIZE(INTEGER_TAG);
3314 sz += sizeof(StgWord) * ARG_SIZE(WORD_TAG);
3317 sz += sizeof(StgWord) * ARG_SIZE(CHAR_TAG);
3320 sz += sizeof(StgWord) * ARG_SIZE(FLOAT_TAG);
3323 sz += sizeof(StgWord) * ARG_SIZE(DOUBLE_TAG);
3326 sz += sizeof(StgWord) * ARG_SIZE(ADDR_TAG);
3329 sz += sizeof(StgWord) * ARG_SIZE(STABLE_TAG);
3331 #ifdef PROVIDE_FOREIGN
3336 sz += sizeof(StgPtr);
3339 barf("argSize: unrecognised result type %d\n",*ks);
3347 /* -----------------------------------------------------------------------------
3348 * encode/decode Float/Double code for standalone Hugs
3349 * Code based on the HBC code (lib/fltcode.c) and more recently GHC
3350 * (ghc/rts/StgPrimFloat.c)
3351 * ---------------------------------------------------------------------------*/
3353 #if IEEE_FLOATING_POINT
3354 #define MY_DMINEXP ((DBL_MIN_EXP) - (DBL_MANT_DIG) - 1)
3355 /* DMINEXP is defined in values.h on Linux (for example) */
3356 #define DHIGHBIT 0x00100000
3357 #define DMSBIT 0x80000000
3359 #define MY_FMINEXP ((FLT_MIN_EXP) - (FLT_MANT_DIG) - 1)
3360 #define FHIGHBIT 0x00800000
3361 #define FMSBIT 0x80000000
3363 #error The following code doesnt work in a non-IEEE FP environment
3366 #ifdef WORDS_BIGENDIAN
3375 StgDouble B__encodeDouble (B* s, I_ e) /* result = s * 2^e */
3380 /* Convert a B to a double; knows a lot about internal rep! */
3381 for(r = 0.0, i = s->used-1; i >= 0; i--)
3382 r = (r * B_BASE_FLT) + s->stuff[i];
3384 /* Now raise to the exponent */
3385 if ( r != 0.0 ) /* Lennart suggests this avoids a bug in MIPS's ldexp */
3388 /* handle the sign */
3389 if (s->sign < 0) r = -r;
3396 #if ! FLOATS_AS_DOUBLES
3397 StgFloat B__encodeFloat (B* s, I_ e) /* result = s * 2^e */
3402 /* Convert a B to a float; knows a lot about internal rep! */
3403 for(r = 0.0, i = s->used-1; i >= 0; i--)
3404 r = (r * B_BASE_FLT) + s->stuff[i];
3406 /* Now raise to the exponent */
3407 if ( r != 0.0 ) /* Lennart suggests this avoids a bug in MIPS's ldexp */
3410 /* handle the sign */
3411 if (s->sign < 0) r = -r;
3415 #endif /* FLOATS_AS_DOUBLES */
3419 /* This only supports IEEE floating point */
3420 void B__decodeDouble (B* man, I_* exp, StgDouble dbl)
3422 /* Do some bit fiddling on IEEE */
3423 nat low, high; /* assuming 32 bit ints */
3425 union { double d; int i[2]; } u; /* assuming 32 bit ints, 64 bit double */
3427 u.d = dbl; /* grab chunks of the double */
3431 ASSERT(B_BASE == 256);
3433 /* Assume that the supplied B is the right size */
3436 if (low == 0 && (high & ~DMSBIT) == 0) {
3437 man->sign = man->used = 0;
3442 iexp = ((high >> 20) & 0x7ff) + MY_DMINEXP;
3446 if (iexp != MY_DMINEXP) /* don't add hidden bit to denorms */
3450 /* A denorm, normalize the mantissa */
3451 while (! (high & DHIGHBIT)) {
3461 man->stuff[7] = (((W_)high) >> 24) & 0xff;
3462 man->stuff[6] = (((W_)high) >> 16) & 0xff;
3463 man->stuff[5] = (((W_)high) >> 8) & 0xff;
3464 man->stuff[4] = (((W_)high) ) & 0xff;
3466 man->stuff[3] = (((W_)low) >> 24) & 0xff;
3467 man->stuff[2] = (((W_)low) >> 16) & 0xff;
3468 man->stuff[1] = (((W_)low) >> 8) & 0xff;
3469 man->stuff[0] = (((W_)low) ) & 0xff;
3471 if (sign < 0) man->sign = -1;
3473 do_renormalise(man);
3477 #if ! FLOATS_AS_DOUBLES
3478 void B__decodeFloat (B* man, I_* exp, StgFloat flt)
3480 /* Do some bit fiddling on IEEE */
3481 int high, sign; /* assuming 32 bit ints */
3482 union { float f; int i; } u; /* assuming 32 bit float and int */
3484 u.f = flt; /* grab the float */
3487 ASSERT(B_BASE == 256);
3489 /* Assume that the supplied B is the right size */
3492 if ((high & ~FMSBIT) == 0) {
3493 man->sign = man->used = 0;
3498 *exp = ((high >> 23) & 0xff) + MY_FMINEXP;
3502 if (*exp != MY_FMINEXP) /* don't add hidden bit to denorms */
3506 /* A denorm, normalize the mantissa */
3507 while (! (high & FHIGHBIT)) {
3512 man->stuff[3] = (((W_)high) >> 24) & 0xff;
3513 man->stuff[2] = (((W_)high) >> 16) & 0xff;
3514 man->stuff[1] = (((W_)high) >> 8) & 0xff;
3515 man->stuff[0] = (((W_)high) ) & 0xff;
3517 if (sign < 0) man->sign = -1;
3519 do_renormalise(man);
3522 #endif /* FLOATS_AS_DOUBLES */
3523 #endif /* INTERPRETER */