2 /* -----------------------------------------------------------------------------
5 * Copyright (c) 1994-1998.
7 * $RCSfile: Evaluator.c,v $
9 * $Date: 2000/03/20 04:26:24 $
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} */
27 #include "Evaluator.h"
28 #include "sainteger.h"
32 #include "Disassembler.h"
37 #include <math.h> /* These are for primops */
38 #include <limits.h> /* These are for primops */
39 #include <float.h> /* These are for primops */
41 #include <ieee754.h> /* These are for primops */
45 /* Allegedly useful macro, taken from ClosureMacros.h */
46 #define payloadWord( c, i ) (*stgCast(StgWord*, ((c)->payload+(i))))
47 #define payloadPtr( c, i ) (*stgCast(StgPtr*, ((c)->payload+(i))))
49 /* An incredibly useful abbreviation.
50 * Interestingly, there are some uses of END_TSO_QUEUE_closure that
51 * can't use it because they use the closure at type StgClosure* or
52 * even StgPtr*. I suspect they should be changed. -- ADR
54 #define EndTSOQueue stgCast(StgTSO*,(void*)&END_TSO_QUEUE_closure)
56 /* These macros are rather delicate - read a good ANSI C book carefully
60 #define mycat(x,y) x##y
61 #define mycat2(x,y) mycat(x,y)
62 #define mycat3(x,y,z) mycat2(x,mycat2(y,z))
64 #if defined(__GNUC__) && !defined(DEBUG)
65 #define USE_GCC_LABELS 1
67 #define USE_GCC_LABELS 0
70 /* Make it possible for the evaluator to get hold of bytecode
71 for a given function by name. Useful but a hack. Sigh.
73 extern void* getHugs_AsmObject_for ( char* s );
74 extern int /*Bool*/ combined;
76 /* --------------------------------------------------------------------------
77 * Crude profiling stuff (mainly to assess effect of optimiser)
78 * ------------------------------------------------------------------------*/
80 #ifdef CRUDE_PROFILING
89 struct { int /*StgVar*/ who;
97 CPRecord cpTab[M_CPTAB];
104 for (i = 0; i < M_CPTAB; i++)
105 cpTab[i].who = CP_NIL;
110 void cp_enter ( StgBCO* b )
114 int /*StgVar*/ v = b->stgexpr;
115 if ((void*)v == NULL) return;
124 h = (-v) % M_CPTAB; else
127 assert (h >= 0 && h < M_CPTAB);
128 while (cpTab[h].who != v && cpTab[h].who != CP_NIL) {
129 h++; if (h == M_CPTAB) h = 0;
132 if (cpTab[cpCurr].who == CP_NIL) {
133 cpTab[cpCurr].who = v;
134 if (!is_ret_cont) cpTab[cpCurr].enters = 1;
135 cpTab[cpCurr].bytes = cpTab[cpCurr].insns = 0;
137 if (cpInUse * 2 > M_CPTAB) {
138 fprintf(stderr, "\nCRUDE_PROFILING hash table is too full\n" );
142 if (!is_ret_cont) cpTab[cpCurr].enters++;
148 void cp_bill_words ( int nw )
150 if (cpCurr == CP_NIL) return;
151 cpTab[cpCurr].bytes += sizeof(StgWord)*nw;
155 void cp_bill_insns ( int ni )
157 if (cpCurr == CP_NIL) return;
158 cpTab[cpCurr].insns += ni;
162 static double percent ( double a, double b )
164 return (100.0 * a) / b;
168 void cp_show ( void )
170 int i, j, max, maxN, totE, totB, totI, cumE, cumB, cumI;
173 if (cpInUse == -1) return;
175 fflush(stdout);fflush(stderr);
178 totE = totB = totI = 0;
179 for (i = 0; i < M_CPTAB; i++) {
180 cpTab[i].twho = cpTab[i].who;
181 if (cpTab[i].who != CP_NIL) {
182 totE += cpTab[i].enters;
183 totB += cpTab[i].bytes;
184 totI += cpTab[i].insns;
189 "%6d (%7.3f M) enters, "
190 "%6d (%7.3f M) insns, "
191 "%6d (%7.3f M) bytes\n\n",
192 totE, totE/1000000.0, totI, totI/1000000.0, totB, totB/1000000.0 );
194 cumE = cumB = cumI = 0;
195 for (j = 0; j < 32; j++) {
198 for (i = 0; i < M_CPTAB; i++)
199 if (cpTab[i].who != CP_NIL &&
200 cpTab[i].enters > maxN) {
201 maxN = cpTab[i].enters;
204 if (max == -1) break;
206 cumE += cpTab[max].enters;
207 cumB += cpTab[max].bytes;
208 cumI += cpTab[max].insns;
210 strcpy(nm, maybeName(cpTab[max].who));
211 if (strcmp(nm, "(unknown)")==0)
212 sprintf ( nm, "id%d", -cpTab[max].who);
214 printf ( "%20s %7d es (%4.1f%%, %4.1f%% c) "
215 "%7d bs (%4.1f%%, %4.1f%% c) "
216 "%7d is (%4.1f%%, %4.1f%% c)\n",
218 cpTab[max].enters, percent(cpTab[max].enters,totE), percent(cumE,totE),
219 cpTab[max].bytes, percent(cpTab[max].bytes,totB), percent(cumB,totB),
220 cpTab[max].insns, percent(cpTab[max].insns,totI), percent(cumI,totI)
223 cpTab[max].twho = cpTab[max].who;
224 cpTab[max].who = CP_NIL;
227 for (i = 0; i < M_CPTAB; i++)
228 cpTab[i].who = cpTab[i].twho;
236 /* --------------------------------------------------------------------------
237 * Hugs Hooks - a bit of a hack
238 * ------------------------------------------------------------------------*/
240 void setRtsFlags( int x );
241 void setRtsFlags( int x )
243 unsigned int w = 0x12345678;
244 unsigned char* pw = (unsigned char *)&w;
247 *(int*)(&(RtsFlags.DebugFlags)) = x;
252 w2 |= (w1 && 0xFF); w2 <<= 8; w1 >>= 8;
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 *(int*)(&(RtsFlags.DebugFlags)) = (int)w2;
262 StgTSOBlockReason reason;
267 /* --------------------------------------------------------------------------
268 * Entering-objects and bytecode interpreter part of evaluator
269 * ------------------------------------------------------------------------*/
271 /* The primop (and all other) parts of this evaluator operate upon the
272 machine state which lives in MainRegTable. enter is different:
273 to make its closure- and bytecode-interpreting loops go fast, some of that
274 state is pulled out into local vars (viz, registers, if we are lucky).
275 That means that we need to save(load) the local state at every exit(reentry)
276 into enter. That is, around every procedure call it makes. Blargh!
277 If you modify this code, __be warned__ it will fail in mysterious ways if
278 you fail to preserve this property.
280 Currently the pulled-out state is Sp in xSp, Su in xSu and SpLim in xSpLim.
281 The SSS macros saves the state back in MainRegTable, and LLL loads it from
282 MainRegTable. RETURN(v) does SSS and then returns v; all exits should
283 be via RETURN and not plain return.
285 Since xSp, xSu and xSpLim are local vars in enter, they are not visible
286 in procedures called from enter. To fix this, either (1) turn the
287 procedures into macros, so they get copied inline, or (2) bracket
288 the procedure call with SSS and LLL so that the local and global
289 machine states are synchronised for the duration of the call.
293 /* Forward decls ... */
294 static void* enterBCO_primop1 ( int );
295 static void* enterBCO_primop2 ( int , int* /*StgThreadReturnCode* */,
296 StgBCO**, Capability*, HugsBlock * );
297 static inline void PopUpdateFrame ( StgClosure* obj );
298 static inline void PopCatchFrame ( void );
299 static inline void PopSeqFrame ( void );
300 static inline void PopStopFrame( StgClosure* obj );
301 static inline void PushTaggedRealWorld( void );
302 /* static inline void PushTaggedInteger ( mpz_ptr ); */
303 static inline StgPtr grabHpUpd( nat size );
304 static inline StgPtr grabHpNonUpd( nat size );
305 static StgClosure* raiseAnError ( StgClosure* exception );
307 static int enterCountI = 0;
309 StgDouble B__encodeDouble (B* s, I_ e);
310 void B__decodeDouble (B* man, I_* exp, StgDouble dbl);
311 #if ! FLOATS_AS_DOUBLES
312 StgFloat B__encodeFloat (B* s, I_ e);
313 void B__decodeFloat (B* man, I_* exp, StgFloat flt);
314 StgPtr CreateByteArrayToHoldInteger ( int );
315 B* IntegerInsideByteArray ( StgPtr );
316 void SloppifyIntegerEnd ( StgPtr );
322 #define gSp MainRegTable.rSp
323 #define gSu MainRegTable.rSu
324 #define gSpLim MainRegTable.rSpLim
327 /* Macros to save/load local state. */
329 #define SSS { tSp=gSp = xSp; tSu=gSu = xSu; tSpLim=gSpLim = xSpLim; }
330 #define LLL { tSp=xSp = gSp; tSu=xSu = gSu; tSpLim=xSpLim = gSpLim; }
332 #define SSS { gSp = xSp; gSu = xSu; gSpLim = xSpLim; }
333 #define LLL { xSp = gSp; xSu = gSu; xSpLim = gSpLim; }
336 #define RETURN(vvv) { \
337 StgThreadReturnCode retVal=(vvv); \
339 cap->rCurrentTSO->sp = gSp; \
340 cap->rCurrentTSO->su = gSu; \
341 cap->rCurrentTSO->splim = gSpLim; \
346 /* Macros to operate directly on the pulled-out machine state.
347 These mirror some of the small procedures used in the primop code
348 below, except you have to be careful about side effects,
349 ie xPushPtr(xStackPtr(n)) won't work! It certainly isn't the
350 same as PushPtr(StackPtr(n)). Also note that (1) some of
351 the macros, in particular xPopTagged*, do not make the tag
352 sanity checks that their non-x cousins do, and (2) some of
353 the macros depend critically on the semantics of C comma
354 expressions to work properly.
356 #define xPushPtr(ppp) { xSp--; *xSp=(StgWord)(ppp); }
357 #define xPopPtr() ((StgPtr)(*xSp++))
359 #define xPushCPtr(ppp) { xSp--; *xSp=(StgWord)(ppp); }
360 #define xPopCPtr() ((StgClosure*)(*xSp++))
362 #define xPushWord(ppp) { xSp--; *xSp=(StgWord)(ppp); }
363 #define xPopWord() ((StgWord)(*xSp++))
365 #define xStackPtr(nnn) ((StgPtr)(*(xSp+(nnn))))
366 #define xStackWord(nnn) ((StgWord)(*(xSp+(nnn))))
367 #define xSetStackWord(iii,www) xSp[iii]=(StgWord)(www)
369 #define xPushTag(ttt) { xSp--; *xSp=(StgWord)(ttt); }
370 #define xPopTag(ttt) { StackTag t = (StackTag)(*xSp++); \
373 #define xPushTaggedInt(xxx) { xSp -= sizeofW(StgInt); \
374 *xSp = (xxx); xPushTag(INT_TAG); }
375 #define xTaggedStackInt(iii) ((StgInt)(*(xSp+1+(iii))))
376 #define xPopTaggedInt() ((xSp++,xSp+=sizeofW(StgInt), \
377 (StgInt)(*(xSp-sizeofW(StgInt)))))
379 #define xPushTaggedWord(xxx) { xSp -= sizeofW(StgWord); \
380 *xSp = (xxx); xPushTag(WORD_TAG); }
381 #define xTaggedStackWord(iii) ((StgWord)(*(xSp+1+(iii))))
382 #define xPopTaggedWord() ((xSp++,xSp+=sizeofW(StgWord), \
383 (StgWord)(*(xSp-sizeofW(StgWord)))))
385 #define xPushTaggedAddr(xxx) { xSp -= sizeofW(StgAddr); \
386 *xSp = (StgWord)(xxx); xPushTag(ADDR_TAG); }
387 #define xTaggedStackAddr(iii) ((StgAddr)(*(xSp+1+(iii))))
388 #define xPopTaggedAddr() ((xSp++,xSp+=sizeofW(StgAddr), \
389 (StgAddr)(*(xSp-sizeofW(StgAddr)))))
391 #define xPushTaggedStable(xxx) { xSp -= sizeofW(StgStablePtr); \
392 *xSp = (StgWord)(xxx); xPushTag(STABLE_TAG); }
393 #define xTaggedStackStable(iii) ((StgStablePtr)(*(xSp+1+(iii))))
394 #define xPopTaggedStable() ((xSp++,xSp+=sizeofW(StgStablePtr), \
395 (StgStablePtr)(*(xSp-sizeofW(StgStablePtr)))))
397 #define xPushTaggedChar(xxx) { xSp -= sizeofW(StgChar); \
398 *xSp = (StgWord)(xxx); xPushTag(CHAR_TAG); }
399 #define xTaggedStackChar(iii) ((StgChar)(*(xSp+1+(iii))))
400 #define xPopTaggedChar() ((xSp++,xSp+=sizeofW(StgChar), \
401 (StgChar)(*(xSp-sizeofW(StgChar)))))
403 #define xPushTaggedFloat(xxx) { xSp -= sizeofW(StgFloat); \
404 ASSIGN_FLT(xSp,xxx); xPushTag(FLOAT_TAG); }
405 #define xTaggedStackFloat(iii) PK_FLT(xSp+1+(iii))
406 #define xPopTaggedFloat() ((xSp++,xSp+=sizeofW(StgFloat), \
407 PK_FLT(xSp-sizeofW(StgFloat))))
409 #define xPushTaggedDouble(xxx) { xSp -= sizeofW(StgDouble); \
410 ASSIGN_DBL(xSp,xxx); xPushTag(DOUBLE_TAG); }
411 #define xTaggedStackDouble(iii) PK_DBL(xSp+1+(iii))
412 #define xPopTaggedDouble() ((xSp++,xSp+=sizeofW(StgDouble), \
413 PK_DBL(xSp-sizeofW(StgDouble))))
416 #define xPushUpdateFrame(target, xSp_offset) \
418 StgUpdateFrame *__frame; \
419 __frame = (StgUpdateFrame *)(xSp + (xSp_offset)) - 1; \
420 SET_INFO(__frame, (StgInfoTable *)&Upd_frame_info); \
421 __frame->link = xSu; \
422 __frame->updatee = (StgClosure *)(target); \
426 #define xPopUpdateFrame(ooo) \
428 /* NB: doesn't assume that Sp == Su */ \
429 IF_DEBUG(evaluator, \
430 fprintf(stderr, "Updating "); \
431 printPtr(stgCast(StgPtr,xSu->updatee)); \
432 fprintf(stderr, " with "); \
434 fprintf(stderr,"xSp = %p\txSu = %p\n\n", xSp, xSu); \
436 UPD_IND(xSu->updatee,ooo); \
437 xSp = stgCast(StgStackPtr,xSu) + sizeofW(StgUpdateFrame); \
443 /* Instruction stream macros */
444 #define BCO_INSTR_8 *bciPtr++
445 #define BCO_INSTR_16 ((bciPtr += 2, (*(bciPtr-2) << 8) + *(bciPtr-1)))
446 #define PC (bciPtr - &(bcoInstr(bco,0)))
449 /* State on entry to enter():
450 * - current thread is in cap->rCurrentTSO;
451 * - allocation area is in cap->rCurrentNursery & cap->rNursery
454 StgThreadReturnCode enter( Capability* cap, StgClosure* obj0 )
456 /* use of register here is primarily to make it clear to compilers
457 that these entities are non-aliasable.
459 register StgPtr xSp; /* local state -- stack pointer */
460 register StgUpdateFrame* xSu; /* local state -- frame pointer */
461 register StgPtr xSpLim; /* local state -- stack lim pointer */
462 register StgClosure* obj; /* object currently under evaluation */
463 char eCount; /* enter counter, for context switching */
466 HugsBlock hugsBlock = { NotBlocked, 0 };
470 StgPtr tSp; StgUpdateFrame* tSu; StgPtr tSpLim;
473 gSp = cap->rCurrentTSO->sp;
474 gSu = cap->rCurrentTSO->su;
475 gSpLim = cap->rCurrentTSO->splim;
478 /* use the t values to check that Su/Sp/SpLim do not change unexpectedly */
479 tSp = gSp; tSu = gSu; tSpLim = gSpLim;
485 /* Load the local state from global state, and Party On, Dudes! */
486 /* From here onwards, we operate with the local state and
487 save/reload it as necessary.
496 assert(gSpLim == tSpLim);
500 ASSERT(xSpLim <= xSp && xSp <= stgCast(StgPtr,xSu));
502 "\n---------------------------------------------------------------\n");
503 fprintf(stderr,"(%d) Entering: ",enterCountI); printObj(obj);
504 fprintf(stderr,"xSp = %p\txSu = %p\n", xSp, xSu);
505 fprintf(stderr, "\n" );
506 printStack(xSp,cap->rCurrentTSO->stack+cap->rCurrentTSO->stack_size,xSu);
507 fprintf(stderr, "\n\n");
514 ((++eCount) & 0x0F) == 0
519 if (context_switch) {
520 switch(hugsBlock.reason) {
522 xPushCPtr(obj); /* code to restart with */
523 RETURN(ThreadYielding);
525 case BlockedOnDelay: /* fall through */
526 case BlockedOnRead: /* fall through */
527 case BlockedOnWrite: {
528 ASSERT(cap->rCurrentTSO->why_blocked == NotBlocked);
529 cap->rCurrentTSO->why_blocked = BlockedOnDelay;
530 ACQUIRE_LOCK(&sched_mutex);
532 cap->rCurrentTSO->block_info.delay
533 = hugsBlock.delay + ticks_since_select;
534 APPEND_TO_BLOCKED_QUEUE(cap->rCurrentTSO);
536 RELEASE_LOCK(&sched_mutex);
538 xPushCPtr(obj); /* code to restart with */
539 RETURN(ThreadBlocked);
542 barf("Unknown context switch reasoning");
547 switch ( get_itbl(obj)->type ) {
549 barf("Invalid object %p",obj);
553 /* ---------------------------------------------------- */
554 /* Start of the bytecode evaluator */
555 /* ---------------------------------------------------- */
558 # define Ins(x) &&l##x
559 static void *labs[] = { INSTRLIST };
561 # define LoopTopLabel
562 # define Case(x) l##x
563 # define Continue goto *labs[BCO_INSTR_8]
564 # define Dispatch Continue;
567 # define LoopTopLabel insnloop:
568 # define Case(x) case x
569 # define Continue goto insnloop
570 # define Dispatch switch (BCO_INSTR_8) {
571 # define EndDispatch }
574 register StgWord8* bciPtr; /* instruction pointer */
575 register StgBCO* bco = (StgBCO*)obj;
578 /* Don't need to SSS ... LLL around doYouWantToGC */
579 wantToGC = doYouWantToGC();
581 xPushCPtr((StgClosure*)bco); /* code to restart with */
582 RETURN(HeapOverflow);
590 bciPtr = &(bcoInstr(bco,0));
594 ASSERT((StgWord)(PC) < bco->n_instrs);
596 fprintf(stderr,"Sp = %p\tSu = %p\tpc = %d\t", xSp, xSu, PC);
600 fprintf(stderr,"\n");
601 for (i = 8; i >= 0; i--)
602 fprintf(stderr, "%d %p\n", i, (StgPtr)(*(gSp+i)));
604 fprintf(stderr,"\n");
609 SSS; cp_bill_insns(1); LLL;
614 Case(i_INTERNAL_ERROR):
615 barf("INTERNAL_ERROR at %p:%d",bco,PC-1);
617 barf("PANIC at %p:%d",bco,PC-1);
621 if (xSp - n < xSpLim) {
622 xPushCPtr((StgClosure*)bco); /* code to restart with */
623 RETURN(StackOverflow);
627 Case(i_STK_CHECK_big):
629 int n = BCO_INSTR_16;
630 if (xSp - n < xSpLim) {
631 xPushCPtr((StgClosure*)bco); /* code to restart with */
632 RETURN(StackOverflow);
639 if ((StgPtr*)(xSp + n) > (StgPtr*)xSu) {
640 StgWord words = (P_)xSu - xSp;
642 /* first build a PAP */
643 ASSERT((P_)xSu >= xSp); /* was (words >= 0) but that's always true */
644 if (words == 0) { /* optimisation */
645 /* Skip building the PAP and update with an indirection. */
648 /* In the evaluator, we avoid the need to do
649 * a heap check here by including the size of
650 * the PAP in the heap check we performed
651 * when we entered the BCO.
655 SSS; pap = (StgPAP*)grabHpNonUpd(PAP_sizeW(words)); LLL;
656 SET_HDR(pap,&PAP_info,CC_pap);
659 for (i = 0; i < (I_)words; ++i) {
660 payloadWord(pap,i) = xSp[i];
663 obj = stgCast(StgClosure*,pap);
666 /* now deal with "update frame" */
667 /* as an optimisation, we process all on top of stack */
668 /* instead of just the top one */
669 ASSERT(xSp==(P_)xSu);
671 switch (get_itbl(xSu)->type) {
673 /* Hit a catch frame during an arg satisfaction check,
674 * so the thing returning (1) has not thrown an
675 * exception, and (2) is of functional type. Just
676 * zap the catch frame and carry on down the stack
677 * (looking for more arguments, basically).
679 SSS; PopCatchFrame(); LLL;
682 xPopUpdateFrame(obj);
685 SSS; PopStopFrame(obj); LLL;
686 RETURN(ThreadFinished);
688 SSS; PopSeqFrame(); LLL;
689 ASSERT(xSp != (P_)xSu);
690 /* Hit a SEQ frame during an arg satisfaction check.
691 * So now return to bco_info which is under the
692 * SEQ frame. The following code is copied from a
693 * case RET_BCO further down. (The reason why we're
694 * here is that something of functional type has
695 * been seq-d on, and we're now returning to the
696 * algebraic-case-continuation which forced the
697 * evaluation in the first place.)
709 barf("Invalid update frame during argcheck");
711 } while (xSp==(P_)xSu);
719 int words = BCO_INSTR_8;
720 SSS; p = grabHpUpd(AP_sizeW(words)); LLL;
724 Case(i_ALLOC_CONSTR):
727 StgInfoTable* info = bcoConstAddr(bco,BCO_INSTR_8);
728 SSS; p = grabHpNonUpd(sizeW_fromITBL(info)); LLL;
729 SET_HDR((StgClosure*)p,info,??);
733 Case(i_ALLOC_CONSTR_big):
736 int x = BCO_INSTR_16;
737 StgInfoTable* info = bcoConstAddr(bco,x);
738 SSS; p = grabHpNonUpd(sizeW_fromITBL(info)); LLL;
739 SET_HDR((StgClosure*)p,info,??);
745 int x = BCO_INSTR_8; /* ToDo: Word not Int! */
747 StgAP_UPD* o = stgCast(StgAP_UPD*,xStackPtr(x));
748 SET_HDR(o,&AP_UPD_info,??);
750 o->fun = stgCast(StgClosure*,xPopPtr());
751 for(x=0; x < y; ++x) {
752 payloadWord(o,x) = xPopWord();
755 fprintf(stderr,"\tBuilt ");
757 printObj(stgCast(StgClosure*,o));
768 o = stgCast(StgAP_UPD*,xStackPtr(x));
769 SET_HDR(o,&AP_UPD_info,??);
771 o->fun = stgCast(StgClosure*,xPopPtr());
772 for(x=0; x < y; ++x) {
773 payloadWord(o,x) = xPopWord();
776 fprintf(stderr,"\tBuilt ");
778 printObj(stgCast(StgClosure*,o));
787 StgPAP* o = stgCast(StgPAP*,xStackPtr(x));
788 SET_HDR(o,&PAP_info,??);
790 o->fun = stgCast(StgClosure*,xPopPtr());
791 for(x=0; x < y; ++x) {
792 payloadWord(o,x) = xPopWord();
795 fprintf(stderr,"\tBuilt ");
797 printObj(stgCast(StgClosure*,o));
804 int offset = BCO_INSTR_8;
805 StgClosure* o = stgCast(StgClosure*,xStackPtr(offset));
806 const StgInfoTable* info = get_itbl(o);
807 nat p = info->layout.payload.ptrs;
808 nat np = info->layout.payload.nptrs;
810 for(i=0; i < p; ++i) {
811 o->payload[i] = xPopCPtr();
813 for(i=0; i < np; ++i) {
814 payloadWord(o,p+i) = 0xdeadbeef;
817 fprintf(stderr,"\tBuilt ");
819 printObj(stgCast(StgClosure*,o));
826 int offset = BCO_INSTR_16;
827 StgClosure* o = stgCast(StgClosure*,xStackPtr(offset));
828 const StgInfoTable* info = get_itbl(o);
829 nat p = info->layout.payload.ptrs;
830 nat np = info->layout.payload.nptrs;
832 for(i=0; i < p; ++i) {
833 o->payload[i] = xPopCPtr();
835 for(i=0; i < np; ++i) {
836 payloadWord(o,p+i) = 0xdeadbeef;
839 fprintf(stderr,"\tBuilt ");
841 printObj(stgCast(StgClosure*,o));
850 ASSERT(xSp+x+y <= stgCast(StgPtr,xSu));
851 /* a_1, .. a_x, b_1, .. b_y, s => a_1, .. a_x, s */
853 xSetStackWord(x+y,xStackWord(x));
863 ASSERT(xSp+x+y <= stgCast(StgPtr,xSu));
864 /* a_1, .. a_x, b_1, .. b_y, s => a_1, .. a_x, s */
866 xSetStackWord(x+y,xStackWord(x));
878 xPushPtr(bcoConstPtr(bco,BCO_INSTR_8));
879 xPushPtr(stgCast(StgPtr,&ret_bco_info));
884 int tag = BCO_INSTR_8;
885 StgWord offset = BCO_INSTR_16;
886 if (constrTag( (StgClosure*)xStackPtr(0) ) != tag) {
893 StgClosure* o = stgCast(StgClosure*,xStackPtr(0));
894 const StgInfoTable* itbl = get_itbl(o);
895 int i = itbl->layout.payload.ptrs;
896 ASSERT( itbl->type == CONSTR
897 || itbl->type == CONSTR_STATIC
898 || itbl->type == CONSTR_NOCAF_STATIC
899 || itbl->type == CONSTR_1_0
900 || itbl->type == CONSTR_0_1
901 || itbl->type == CONSTR_2_0
902 || itbl->type == CONSTR_1_1
903 || itbl->type == CONSTR_0_2
906 xPushCPtr(o->payload[i]);
912 int n = BCO_INSTR_16;
913 StgPtr p = xStackPtr(n);
919 StgPtr p = xStackPtr(BCO_INSTR_8);
925 xPushPtr(stgCast(StgPtr,bcoConstPtr(bco,BCO_INSTR_8)));
930 int n = BCO_INSTR_16;
931 xPushPtr(stgCast(StgPtr,bcoConstPtr(bco,n)));
936 SSS; PushTaggedRealWorld(); LLL;
941 StgInt i = xTaggedStackInt(BCO_INSTR_8);
947 xPushTaggedInt(bcoConstInt(bco,BCO_INSTR_8));
950 Case(i_CONST_INT_big):
952 int n = BCO_INSTR_16;
953 xPushTaggedInt(bcoConstInt(bco,n));
959 SSS; o = (StgClosure*)grabHpNonUpd(Izh_sizeW); LLL;
960 SET_HDR(o,Izh_con_info,??);
961 payloadWord(o,0) = xPopTaggedInt();
963 fprintf(stderr,"\tBuilt ");
965 printObj(stgCast(StgClosure*,o));
968 xPushPtr(stgCast(StgPtr,o));
973 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
974 /* ASSERT(isIntLike(con)); */
975 xPushTaggedInt(payloadWord(con,0));
980 StgWord offset = BCO_INSTR_16;
981 StgInt x = xPopTaggedInt();
982 StgInt y = xPopTaggedInt();
988 Case(i_CONST_INTEGER):
992 char* s = bcoConstAddr(bco,BCO_INSTR_8);
995 p = CreateByteArrayToHoldInteger(n);
996 do_fromStr ( s, n, IntegerInsideByteArray(p));
997 SloppifyIntegerEnd(p);
1004 StgWord w = xTaggedStackWord(BCO_INSTR_8);
1010 xPushTaggedWord(bcoConstWord(bco,BCO_INSTR_8));
1016 SSS; o = (StgClosure*)grabHpNonUpd(Wzh_sizeW); LLL;
1017 SET_HDR(o,Wzh_con_info,??);
1018 payloadWord(o,0) = xPopTaggedWord();
1020 fprintf(stderr,"\tBuilt ");
1022 printObj(stgCast(StgClosure*,o));
1025 xPushPtr(stgCast(StgPtr,o));
1028 Case(i_UNPACK_WORD):
1030 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1031 /* ASSERT(isWordLike(con)); */
1032 xPushTaggedWord(payloadWord(con,0));
1037 StgAddr a = xTaggedStackAddr(BCO_INSTR_8);
1043 xPushTaggedAddr(bcoConstAddr(bco,BCO_INSTR_8));
1046 Case(i_CONST_ADDR_big):
1048 int n = BCO_INSTR_16;
1049 xPushTaggedAddr(bcoConstAddr(bco,n));
1055 SSS; o = (StgClosure*)grabHpNonUpd(Azh_sizeW); LLL;
1056 SET_HDR(o,Azh_con_info,??);
1057 payloadPtr(o,0) = xPopTaggedAddr();
1059 fprintf(stderr,"\tBuilt ");
1061 printObj(stgCast(StgClosure*,o));
1064 xPushPtr(stgCast(StgPtr,o));
1067 Case(i_UNPACK_ADDR):
1069 StgClosure* con = (StgClosure*)xStackPtr(0);
1070 /* ASSERT(isAddrLike(con)); */
1071 xPushTaggedAddr(payloadPtr(con,0));
1076 StgChar c = xTaggedStackChar(BCO_INSTR_8);
1082 xPushTaggedChar(bcoConstChar(bco,BCO_INSTR_8));
1088 SSS; o = (StgClosure*)grabHpNonUpd(Czh_sizeW); LLL;
1089 SET_HDR(o,Czh_con_info,??);
1090 payloadWord(o,0) = xPopTaggedChar();
1091 xPushPtr(stgCast(StgPtr,o));
1093 fprintf(stderr,"\tBuilt ");
1095 printObj(stgCast(StgClosure*,o));
1100 Case(i_UNPACK_CHAR):
1102 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1103 /* ASSERT(isCharLike(con)); */
1104 xPushTaggedChar(payloadWord(con,0));
1109 StgFloat f = xTaggedStackFloat(BCO_INSTR_8);
1110 xPushTaggedFloat(f);
1113 Case(i_CONST_FLOAT):
1115 xPushTaggedFloat(bcoConstFloat(bco,BCO_INSTR_8));
1121 SSS; o = (StgClosure*)grabHpNonUpd(Fzh_sizeW); LLL;
1122 SET_HDR(o,Fzh_con_info,??);
1123 ASSIGN_FLT(&payloadWord(o,0),xPopTaggedFloat());
1125 fprintf(stderr,"\tBuilt ");
1127 printObj(stgCast(StgClosure*,o));
1130 xPushPtr(stgCast(StgPtr,o));
1133 Case(i_UNPACK_FLOAT):
1135 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1136 /* ASSERT(isFloatLike(con)); */
1137 xPushTaggedFloat(PK_FLT(&payloadWord(con,0)));
1142 StgDouble d = xTaggedStackDouble(BCO_INSTR_8);
1143 xPushTaggedDouble(d);
1146 Case(i_CONST_DOUBLE):
1148 xPushTaggedDouble(bcoConstDouble(bco,BCO_INSTR_8));
1151 Case(i_CONST_DOUBLE_big):
1153 int n = BCO_INSTR_16;
1154 xPushTaggedDouble(bcoConstDouble(bco,n));
1157 Case(i_PACK_DOUBLE):
1160 SSS; o = (StgClosure*)grabHpNonUpd(Dzh_sizeW); LLL;
1161 SET_HDR(o,Dzh_con_info,??);
1162 ASSIGN_DBL(&payloadWord(o,0),xPopTaggedDouble());
1164 fprintf(stderr,"\tBuilt ");
1165 printObj(stgCast(StgClosure*,o));
1167 xPushPtr(stgCast(StgPtr,o));
1170 Case(i_UNPACK_DOUBLE):
1172 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1173 /* ASSERT(isDoubleLike(con)); */
1174 xPushTaggedDouble(PK_DBL(&payloadWord(con,0)));
1179 StgStablePtr s = xTaggedStackStable(BCO_INSTR_8);
1180 xPushTaggedStable(s);
1183 Case(i_PACK_STABLE):
1186 SSS; o = (StgClosure*)grabHpNonUpd(Stablezh_sizeW); LLL;
1187 SET_HDR(o,StablePtr_con_info,??);
1188 payloadWord(o,0) = xPopTaggedStable();
1190 fprintf(stderr,"\tBuilt ");
1192 printObj(stgCast(StgClosure*,o));
1195 xPushPtr(stgCast(StgPtr,o));
1198 Case(i_UNPACK_STABLE):
1200 StgClosure* con = (StgClosure*)xStackPtr(0);
1201 /* ASSERT(isStableLike(con)); */
1202 xPushTaggedStable(payloadWord(con,0));
1210 SSS; p = enterBCO_primop1 ( i ); LLL;
1211 if (p) { obj = p; goto enterLoop; };
1216 int i, trc, pc_saved;
1219 trc = 12345678; /* Assume != any StgThreadReturnCode */
1224 p = enterBCO_primop2 ( i, &trc, &bco_tmp, cap,
1228 bciPtr = &(bcoInstr(bco,pc_saved));
1230 if (trc == 12345678) {
1231 /* we want to enter p */
1232 obj = p; goto enterLoop;
1234 /* trc is the the StgThreadReturnCode for
1236 RETURN((StgThreadReturnCode)trc);
1242 /* combined insns, created by peephole opt */
1245 int x = BCO_INSTR_8;
1246 int y = BCO_INSTR_8;
1247 ASSERT(xSp+x+y <= stgCast(StgPtr,xSu));
1248 /* a_1, .. a_x, b_1, .. b_y, s => a_1, .. a_x, s */
1255 xSetStackWord(x+y,xStackWord(x));
1265 p = xStackPtr(BCO_INSTR_8);
1267 p = xStackPtr(BCO_INSTR_8);
1274 xPushPtr(bcoConstPtr(bco,BCO_INSTR_8));
1275 xPushPtr(stgCast(StgPtr,&ret_bco_info));
1276 p = xStackPtr(BCO_INSTR_8);
1282 StgPtr retaddr = bcoConstPtr(bco,BCO_INSTR_8);
1283 StgPtr ptr = xStackPtr(BCO_INSTR_8);
1285 /* A shortcut. We're going to push the address of a
1286 return continuation, and then enter a variable, so
1287 that when the var is evaluated, we return to the
1288 continuation. The shortcut is: if the var is a
1289 constructor, don't bother to enter it. Instead,
1290 push the variable on the stack (since this is what
1291 the continuation expects) and jump directly to the
1294 if (get_itbl((StgClosure*)ptr)->type == CONSTR) {
1296 obj = (StgClosure*)retaddr;
1298 fprintf(stderr, "object to enter is a constructor -- "
1299 "jumping directly to return continuation\n" );
1304 /* This is the normal, non-short-cut route */
1306 xPushPtr(stgCast(StgPtr,&ret_bco_info));
1307 obj = (StgClosure*)ptr;
1312 Case(i_VAR_DOUBLE_big):
1313 Case(i_CONST_FLOAT_big):
1314 Case(i_VAR_FLOAT_big):
1315 Case(i_CONST_CHAR_big):
1316 Case(i_VAR_CHAR_big):
1317 Case(i_VAR_ADDR_big):
1318 Case(i_VAR_STABLE_big):
1319 Case(i_CONST_INTEGER_big):
1320 Case(i_VAR_INT_big):
1321 Case(i_VAR_WORD_big):
1322 Case(i_RETADDR_big):
1326 disInstr ( bco, PC );
1327 barf("\nUnrecognised instruction");
1331 barf("enterBCO: ran off end of loop");
1335 # undef LoopTopLabel
1341 /* ---------------------------------------------------- */
1342 /* End of the bytecode evaluator */
1343 /* ---------------------------------------------------- */
1347 StgBlockingQueue* bh;
1348 StgCAF* caf = (StgCAF*)obj;
1349 if (xSp - sizeofW(StgUpdateFrame) < xSpLim) {
1350 xPushCPtr(obj); /* code to restart with */
1351 RETURN(StackOverflow);
1353 /* ToDo: look for xSp==xSu && stackInt(0) == UPD_FRAME
1354 and insert an indirection immediately */
1355 SSS; bh = (StgBlockingQueue*)grabHpUpd(BLACKHOLE_sizeW()); LLL;
1356 SET_INFO(bh,&CAF_BLACKHOLE_info);
1357 bh->blocking_queue = EndTSOQueue;
1359 fprintf(stderr,"Created CAF_BLACKHOLE %p for CAF %p in evaluator\n",bh,caf));
1360 SET_INFO(caf,&CAF_ENTERED_info);
1361 caf->value = (StgClosure*)bh;
1362 if (caf->mut_link == NULL) {
1363 SSS; recordOldToNewPtrs((StgMutClosure*)caf); LLL;
1365 xPushUpdateFrame(bh,0);
1366 xSp -= sizeofW(StgUpdateFrame);
1367 caf->link = enteredCAFs;
1374 StgCAF* caf = (StgCAF*)obj;
1375 obj = caf->value; /* it's just a fancy indirection */
1381 case SE_CAF_BLACKHOLE:
1383 /* Let the scheduler figure out what to do :-) */
1384 cap->rCurrentTSO->what_next = ThreadEnterGHC;
1386 RETURN(ThreadYielding);
1390 StgAP_UPD* ap = stgCast(StgAP_UPD*,obj);
1392 if (xSp - (i + sizeofW(StgUpdateFrame)) < xSpLim) {
1393 xPushCPtr(obj); /* code to restart with */
1394 RETURN(StackOverflow);
1396 /* ToDo: look for xSp==xSu && stackInt(0) == UPD_FRAME
1397 and insert an indirection immediately */
1398 xPushUpdateFrame(ap,0);
1399 xSp -= sizeofW(StgUpdateFrame);
1401 xPushWord(payloadWord(ap,i));
1404 #ifdef EAGER_BLACKHOLING
1405 #warn LAZY_BLACKHOLING is default for StgHugs
1406 #error Dont know if EAGER_BLACKHOLING works in StgHugs
1408 /* superfluous - but makes debugging easier */
1409 StgBlackHole* bh = stgCast(StgBlackHole*,ap);
1410 SET_INFO(bh,&BLACKHOLE_info);
1411 bh->blocking_queue = EndTSOQueue;
1413 fprintf(stderr,"Eagerly blackholed AP_UPD %p in evaluator\n",bh));
1416 #endif /* EAGER_BLACKHOLING */
1421 StgPAP* pap = stgCast(StgPAP*,obj);
1422 int i = pap->n_args; /* ToDo: stack check */
1423 /* ToDo: if PAP is in whnf, we can update any update frames
1427 xPushWord(payloadWord(pap,i));
1434 obj = stgCast(StgInd*,obj)->indirectee;
1439 obj = stgCast(StgIndOldGen*,obj)->indirectee;
1448 case CONSTR_INTLIKE:
1449 case CONSTR_CHARLIKE:
1451 case CONSTR_NOCAF_STATIC:
1454 switch (get_itbl(stgCast(StgClosure*,xSp))->type) {
1456 SSS; PopCatchFrame(); LLL;
1459 xPopUpdateFrame(obj);
1462 SSS; PopSeqFrame(); LLL;
1466 ASSERT(xSp==(P_)xSu);
1469 fprintf(stderr, "hit a STOP_FRAME\n");
1471 fprintf(stderr,"xSp = %p\txSu = %p\n", xSp, xSu);
1472 printStack(xSp,cap->rCurrentTSO->stack
1473 + cap->rCurrentTSO->stack_size,xSu);
1476 SSS; PopStopFrame(obj); LLL;
1477 RETURN(ThreadFinished);
1487 /* was: goto enterLoop;
1488 But we know that obj must be a bco now, so jump directly.
1491 case RET_SMALL: /* return to GHC */
1495 cap->rCurrentTSO->what_next = ThreadEnterGHC;
1497 RETURN(ThreadYielding);
1499 belch("entered CONSTR with invalid continuation on stack");
1502 printObj(stgCast(StgClosure*,xSp));
1505 barf("bailing out");
1512 //fprintf(stderr, "enterCountI = %d\n", enterCountI);
1513 //fprintf(stderr, "entering unknown closure -- yielding to sched\n");
1516 cap->rCurrentTSO->what_next = ThreadEnterGHC;
1517 xPushCPtr(obj); /* code to restart with */
1518 RETURN(ThreadYielding);
1521 barf("Ran off the end of enter - yoiks");
1538 #undef xSetStackWord
1541 #undef xPushTaggedInt
1542 #undef xPopTaggedInt
1543 #undef xTaggedStackInt
1544 #undef xPushTaggedWord
1545 #undef xPopTaggedWord
1546 #undef xTaggedStackWord
1547 #undef xPushTaggedAddr
1548 #undef xTaggedStackAddr
1549 #undef xPopTaggedAddr
1550 #undef xPushTaggedStable
1551 #undef xTaggedStackStable
1552 #undef xPopTaggedStable
1553 #undef xPushTaggedChar
1554 #undef xTaggedStackChar
1555 #undef xPopTaggedChar
1556 #undef xPushTaggedFloat
1557 #undef xTaggedStackFloat
1558 #undef xPopTaggedFloat
1559 #undef xPushTaggedDouble
1560 #undef xTaggedStackDouble
1561 #undef xPopTaggedDouble
1562 #undef xPopUpdateFrame
1563 #undef xPushUpdateFrame
1566 /* --------------------------------------------------------------------------
1567 * Supporting routines for primops
1568 * ------------------------------------------------------------------------*/
1570 static inline void PushTag ( StackTag t )
1572 inline void PushPtr ( StgPtr x )
1573 { *(--stgCast(StgPtr*,gSp)) = x; }
1574 static inline void PushCPtr ( StgClosure* x )
1575 { *(--stgCast(StgClosure**,gSp)) = x; }
1576 static inline void PushInt ( StgInt x )
1577 { *(--stgCast(StgInt*,gSp)) = x; }
1578 static inline void PushWord ( StgWord x )
1579 { *(--stgCast(StgWord*,gSp)) = x; }
1582 static inline void checkTag ( StackTag t1, StackTag t2 )
1583 { ASSERT(t1 == t2);}
1584 static inline void PopTag ( StackTag t )
1585 { checkTag(t,*(gSp++)); }
1586 inline StgPtr PopPtr ( void )
1587 { return *stgCast(StgPtr*,gSp)++; }
1588 static inline StgClosure* PopCPtr ( void )
1589 { return *stgCast(StgClosure**,gSp)++; }
1590 static inline StgInt PopInt ( void )
1591 { return *stgCast(StgInt*,gSp)++; }
1592 static inline StgWord PopWord ( void )
1593 { return *stgCast(StgWord*,gSp)++; }
1595 static inline StgPtr stackPtr ( StgStackOffset i )
1596 { return *stgCast(StgPtr*, gSp+i); }
1597 static inline StgInt stackInt ( StgStackOffset i )
1598 { return *stgCast(StgInt*, gSp+i); }
1599 static inline StgWord stackWord ( StgStackOffset i )
1600 { return *stgCast(StgWord*,gSp+i); }
1602 static inline void setStackWord ( StgStackOffset i, StgWord w )
1605 static inline void PushTaggedRealWorld( void )
1606 { PushTag(REALWORLD_TAG); }
1607 inline void PushTaggedInt ( StgInt x )
1608 { gSp -= sizeofW(StgInt); *gSp = x; PushTag(INT_TAG); }
1609 inline void PushTaggedWord ( StgWord x )
1610 { gSp -= sizeofW(StgWord); *gSp = x; PushTag(WORD_TAG); }
1611 inline void PushTaggedAddr ( StgAddr x )
1612 { gSp -= sizeofW(StgAddr); *gSp = (W_)x; PushTag(ADDR_TAG); }
1613 inline void PushTaggedChar ( StgChar x )
1614 { gSp -= sizeofW(StgChar); *gSp = stgCast(StgWord,x); PushTag(CHAR_TAG); }
1615 inline void PushTaggedFloat ( StgFloat x )
1616 { gSp -= sizeofW(StgFloat); ASSIGN_FLT(gSp,x); PushTag(FLOAT_TAG); }
1617 inline void PushTaggedDouble ( StgDouble x )
1618 { gSp -= sizeofW(StgDouble); ASSIGN_DBL(gSp,x); PushTag(DOUBLE_TAG); }
1619 inline void PushTaggedStablePtr ( StgStablePtr x )
1620 { gSp -= sizeofW(StgStablePtr); *gSp = x; PushTag(STABLE_TAG); }
1621 static inline void PushTaggedBool ( int x )
1622 { PushTaggedInt(x); }
1626 static inline void PopTaggedRealWorld ( void )
1627 { PopTag(REALWORLD_TAG); }
1628 inline StgInt PopTaggedInt ( void )
1629 { StgInt r; PopTag(INT_TAG); r = *stgCast(StgInt*, gSp);
1630 gSp += sizeofW(StgInt); return r;}
1631 inline StgWord PopTaggedWord ( void )
1632 { StgWord r; PopTag(WORD_TAG); r = *stgCast(StgWord*, gSp);
1633 gSp += sizeofW(StgWord); return r;}
1634 inline StgAddr PopTaggedAddr ( void )
1635 { StgAddr r; PopTag(ADDR_TAG); r = *stgCast(StgAddr*, gSp);
1636 gSp += sizeofW(StgAddr); return r;}
1637 inline StgChar PopTaggedChar ( void )
1638 { StgChar r; PopTag(CHAR_TAG); r = stgCast(StgChar, *gSp);
1639 gSp += sizeofW(StgChar); return r;}
1640 inline StgFloat PopTaggedFloat ( void )
1641 { StgFloat r; PopTag(FLOAT_TAG); r = PK_FLT(gSp);
1642 gSp += sizeofW(StgFloat); return r;}
1643 inline StgDouble PopTaggedDouble ( void )
1644 { StgDouble r; PopTag(DOUBLE_TAG); r = PK_DBL(gSp);
1645 gSp += sizeofW(StgDouble); return r;}
1646 inline StgStablePtr PopTaggedStablePtr ( void )
1647 { StgInt r; PopTag(STABLE_TAG); r = *stgCast(StgStablePtr*, gSp);
1648 gSp += sizeofW(StgStablePtr); return r;}
1652 static inline StgInt taggedStackInt ( StgStackOffset i )
1653 { checkTag(INT_TAG,gSp[i]); return *stgCast(StgInt*, gSp+1+i); }
1654 static inline StgWord taggedStackWord ( StgStackOffset i )
1655 { checkTag(WORD_TAG,gSp[i]); return *stgCast(StgWord*, gSp+1+i); }
1656 static inline StgAddr taggedStackAddr ( StgStackOffset i )
1657 { checkTag(ADDR_TAG,gSp[i]); return *stgCast(StgAddr*, gSp+1+i); }
1658 static inline StgChar taggedStackChar ( StgStackOffset i )
1659 { checkTag(CHAR_TAG,gSp[i]); return stgCast(StgChar, *(gSp+1+i)) ; }
1660 static inline StgFloat taggedStackFloat ( StgStackOffset i )
1661 { checkTag(FLOAT_TAG,gSp[i]); return PK_FLT(gSp+1+i); }
1662 static inline StgDouble taggedStackDouble ( StgStackOffset i )
1663 { checkTag(DOUBLE_TAG,gSp[i]); return PK_DBL(gSp+1+i); }
1664 static inline StgStablePtr taggedStackStable ( StgStackOffset i )
1665 { checkTag(STABLE_TAG,gSp[i]); return *stgCast(StgStablePtr*, gSp+1+i); }
1668 /* --------------------------------------------------------------------------
1671 * Should we allocate from a nursery or use the
1672 * doYouWantToGC/allocate interface? We'd already implemented a
1673 * nursery-style scheme when the doYouWantToGC/allocate interface
1675 * One reason to prefer the doYouWantToGC/allocate interface is to
1676 * support operations which allocate an unknown amount in the heap
1677 * (array ops, gmp ops, etc)
1678 * ------------------------------------------------------------------------*/
1680 static inline StgPtr grabHpUpd( nat size )
1682 ASSERT( size >= MIN_UPD_SIZE + sizeofW(StgHeader) );
1683 #ifdef CRUDE_PROFILING
1684 cp_bill_words ( size );
1686 return allocate(size);
1689 static inline StgPtr grabHpNonUpd( nat size )
1691 ASSERT( size >= MIN_NONUPD_SIZE + sizeofW(StgHeader) );
1692 #ifdef CRUDE_PROFILING
1693 cp_bill_words ( size );
1695 return allocate(size);
1698 /* --------------------------------------------------------------------------
1699 * Manipulate "update frame" list:
1700 * o Update frames (based on stg_do_update and friends in Updates.hc)
1701 * o Error handling/catching (based on catchzh_fast and friends in Prims.hc)
1702 * o Seq frames (based on seq_frame_entry in Prims.hc)
1704 * ------------------------------------------------------------------------*/
1706 static inline void PopUpdateFrame ( StgClosure* obj )
1708 /* NB: doesn't assume that gSp == gSu */
1710 fprintf(stderr, "Updating ");
1711 printPtr(stgCast(StgPtr,gSu->updatee));
1712 fprintf(stderr, " with ");
1714 fprintf(stderr,"gSp = %p\tgSu = %p\n\n", gSp, gSu);
1716 #ifdef EAGER_BLACKHOLING
1717 #warn LAZY_BLACKHOLING is default for StgHugs
1718 #error Dont know if EAGER_BLACKHOLING works in StgHugs
1719 ASSERT(get_itbl(gSu->updatee)->type == BLACKHOLE
1720 || get_itbl(gSu->updatee)->type == SE_BLACKHOLE
1721 || get_itbl(gSu->updatee)->type == CAF_BLACKHOLE
1722 || get_itbl(gSu->updatee)->type == SE_CAF_BLACKHOLE
1724 #endif /* EAGER_BLACKHOLING */
1725 UPD_IND(gSu->updatee,obj);
1726 gSp = stgCast(StgStackPtr,gSu) + sizeofW(StgUpdateFrame);
1730 static inline void PopStopFrame ( StgClosure* obj )
1732 /* Move gSu just off the end of the stack, we're about to gSpam the
1733 * STOP_FRAME with the return value.
1735 gSu = stgCast(StgUpdateFrame*,gSp+1);
1736 *stgCast(StgClosure**,gSp) = obj;
1739 static inline void PushCatchFrame ( StgClosure* handler )
1742 /* ToDo: stack check! */
1743 gSp -= sizeofW(StgCatchFrame);
1744 fp = stgCast(StgCatchFrame*,gSp);
1745 SET_HDR(fp,(StgInfoTable*)&catch_frame_info,CCCS);
1746 fp->handler = handler;
1748 gSu = stgCast(StgUpdateFrame*,fp);
1751 static inline void PopCatchFrame ( void )
1753 /* NB: doesn't assume that gSp == gSu */
1754 /* fprintf(stderr,"Popping catch frame\n"); */
1755 gSp = stgCast(StgStackPtr,gSu) + sizeofW(StgCatchFrame);
1756 gSu = stgCast(StgCatchFrame*,gSu)->link;
1759 static inline void PushSeqFrame ( void )
1762 /* ToDo: stack check! */
1763 gSp -= sizeofW(StgSeqFrame);
1764 fp = stgCast(StgSeqFrame*,gSp);
1765 SET_HDR(fp,(StgInfoTable*)&seq_frame_info,CCCS);
1767 gSu = stgCast(StgUpdateFrame*,fp);
1770 static inline void PopSeqFrame ( void )
1772 /* NB: doesn't assume that gSp == gSu */
1773 gSp = stgCast(StgStackPtr,gSu) + sizeofW(StgSeqFrame);
1774 gSu = stgCast(StgSeqFrame*,gSu)->link;
1777 static inline StgClosure* raiseAnError ( StgClosure* exception )
1779 /* This closure represents the expression 'primRaise E' where E
1780 * is the exception raised (:: Exception).
1781 * It is used to overwrite all the
1782 * thunks which are currently under evaluation.
1784 HaskellObj primRaiseClosure
1785 = asmClosureOfObject(getHugs_AsmObject_for("primRaise"));
1786 HaskellObj reraiseClosure
1787 = rts_apply ( primRaiseClosure, exception );
1790 switch (get_itbl(gSu)->type) {
1792 UPD_IND(gSu->updatee,reraiseClosure);
1793 gSp = stgCast(StgStackPtr,gSu) + sizeofW(StgUpdateFrame);
1799 case CATCH_FRAME: /* found it! */
1801 StgCatchFrame* fp = stgCast(StgCatchFrame*,gSu);
1802 StgClosure *handler = fp->handler;
1804 gSp += sizeofW(StgCatchFrame); /* Pop */
1805 PushCPtr(exception);
1809 barf("raiseError: uncaught exception: STOP_FRAME");
1811 barf("raiseError: weird activation record");
1817 static StgClosure* makeErrorCall ( const char* msg )
1819 /* Note! the msg string should be allocated in a
1820 place which will not get freed -- preferably
1821 read-only data of the program. That's because
1822 the thunk we build here may linger indefinitely.
1823 (thinks: probably not so, but anyway ...)
1826 = asmClosureOfObject(getHugs_AsmObject_for("error"));
1828 = asmClosureOfObject(getHugs_AsmObject_for("hugsprimUnpackString"));
1830 = rts_apply ( unpack, rts_mkAddr ( (void*)msg ) );
1832 = rts_apply ( error, thunk );
1834 (StgClosure*) thunk;
1837 #define raiseIndex(where) makeErrorCall("Array index out of range in " where)
1838 #define raiseDiv0(where) makeErrorCall("Division by zero in " where)
1840 /* --------------------------------------------------------------------------
1842 * ------------------------------------------------------------------------*/
1844 #define OP_CC_B(e) \
1846 unsigned char x = PopTaggedChar(); \
1847 unsigned char y = PopTaggedChar(); \
1848 PushTaggedBool(e); \
1853 unsigned char x = PopTaggedChar(); \
1862 #define OP_IW_I(e) \
1864 StgInt x = PopTaggedInt(); \
1865 StgWord y = PopTaggedWord(); \
1869 #define OP_II_I(e) \
1871 StgInt x = PopTaggedInt(); \
1872 StgInt y = PopTaggedInt(); \
1876 #define OP_II_B(e) \
1878 StgInt x = PopTaggedInt(); \
1879 StgInt y = PopTaggedInt(); \
1880 PushTaggedBool(e); \
1885 PushTaggedAddr(e); \
1890 StgInt x = PopTaggedInt(); \
1891 PushTaggedAddr(e); \
1896 StgInt x = PopTaggedInt(); \
1902 PushTaggedChar(e); \
1907 StgInt x = PopTaggedInt(); \
1908 PushTaggedChar(e); \
1913 PushTaggedWord(e); \
1918 StgInt x = PopTaggedInt(); \
1919 PushTaggedWord(e); \
1924 StgInt x = PopTaggedInt(); \
1925 PushTaggedStablePtr(e); \
1930 PushTaggedFloat(e); \
1935 StgInt x = PopTaggedInt(); \
1936 PushTaggedFloat(e); \
1941 PushTaggedDouble(e); \
1946 StgInt x = PopTaggedInt(); \
1947 PushTaggedDouble(e); \
1950 #define OP_WW_B(e) \
1952 StgWord x = PopTaggedWord(); \
1953 StgWord y = PopTaggedWord(); \
1954 PushTaggedBool(e); \
1957 #define OP_WW_W(e) \
1959 StgWord x = PopTaggedWord(); \
1960 StgWord y = PopTaggedWord(); \
1961 PushTaggedWord(e); \
1966 StgWord x = PopTaggedWord(); \
1972 StgStablePtr x = PopTaggedStablePtr(); \
1978 StgWord x = PopTaggedWord(); \
1979 PushTaggedWord(e); \
1982 #define OP_AA_B(e) \
1984 StgAddr x = PopTaggedAddr(); \
1985 StgAddr y = PopTaggedAddr(); \
1986 PushTaggedBool(e); \
1990 StgAddr x = PopTaggedAddr(); \
1993 #define OP_AI_C(s) \
1995 StgAddr x = PopTaggedAddr(); \
1996 int y = PopTaggedInt(); \
1999 PushTaggedChar(r); \
2001 #define OP_AI_I(s) \
2003 StgAddr x = PopTaggedAddr(); \
2004 int y = PopTaggedInt(); \
2009 #define OP_AI_A(s) \
2011 StgAddr x = PopTaggedAddr(); \
2012 int y = PopTaggedInt(); \
2015 PushTaggedAddr(s); \
2017 #define OP_AI_F(s) \
2019 StgAddr x = PopTaggedAddr(); \
2020 int y = PopTaggedInt(); \
2023 PushTaggedFloat(r); \
2025 #define OP_AI_D(s) \
2027 StgAddr x = PopTaggedAddr(); \
2028 int y = PopTaggedInt(); \
2031 PushTaggedDouble(r); \
2033 #define OP_AI_s(s) \
2035 StgAddr x = PopTaggedAddr(); \
2036 int y = PopTaggedInt(); \
2039 PushTaggedStablePtr(r); \
2041 #define OP_AIC_(s) \
2043 StgAddr x = PopTaggedAddr(); \
2044 int y = PopTaggedInt(); \
2045 StgChar z = PopTaggedChar(); \
2048 #define OP_AII_(s) \
2050 StgAddr x = PopTaggedAddr(); \
2051 int y = PopTaggedInt(); \
2052 StgInt z = PopTaggedInt(); \
2055 #define OP_AIA_(s) \
2057 StgAddr x = PopTaggedAddr(); \
2058 int y = PopTaggedInt(); \
2059 StgAddr z = PopTaggedAddr(); \
2062 #define OP_AIF_(s) \
2064 StgAddr x = PopTaggedAddr(); \
2065 int y = PopTaggedInt(); \
2066 StgFloat z = PopTaggedFloat(); \
2069 #define OP_AID_(s) \
2071 StgAddr x = PopTaggedAddr(); \
2072 int y = PopTaggedInt(); \
2073 StgDouble z = PopTaggedDouble(); \
2076 #define OP_AIs_(s) \
2078 StgAddr x = PopTaggedAddr(); \
2079 int y = PopTaggedInt(); \
2080 StgStablePtr z = PopTaggedStablePtr(); \
2085 #define OP_FF_B(e) \
2087 StgFloat x = PopTaggedFloat(); \
2088 StgFloat y = PopTaggedFloat(); \
2089 PushTaggedBool(e); \
2092 #define OP_FF_F(e) \
2094 StgFloat x = PopTaggedFloat(); \
2095 StgFloat y = PopTaggedFloat(); \
2096 PushTaggedFloat(e); \
2101 StgFloat x = PopTaggedFloat(); \
2102 PushTaggedFloat(e); \
2107 StgFloat x = PopTaggedFloat(); \
2108 PushTaggedBool(e); \
2113 StgFloat x = PopTaggedFloat(); \
2119 StgFloat x = PopTaggedFloat(); \
2120 PushTaggedDouble(e); \
2123 #define OP_DD_B(e) \
2125 StgDouble x = PopTaggedDouble(); \
2126 StgDouble y = PopTaggedDouble(); \
2127 PushTaggedBool(e); \
2130 #define OP_DD_D(e) \
2132 StgDouble x = PopTaggedDouble(); \
2133 StgDouble y = PopTaggedDouble(); \
2134 PushTaggedDouble(e); \
2139 StgDouble x = PopTaggedDouble(); \
2140 PushTaggedBool(e); \
2145 StgDouble x = PopTaggedDouble(); \
2146 PushTaggedDouble(e); \
2151 StgDouble x = PopTaggedDouble(); \
2157 StgDouble x = PopTaggedDouble(); \
2158 PushTaggedFloat(e); \
2162 StgPtr CreateByteArrayToHoldInteger ( int nbytes )
2164 StgWord words = (nbytes+sizeof(W_)-1)/sizeof(W_);
2165 StgWord size = sizeofW(StgArrWords) + words;
2166 StgArrWords* arr = (StgArrWords*)allocate(size);
2167 SET_HDR(arr,&ARR_WORDS_info,CCCS);
2169 ASSERT((W_)nbytes <= arr->words * sizeof(W_));
2172 for (i = 0; i < words; ++i) {
2173 arr->payload[i] = 0xdeadbeef;
2175 { B* b = (B*) &(arr->payload[0]);
2176 b->used = b->sign = 0;
2182 B* IntegerInsideByteArray ( StgPtr arr0 )
2185 StgArrWords* arr = (StgArrWords*)arr0;
2186 ASSERT(GET_INFO(arr) == &ARR_WORDS_info);
2187 b = (B*) &(arr->payload[0]);
2191 void SloppifyIntegerEnd ( StgPtr arr0 )
2193 StgArrWords* arr = (StgArrWords*)arr0;
2194 B* b = (B*) & (arr->payload[0]);
2195 I_ nwunused = arr->words - sizeofW(B) - (b->used+sizeof(W_)-1)/sizeof(W_);
2196 if (nwunused >= ((I_)sizeofW(StgArrWords))) {
2198 b->size -= nwunused * sizeof(W_);
2199 if (b->size < b->used) b->size = b->used;
2202 arr->words -= nwunused;
2203 slop = (StgArrWords*)&(arr->payload[arr->words]);
2204 SET_HDR(slop,&ARR_WORDS_info,CCCS);
2205 slop->words = nwunused - sizeofW(StgArrWords);
2206 ASSERT( &(slop->payload[slop->words]) ==
2207 &(arr->payload[arr->words + nwunused]) );
2211 #define OP_Z_Z(op) \
2213 B* x = IntegerInsideByteArray(PopPtr()); \
2214 int n = mycat2(size_,op)(x); \
2215 StgPtr p = CreateByteArrayToHoldInteger(n); \
2216 mycat2(do_,op)(x,n,IntegerInsideByteArray(p)); \
2217 SloppifyIntegerEnd(p); \
2220 #define OP_ZZ_Z(op) \
2222 B* x = IntegerInsideByteArray(PopPtr()); \
2223 B* y = IntegerInsideByteArray(PopPtr()); \
2224 int n = mycat2(size_,op)(x,y); \
2225 StgPtr p = CreateByteArrayToHoldInteger(n); \
2226 mycat2(do_,op)(x,y,n,IntegerInsideByteArray(p)); \
2227 SloppifyIntegerEnd(p); \
2234 #define HEADER_mI(ty,where) \
2235 StgArrWords* x = stgCast(StgArrWords*,PopPtr()); \
2236 nat i = PopTaggedInt(); \
2237 if (i * sizeof(ty) + (sizeof(ty)) > sizeof(StgWord) * x->words) { \
2238 return (raiseIndex(where)); \
2240 #define OP_mI_ty(ty,where,s) \
2242 HEADER_mI(mycat2(Stg,ty),where) \
2243 { mycat2(Stg,ty) r; \
2245 mycat2(PushTagged,ty)(r); \
2248 #define OP_mIty_(ty,where,s) \
2250 HEADER_mI(mycat2(Stg,ty),where) \
2252 mycat2(Stg,ty) z = mycat2(PopTagged,ty)(); \
2258 static void myStackCheck ( Capability* cap )
2260 /* fprintf(stderr, "myStackCheck\n"); */
2261 if (!(gSpLim <= gSp && gSp <= stgCast(StgPtr,gSu))) {
2262 fprintf(stderr, "myStackCheck: invalid initial gSp/gSu \n" );
2266 if (!( (P_)gSu >= (P_)cap->rCurrentTSO->stack
2268 (P_)gSu <= (P_)(cap->rCurrentTSO->stack
2269 + cap->rCurrentTSO->stack_size))) {
2270 fprintf ( stderr, "myStackCheck: gSu out of stack\n" );
2273 switch (get_itbl(stgCast(StgClosure*,gSu))->type) {
2275 gSu = (StgUpdateFrame*) ((StgCatchFrame*)(gSu))->link;
2278 gSu = (StgUpdateFrame*) ((StgUpdateFrame*)(gSu))->link;
2281 gSu = (StgUpdateFrame*) ((StgSeqFrame*)(gSu))->link;
2286 fprintf(stderr, "myStackCheck: invalid activation record\n"); assert(0);
2293 /* --------------------------------------------------------------------------
2294 * Primop stuff for bytecode interpreter
2295 * ------------------------------------------------------------------------*/
2297 /* Returns & of the next thing to enter (if throwing an exception),
2298 or NULL in the normal case.
2300 static void* enterBCO_primop1 ( int primop1code )
2303 barf("enterBCO_primop1 in combined mode");
2305 switch (primop1code) {
2306 case i_pushseqframe:
2308 StgClosure* c = PopCPtr();
2313 case i_pushcatchframe:
2315 StgClosure* e = PopCPtr();
2316 StgClosure* h = PopCPtr();
2322 case i_gtChar: OP_CC_B(x>y); break;
2323 case i_geChar: OP_CC_B(x>=y); break;
2324 case i_eqChar: OP_CC_B(x==y); break;
2325 case i_neChar: OP_CC_B(x!=y); break;
2326 case i_ltChar: OP_CC_B(x<y); break;
2327 case i_leChar: OP_CC_B(x<=y); break;
2328 case i_charToInt: OP_C_I(x); break;
2329 case i_intToChar: OP_I_C(x); break;
2331 case i_gtInt: OP_II_B(x>y); break;
2332 case i_geInt: OP_II_B(x>=y); break;
2333 case i_eqInt: OP_II_B(x==y); break;
2334 case i_neInt: OP_II_B(x!=y); break;
2335 case i_ltInt: OP_II_B(x<y); break;
2336 case i_leInt: OP_II_B(x<=y); break;
2337 case i_minInt: OP__I(INT_MIN); break;
2338 case i_maxInt: OP__I(INT_MAX); break;
2339 case i_plusInt: OP_II_I(x+y); break;
2340 case i_minusInt: OP_II_I(x-y); break;
2341 case i_timesInt: OP_II_I(x*y); break;
2344 int x = PopTaggedInt();
2345 int y = PopTaggedInt();
2347 return (raiseDiv0("quotInt"));
2349 /* ToDo: protect against minInt / -1 errors
2350 * (repeat for all other division primops) */
2356 int x = PopTaggedInt();
2357 int y = PopTaggedInt();
2359 return (raiseDiv0("remInt"));
2366 StgInt x = PopTaggedInt();
2367 StgInt y = PopTaggedInt();
2369 return (raiseDiv0("quotRemInt"));
2371 PushTaggedInt(x%y); /* last result */
2372 PushTaggedInt(x/y); /* first result */
2375 case i_negateInt: OP_I_I(-x); break;
2377 case i_andInt: OP_II_I(x&y); break;
2378 case i_orInt: OP_II_I(x|y); break;
2379 case i_xorInt: OP_II_I(x^y); break;
2380 case i_notInt: OP_I_I(~x); break;
2381 case i_shiftLInt: OP_II_I(x<<y); break;
2382 case i_shiftRAInt: OP_II_I(x>>y); break; /* ToDo */
2383 case i_shiftRLInt: OP_II_I(x>>y); break; /* ToDo */
2385 case i_gtWord: OP_WW_B(x>y); break;
2386 case i_geWord: OP_WW_B(x>=y); break;
2387 case i_eqWord: OP_WW_B(x==y); break;
2388 case i_neWord: OP_WW_B(x!=y); break;
2389 case i_ltWord: OP_WW_B(x<y); break;
2390 case i_leWord: OP_WW_B(x<=y); break;
2391 case i_minWord: OP__W(0); break;
2392 case i_maxWord: OP__W(UINT_MAX); break;
2393 case i_plusWord: OP_WW_W(x+y); break;
2394 case i_minusWord: OP_WW_W(x-y); break;
2395 case i_timesWord: OP_WW_W(x*y); break;
2398 StgWord x = PopTaggedWord();
2399 StgWord y = PopTaggedWord();
2401 return (raiseDiv0("quotWord"));
2403 PushTaggedWord(x/y);
2408 StgWord x = PopTaggedWord();
2409 StgWord y = PopTaggedWord();
2411 return (raiseDiv0("remWord"));
2413 PushTaggedWord(x%y);
2418 StgWord x = PopTaggedWord();
2419 StgWord y = PopTaggedWord();
2421 return (raiseDiv0("quotRemWord"));
2423 PushTaggedWord(x%y); /* last result */
2424 PushTaggedWord(x/y); /* first result */
2427 case i_negateWord: OP_W_W(-x); break;
2428 case i_andWord: OP_WW_W(x&y); break;
2429 case i_orWord: OP_WW_W(x|y); break;
2430 case i_xorWord: OP_WW_W(x^y); break;
2431 case i_notWord: OP_W_W(~x); break;
2432 case i_shiftLWord: OP_WW_W(x<<y); break;
2433 case i_shiftRAWord: OP_WW_W(x>>y); break; /* ToDo */
2434 case i_shiftRLWord: OP_WW_W(x>>y); break; /* ToDo */
2435 case i_intToWord: OP_I_W(x); break;
2436 case i_wordToInt: OP_W_I(x); break;
2438 case i_gtAddr: OP_AA_B(x>y); break;
2439 case i_geAddr: OP_AA_B(x>=y); break;
2440 case i_eqAddr: OP_AA_B(x==y); break;
2441 case i_neAddr: OP_AA_B(x!=y); break;
2442 case i_ltAddr: OP_AA_B(x<y); break;
2443 case i_leAddr: OP_AA_B(x<=y); break;
2444 case i_intToAddr: OP_I_A((StgAddr)x); break; /* ToDo */
2445 case i_addrToInt: OP_A_I((StgInt)x); break; /* ToDo */
2447 case i_intToStable: OP_I_s(x); break;
2448 case i_stableToInt: OP_s_I(x); break;
2450 case i_indexCharOffAddr: OP_AI_C(indexCharOffAddrzh(r,x,y)); break;
2451 case i_readCharOffAddr: OP_AI_C(indexCharOffAddrzh(r,x,y)); break;
2452 case i_writeCharOffAddr: OP_AIC_(writeCharOffAddrzh(x,y,z)); break;
2454 case i_indexIntOffAddr: OP_AI_I(indexIntOffAddrzh(r,x,y)); break;
2455 case i_readIntOffAddr: OP_AI_I(indexIntOffAddrzh(r,x,y)); break;
2456 case i_writeIntOffAddr: OP_AII_(writeIntOffAddrzh(x,y,z)); break;
2458 case i_indexAddrOffAddr: OP_AI_A(indexAddrOffAddrzh(r,x,y)); break;
2459 case i_readAddrOffAddr: OP_AI_A(indexAddrOffAddrzh(r,x,y)); break;
2460 case i_writeAddrOffAddr: OP_AIA_(writeAddrOffAddrzh(x,y,z)); break;
2462 case i_indexFloatOffAddr: OP_AI_F(indexFloatOffAddrzh(r,x,y)); break;
2463 case i_readFloatOffAddr: OP_AI_F(indexFloatOffAddrzh(r,x,y)); break;
2464 case i_writeFloatOffAddr: OP_AIF_(writeFloatOffAddrzh(x,y,z)); break;
2466 case i_indexDoubleOffAddr: OP_AI_D(indexDoubleOffAddrzh(r,x,y)); break;
2467 case i_readDoubleOffAddr: OP_AI_D(indexDoubleOffAddrzh(r,x,y)); break;
2468 case i_writeDoubleOffAddr: OP_AID_(writeDoubleOffAddrzh(x,y,z)); break;
2470 case i_indexStableOffAddr: OP_AI_s(indexStablePtrOffAddrzh(r,x,y)); break;
2471 case i_readStableOffAddr: OP_AI_s(indexStablePtrOffAddrzh(r,x,y)); break;
2472 case i_writeStableOffAddr: OP_AIs_(writeStablePtrOffAddrzh(x,y,z)); break;
2474 case i_compareInteger:
2476 B* x = IntegerInsideByteArray(PopPtr());
2477 B* y = IntegerInsideByteArray(PopPtr());
2478 StgInt r = do_cmp(x,y);
2479 PushTaggedInt(r<0 ? -1 : (r>0 ? 1 : 0));
2482 case i_negateInteger: OP_Z_Z(neg); break;
2483 case i_plusInteger: OP_ZZ_Z(add); break;
2484 case i_minusInteger: OP_ZZ_Z(sub); break;
2485 case i_timesInteger: OP_ZZ_Z(mul); break;
2486 case i_quotRemInteger:
2488 B* x = IntegerInsideByteArray(PopPtr());
2489 B* y = IntegerInsideByteArray(PopPtr());
2490 int n = size_qrm(x,y);
2491 StgPtr q = CreateByteArrayToHoldInteger(n);
2492 StgPtr r = CreateByteArrayToHoldInteger(n);
2493 if (do_getsign(y)==0)
2494 return (raiseDiv0("quotRemInteger"));
2495 do_qrm(x,y,n,IntegerInsideByteArray(q),
2496 IntegerInsideByteArray(r));
2497 SloppifyIntegerEnd(q);
2498 SloppifyIntegerEnd(r);
2503 case i_intToInteger:
2505 int n = size_fromInt();
2506 StgPtr p = CreateByteArrayToHoldInteger(n);
2507 do_fromInt( PopTaggedInt(), n, IntegerInsideByteArray(p));
2511 case i_wordToInteger:
2513 int n = size_fromWord();
2514 StgPtr p = CreateByteArrayToHoldInteger(n);
2515 do_fromWord( PopTaggedWord(), n, IntegerInsideByteArray(p));
2519 case i_integerToInt: PushTaggedInt(do_toInt(
2520 IntegerInsideByteArray(PopPtr())
2524 case i_integerToWord: PushTaggedWord(do_toWord(
2525 IntegerInsideByteArray(PopPtr())
2529 case i_integerToFloat: PushTaggedFloat(do_toFloat(
2530 IntegerInsideByteArray(PopPtr())
2534 case i_integerToDouble: PushTaggedDouble(do_toDouble(
2535 IntegerInsideByteArray(PopPtr())
2539 case i_gtFloat: OP_FF_B(x>y); break;
2540 case i_geFloat: OP_FF_B(x>=y); break;
2541 case i_eqFloat: OP_FF_B(x==y); break;
2542 case i_neFloat: OP_FF_B(x!=y); break;
2543 case i_ltFloat: OP_FF_B(x<y); break;
2544 case i_leFloat: OP_FF_B(x<=y); break;
2545 case i_minFloat: OP__F(FLT_MIN); break;
2546 case i_maxFloat: OP__F(FLT_MAX); break;
2547 case i_radixFloat: OP__I(FLT_RADIX); break;
2548 case i_digitsFloat: OP__I(FLT_MANT_DIG); break;
2549 case i_minExpFloat: OP__I(FLT_MIN_EXP); break;
2550 case i_maxExpFloat: OP__I(FLT_MAX_EXP); break;
2551 case i_plusFloat: OP_FF_F(x+y); break;
2552 case i_minusFloat: OP_FF_F(x-y); break;
2553 case i_timesFloat: OP_FF_F(x*y); break;
2556 StgFloat x = PopTaggedFloat();
2557 StgFloat y = PopTaggedFloat();
2558 PushTaggedFloat(x/y);
2561 case i_negateFloat: OP_F_F(-x); break;
2562 case i_floatToInt: OP_F_I(x); break;
2563 case i_intToFloat: OP_I_F(x); break;
2564 case i_expFloat: OP_F_F(exp(x)); break;
2565 case i_logFloat: OP_F_F(log(x)); break;
2566 case i_sqrtFloat: OP_F_F(sqrt(x)); break;
2567 case i_sinFloat: OP_F_F(sin(x)); break;
2568 case i_cosFloat: OP_F_F(cos(x)); break;
2569 case i_tanFloat: OP_F_F(tan(x)); break;
2570 case i_asinFloat: OP_F_F(asin(x)); break;
2571 case i_acosFloat: OP_F_F(acos(x)); break;
2572 case i_atanFloat: OP_F_F(atan(x)); break;
2573 case i_sinhFloat: OP_F_F(sinh(x)); break;
2574 case i_coshFloat: OP_F_F(cosh(x)); break;
2575 case i_tanhFloat: OP_F_F(tanh(x)); break;
2576 case i_powerFloat: OP_FF_F(pow(x,y)); break;
2578 case i_encodeFloatZ:
2580 StgPtr sig = PopPtr();
2581 StgInt exp = PopTaggedInt();
2583 B__encodeFloat(IntegerInsideByteArray(sig), exp)
2587 case i_decodeFloatZ:
2589 StgFloat f = PopTaggedFloat();
2590 StgPtr sig = CreateByteArrayToHoldInteger(size_fltmantissa());
2592 B__decodeFloat(IntegerInsideByteArray(sig), &exp, f);
2598 case i_isNaNFloat: OP_F_B(isFloatNaN(x)); break;
2599 case i_isInfiniteFloat: OP_F_B(isFloatInfinite(x)); break;
2600 case i_isNegativeZeroFloat: OP_F_B(isFloatNegativeZero(x)); break;
2601 case i_isDenormalizedFloat: OP_F_B(isFloatDenormalized(x)); break;
2602 case i_gtDouble: OP_DD_B(x>y); break;
2603 case i_geDouble: OP_DD_B(x>=y); break;
2604 case i_eqDouble: OP_DD_B(x==y); break;
2605 case i_neDouble: OP_DD_B(x!=y); break;
2606 case i_ltDouble: OP_DD_B(x<y); break;
2607 case i_leDouble: OP_DD_B(x<=y) break;
2608 case i_minDouble: OP__D(DBL_MIN); break;
2609 case i_maxDouble: OP__D(DBL_MAX); break;
2610 case i_radixDouble: OP__I(FLT_RADIX); break;
2611 case i_digitsDouble: OP__I(DBL_MANT_DIG); break;
2612 case i_minExpDouble: OP__I(DBL_MIN_EXP); break;
2613 case i_maxExpDouble: OP__I(DBL_MAX_EXP); break;
2614 case i_plusDouble: OP_DD_D(x+y); break;
2615 case i_minusDouble: OP_DD_D(x-y); break;
2616 case i_timesDouble: OP_DD_D(x*y); break;
2617 case i_divideDouble:
2619 StgDouble x = PopTaggedDouble();
2620 StgDouble y = PopTaggedDouble();
2621 PushTaggedDouble(x/y);
2624 case i_negateDouble: OP_D_D(-x); break;
2625 case i_doubleToInt: OP_D_I(x); break;
2626 case i_intToDouble: OP_I_D(x); break;
2627 case i_doubleToFloat: OP_D_F(x); break;
2628 case i_floatToDouble: OP_F_F(x); break;
2629 case i_expDouble: OP_D_D(exp(x)); break;
2630 case i_logDouble: OP_D_D(log(x)); break;
2631 case i_sqrtDouble: OP_D_D(sqrt(x)); break;
2632 case i_sinDouble: OP_D_D(sin(x)); break;
2633 case i_cosDouble: OP_D_D(cos(x)); break;
2634 case i_tanDouble: OP_D_D(tan(x)); break;
2635 case i_asinDouble: OP_D_D(asin(x)); break;
2636 case i_acosDouble: OP_D_D(acos(x)); break;
2637 case i_atanDouble: OP_D_D(atan(x)); break;
2638 case i_sinhDouble: OP_D_D(sinh(x)); break;
2639 case i_coshDouble: OP_D_D(cosh(x)); break;
2640 case i_tanhDouble: OP_D_D(tanh(x)); break;
2641 case i_powerDouble: OP_DD_D(pow(x,y)); break;
2643 case i_encodeDoubleZ:
2645 StgPtr sig = PopPtr();
2646 StgInt exp = PopTaggedInt();
2648 B__encodeDouble(IntegerInsideByteArray(sig), exp)
2652 case i_decodeDoubleZ:
2654 StgDouble d = PopTaggedDouble();
2655 StgPtr sig = CreateByteArrayToHoldInteger(size_dblmantissa());
2657 B__decodeDouble(IntegerInsideByteArray(sig), &exp, d);
2663 case i_isNaNDouble: OP_D_B(isDoubleNaN(x)); break;
2664 case i_isInfiniteDouble: OP_D_B(isDoubleInfinite(x)); break;
2665 case i_isNegativeZeroDouble: OP_D_B(isDoubleNegativeZero(x)); break;
2666 case i_isDenormalizedDouble: OP_D_B(isDoubleDenormalized(x)); break;
2667 case i_isIEEEDouble:
2669 PushTaggedBool(rtsTrue);
2673 barf("Unrecognised primop1");
2680 /* For normal cases, return NULL and leave *return2 unchanged.
2681 To return the address of the next thing to enter,
2682 return the address of it and leave *return2 unchanged.
2683 To return a StgThreadReturnCode to the scheduler,
2684 set *return2 to it and return a non-NULL value.
2685 To cause a context switch, set context_switch (its a global),
2686 and optionally set hugsBlock to your rational.
2688 static void* enterBCO_primop2 ( int primop2code,
2689 int* /*StgThreadReturnCode* */ return2,
2692 HugsBlock *hugsBlock )
2695 /* A small concession: we need to allow ccalls,
2696 even in combined mode.
2698 if (primop2code != i_ccall_ccall_IO &&
2699 primop2code != i_ccall_stdcall_IO)
2700 barf("enterBCO_primop2 in combined mode");
2703 switch (primop2code) {
2704 case i_raise: /* raise#{err} */
2706 StgClosure* err = PopCPtr();
2707 return (raiseAnError(err));
2712 StgClosure* init = PopCPtr();
2714 = stgCast(StgMutVar*,allocate(sizeofW(StgMutVar)));
2715 SET_HDR(mv,&MUT_VAR_info,CCCS);
2717 PushPtr(stgCast(StgPtr,mv));
2722 StgMutVar* mv = stgCast(StgMutVar*,PopPtr());
2728 StgMutVar* mv = stgCast(StgMutVar*,PopPtr());
2729 StgClosure* value = PopCPtr();
2735 nat n = PopTaggedInt(); /* or Word?? */
2736 StgClosure* init = PopCPtr();
2737 StgWord size = sizeofW(StgMutArrPtrs) + n;
2740 = stgCast(StgMutArrPtrs*,allocate(size));
2741 SET_HDR(arr,&MUT_ARR_PTRS_info,CCCS);
2743 for (i = 0; i < n; ++i) {
2744 arr->payload[i] = init;
2746 PushPtr(stgCast(StgPtr,arr));
2752 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
2753 nat i = PopTaggedInt(); /* or Word?? */
2754 StgWord n = arr->ptrs;
2756 return (raiseIndex("{index,read}Array"));
2758 PushCPtr(arr->payload[i]);
2763 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
2764 nat i = PopTaggedInt(); /* or Word? */
2765 StgClosure* v = PopCPtr();
2766 StgWord n = arr->ptrs;
2768 return (raiseIndex("{index,read}Array"));
2770 arr->payload[i] = v;
2774 case i_sizeMutableArray:
2776 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
2777 PushTaggedInt(arr->ptrs);
2780 case i_unsafeFreezeArray:
2782 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
2783 SET_INFO(arr,&MUT_ARR_PTRS_FROZEN_info);
2784 PushPtr(stgCast(StgPtr,arr));
2787 case i_unsafeFreezeByteArray:
2789 /* Delightfully simple :-) */
2793 case i_sameMutableArray:
2794 case i_sameMutableByteArray:
2796 StgPtr x = PopPtr();
2797 StgPtr y = PopPtr();
2798 PushTaggedBool(x==y);
2802 case i_newByteArray:
2804 nat n = PopTaggedInt(); /* or Word?? */
2805 StgInt words = (n+sizeof(W_)-1)/sizeof(W_);
2806 StgWord size = sizeofW(StgArrWords) + words;
2807 StgArrWords* arr = stgCast(StgArrWords*,allocate(size));
2808 SET_HDR(arr,&ARR_WORDS_info,CCCS);
2812 for (i = 0; i < n; ++i) {
2813 arr->payload[i] = 0xdeadbeef;
2816 PushPtr(stgCast(StgPtr,arr));
2820 /* Most of these generate alignment warnings on Sparcs and similar architectures.
2821 * These are harmless and are caused by the cast to C* in BYTE_ARR_CTS.
2823 case i_indexCharArray:
2824 OP_mI_ty(Char,"indexCharArray", indexCharArrayzh(r,x,i)); break;
2825 case i_readCharArray:
2826 OP_mI_ty(Char,"readCharArray", readCharArrayzh(r,x,i)); break;
2827 case i_writeCharArray:
2828 OP_mIty_(Char,"writeCharArray", writeCharArrayzh(x,i,z)); break;
2830 case i_indexIntArray:
2831 OP_mI_ty(Int,"indexIntArray", indexIntArrayzh(r,x,i)); break;
2832 case i_readIntArray:
2833 OP_mI_ty(Int,"readIntArray", readIntArrayzh(r,x,i)); break;
2834 case i_writeIntArray:
2835 OP_mIty_(Int,"writeIntArray", writeIntArrayzh(x,i,z)); break;
2837 case i_indexAddrArray:
2838 OP_mI_ty(Addr,"indexAddrArray", indexAddrArrayzh(r,x,i)); break;
2839 case i_readAddrArray:
2840 OP_mI_ty(Addr,"readAddrArray", readAddrArrayzh(r,x,i)); break;
2841 case i_writeAddrArray:
2842 OP_mIty_(Addr,"writeAddrArray", writeAddrArrayzh(x,i,z)); break;
2844 case i_indexFloatArray:
2845 OP_mI_ty(Float,"indexFloatArray", indexFloatArrayzh(r,x,i)); break;
2846 case i_readFloatArray:
2847 OP_mI_ty(Float,"readFloatArray", readFloatArrayzh(r,x,i)); break;
2848 case i_writeFloatArray:
2849 OP_mIty_(Float,"writeFloatArray", writeFloatArrayzh(x,i,z)); break;
2851 case i_indexDoubleArray:
2852 OP_mI_ty(Double,"indexDoubleArray", indexDoubleArrayzh(r,x,i)); break;
2853 case i_readDoubleArray:
2854 OP_mI_ty(Double,"readDoubleArray", readDoubleArrayzh(r,x,i)); break;
2855 case i_writeDoubleArray:
2856 OP_mIty_(Double,"writeDoubleArray", writeDoubleArrayzh(x,i,z)); break;
2859 #ifdef PROVIDE_STABLE
2860 case i_indexStableArray:
2861 OP_mI_ty(StablePtr,"indexStableArray", indexStablePtrArrayzh(r,x,i)); break;
2862 case i_readStableArray:
2863 OP_mI_ty(StablePtr,"readStableArray", readStablePtrArrayzh(r,x,i)); break;
2864 case i_writeStableArray:
2865 OP_mIty_(StablePtr,"writeStableArray", writeStablePtrArrayzh(x,i,z)); break;
2871 #ifdef PROVIDE_COERCE
2872 case i_unsafeCoerce:
2874 /* Another nullop */
2878 #ifdef PROVIDE_PTREQUALITY
2879 case i_reallyUnsafePtrEquality:
2880 { /* identical to i_sameRef */
2881 StgPtr x = PopPtr();
2882 StgPtr y = PopPtr();
2883 PushTaggedBool(x==y);
2887 #ifdef PROVIDE_FOREIGN
2888 /* ForeignObj# operations */
2889 case i_makeForeignObj:
2891 StgForeignObj *result
2892 = stgCast(StgForeignObj*,allocate(sizeofW(StgForeignObj)));
2893 SET_HDR(result,&FOREIGN_info,CCCS);
2894 result -> data = PopTaggedAddr();
2895 PushPtr(stgCast(StgPtr,result));
2898 #endif /* PROVIDE_FOREIGN */
2903 = stgCast(StgWeak*,allocate(sizeofW(StgWeak)));
2904 SET_HDR(w, &WEAK_info, CCCS);
2906 w->value = PopCPtr();
2907 w->finaliser = PopCPtr();
2908 w->link = weak_ptr_list;
2910 IF_DEBUG(weak, fprintf(stderr,"New weak pointer at %p\n",w));
2911 PushPtr(stgCast(StgPtr,w));
2916 StgWeak *w = stgCast(StgWeak*,PopPtr());
2917 if (w->header.info == &WEAK_info) {
2918 PushCPtr(w->value); /* last result */
2919 PushTaggedInt(1); /* first result */
2921 PushPtr(stgCast(StgPtr,w));
2922 /* ToDo: error thunk would be better */
2927 #endif /* PROVIDE_WEAK */
2929 case i_makeStablePtr:
2931 StgPtr p = PopPtr();
2932 StgStablePtr sp = getStablePtr ( p );
2933 PushTaggedStablePtr(sp);
2936 case i_deRefStablePtr:
2939 StgStablePtr sp = PopTaggedStablePtr();
2940 p = deRefStablePtr(sp);
2944 case i_freeStablePtr:
2946 StgStablePtr sp = PopTaggedStablePtr();
2951 case i_createAdjThunkARCH:
2953 StgStablePtr stableptr = PopTaggedStablePtr();
2954 StgAddr typestr = PopTaggedAddr();
2955 StgChar callconv = PopTaggedChar();
2956 StgAddr adj_thunk = createAdjThunk(stableptr,typestr,callconv);
2957 PushTaggedAddr(adj_thunk);
2963 StgInt n = prog_argc;
2969 StgInt n = PopTaggedInt();
2970 StgAddr a = (StgAddr)prog_argv[n];
2977 StgMVar *mvar = stgCast(StgMVar*,allocate(sizeofW(StgMVar)));
2978 SET_INFO(mvar,&EMPTY_MVAR_info);
2979 mvar->head = mvar->tail = (StgTSO *)&END_TSO_QUEUE_closure;
2980 mvar->value = stgCast(StgClosure*,&END_TSO_QUEUE_closure);
2981 PushPtr(stgCast(StgPtr,mvar));
2986 StgMVar *mvar = (StgMVar*)PopCPtr();
2987 if (GET_INFO(mvar) == &EMPTY_MVAR_info) {
2989 /* The MVar is empty. Attach ourselves to the TSO's
2992 if (mvar->head == (StgTSO *)&END_TSO_QUEUE_closure) {
2993 mvar->head = cap->rCurrentTSO;
2995 mvar->tail->link = cap->rCurrentTSO;
2997 cap->rCurrentTSO->link = (StgTSO *)&END_TSO_QUEUE_closure;
2998 cap->rCurrentTSO->why_blocked = BlockedOnMVar;
2999 cap->rCurrentTSO->block_info.closure = (StgClosure *)mvar;
3000 mvar->tail = cap->rCurrentTSO;
3002 /* At this point, the top-of-stack holds the MVar,
3003 and underneath is the world token (). So the
3004 stack is in the same state as when primTakeMVar
3005 was entered (primTakeMVar is handwritten bytecode).
3006 Push obj, which is this BCO, and return to the
3007 scheduler. When the MVar is filled, the scheduler
3008 will re-enter primTakeMVar, with the args still on
3009 the top of the stack.
3011 PushCPtr((StgClosure*)(*bco));
3012 *return2 = ThreadBlocked;
3013 return (void*)(1+(char*)(NULL));
3016 PushCPtr(mvar->value);
3017 mvar->value = (StgClosure *)&END_TSO_QUEUE_closure;
3018 SET_INFO(mvar,&EMPTY_MVAR_info);
3024 StgMVar* mvar = stgCast(StgMVar*,PopPtr());
3025 StgClosure* value = PopCPtr();
3026 if (GET_INFO(mvar) == &FULL_MVAR_info) {
3027 return (makeErrorCall("putMVar {full MVar}"));
3029 /* wake up the first thread on the
3030 * queue, it will continue with the
3031 * takeMVar operation and mark the
3034 mvar->value = value;
3036 if (mvar->head != (StgTSO *)&END_TSO_QUEUE_closure) {
3037 ASSERT(mvar->head->why_blocked == BlockedOnMVar);
3038 mvar->head = unblockOne(mvar->head);
3039 if (mvar->head == (StgTSO *)&END_TSO_QUEUE_closure) {
3040 mvar->tail = (StgTSO *)&END_TSO_QUEUE_closure;
3044 /* unlocks the MVar in the SMP case */
3045 SET_INFO(mvar,&FULL_MVAR_info);
3047 /* yield for better communication performance */
3053 { /* identical to i_sameRef */
3054 StgMVar* x = (StgMVar*)PopPtr();
3055 StgMVar* y = (StgMVar*)PopPtr();
3056 PushTaggedBool(x==y);
3059 #ifdef PROVIDE_CONCURRENT
3062 StgClosure* closure;
3065 closure = PopCPtr();
3066 tso = createGenThread (RtsFlags.GcFlags.initialStkSize,closure);
3068 scheduleThread(tso);
3070 /* Later: Change to use tso as the ThreadId */
3071 PushTaggedWord(tid);
3077 StgWord n = PopTaggedWord();
3081 // Map from ThreadId to Thread Structure */
3082 for (t = all_threads; t != END_TSO_QUEUE; t = t->global_link) {
3091 while (tso->what_next == ThreadRelocated) {
3096 if (tso == cap->rCurrentTSO) { /* suicide */
3097 *return2 = ThreadFinished;
3098 return (void*)(1+(NULL));
3102 case i_raiseInThread:
3103 ASSERT(0); /* not (yet) supported */
3106 StgInt n = PopTaggedInt();
3108 hugsBlock->reason = BlockedOnDelay;
3109 hugsBlock->delay = n;
3114 StgInt n = PopTaggedInt();
3116 hugsBlock->reason = BlockedOnRead;
3117 hugsBlock->delay = n;
3122 StgInt n = PopTaggedInt();
3124 hugsBlock->reason = BlockedOnWrite;
3125 hugsBlock->delay = n;
3130 /* The definition of yield include an enter right after
3131 * the primYield, at which time context_switch is tested.
3138 StgWord tid = cap->rCurrentTSO->id;
3139 PushTaggedWord(tid);
3142 case i_cmpThreadIds:
3144 StgWord tid1 = PopTaggedWord();
3145 StgWord tid2 = PopTaggedWord();
3146 if (tid1 < tid2) PushTaggedInt(-1);
3147 else if (tid1 > tid2) PushTaggedInt(1);
3148 else PushTaggedInt(0);
3151 #endif /* PROVIDE_CONCURRENT */
3153 case i_ccall_ccall_Id:
3154 case i_ccall_ccall_IO:
3155 case i_ccall_stdcall_Id:
3156 case i_ccall_stdcall_IO:
3159 CFunDescriptor* descriptor;
3160 void (*funPtr)(void);
3162 descriptor = PopTaggedAddr();
3163 funPtr = PopTaggedAddr();
3164 cc = (primop2code == i_ccall_stdcall_Id ||
3165 primop2code == i_ccall_stdcall_IO)
3167 r = ccall(descriptor,funPtr,bco,cc,cap);
3170 return makeErrorCall(
3171 "unhandled type or too many args/results in ccall");
3173 barf("ccall not configured correctly for this platform");
3174 barf("unknown return code from ccall");
3177 barf("Unrecognised primop2");
3183 /* -----------------------------------------------------------------------------
3184 * ccall support code:
3185 * marshall moves args from C stack to Haskell stack
3186 * unmarshall moves args from Haskell stack to C stack
3187 * argSize calculates how much gSpace you need on the C stack
3188 * ---------------------------------------------------------------------------*/
3190 /* Pop arguments off the C stack and Push them onto the Hugs stack.
3191 * Used when preparing for C calling Haskell or in regSponse to
3192 * Haskell calling C.
3194 nat marshall(char arg_ty, void* arg)
3198 PushTaggedInt(*((int*)arg));
3199 return ARG_SIZE(INT_TAG);
3202 PushTaggedInteger(*((mpz_ptr*)arg));
3203 return ARG_SIZE(INTEGER_TAG);
3206 PushTaggedWord(*((unsigned int*)arg));
3207 return ARG_SIZE(WORD_TAG);
3209 PushTaggedChar(*((char*)arg));
3210 return ARG_SIZE(CHAR_TAG);
3212 PushTaggedFloat(*((float*)arg));
3213 return ARG_SIZE(FLOAT_TAG);
3215 PushTaggedDouble(*((double*)arg));
3216 return ARG_SIZE(DOUBLE_TAG);
3218 PushTaggedAddr(*((void**)arg));
3219 return ARG_SIZE(ADDR_TAG);
3221 PushTaggedStablePtr(*((StgStablePtr*)arg));
3222 return ARG_SIZE(STABLE_TAG);
3223 #ifdef PROVIDE_FOREIGN
3225 /* Not allowed in this direction - you have to
3226 * call makeForeignPtr explicitly
3228 barf("marshall: ForeignPtr#\n");
3233 /* Not allowed in this direction */
3234 barf("marshall: [Mutable]ByteArray#\n");
3237 barf("marshall: unrecognised arg type %d\n",arg_ty);
3242 /* Pop arguments off the Hugs stack and Push them onto the C stack.
3243 * Used when preparing for Haskell calling C or in regSponse to
3244 * C calling Haskell.
3246 nat unmarshall(char res_ty, void* res)
3250 *((int*)res) = PopTaggedInt();
3251 return ARG_SIZE(INT_TAG);
3254 *((mpz_ptr*)res) = PopTaggedInteger();
3255 return ARG_SIZE(INTEGER_TAG);
3258 *((unsigned int*)res) = PopTaggedWord();
3259 return ARG_SIZE(WORD_TAG);
3261 *((int*)res) = PopTaggedChar();
3262 return ARG_SIZE(CHAR_TAG);
3264 *((float*)res) = PopTaggedFloat();
3265 return ARG_SIZE(FLOAT_TAG);
3267 *((double*)res) = PopTaggedDouble();
3268 return ARG_SIZE(DOUBLE_TAG);
3270 *((void**)res) = PopTaggedAddr();
3271 return ARG_SIZE(ADDR_TAG);
3273 *((StgStablePtr*)res) = PopTaggedStablePtr();
3274 return ARG_SIZE(STABLE_TAG);
3275 #ifdef PROVIDE_FOREIGN
3278 StgForeignObj *result = stgCast(StgForeignObj*,PopPtr());
3279 *((void**)res) = result->data;
3280 return sizeofW(StgPtr);
3286 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
3287 *((void**)res) = stgCast(void*,&(arr->payload));
3288 return sizeofW(StgPtr);
3291 barf("unmarshall: unrecognised result type %d\n",res_ty);
3295 nat argSize( const char* ks )
3298 for( ; *ks != '\0'; ++ks) {
3301 sz += sizeof(StgWord) * ARG_SIZE(INT_TAG);
3305 sz += sizeof(StgWord) * ARG_SIZE(INTEGER_TAG);
3309 sz += sizeof(StgWord) * ARG_SIZE(WORD_TAG);
3312 sz += sizeof(StgWord) * ARG_SIZE(CHAR_TAG);
3315 sz += sizeof(StgWord) * ARG_SIZE(FLOAT_TAG);
3318 sz += sizeof(StgWord) * ARG_SIZE(DOUBLE_TAG);
3321 sz += sizeof(StgWord) * ARG_SIZE(ADDR_TAG);
3324 sz += sizeof(StgWord) * ARG_SIZE(STABLE_TAG);
3326 #ifdef PROVIDE_FOREIGN
3331 sz += sizeof(StgPtr);
3334 barf("argSize: unrecognised result type %d\n",*ks);
3342 /* -----------------------------------------------------------------------------
3343 * encode/decode Float/Double code for standalone Hugs
3344 * Code based on the HBC code (lib/fltcode.c) and more recently GHC
3345 * (ghc/rts/StgPrimFloat.c)
3346 * ---------------------------------------------------------------------------*/
3348 #if IEEE_FLOATING_POINT
3349 #define MY_DMINEXP ((DBL_MIN_EXP) - (DBL_MANT_DIG) - 1)
3350 /* DMINEXP is defined in values.h on Linux (for example) */
3351 #define DHIGHBIT 0x00100000
3352 #define DMSBIT 0x80000000
3354 #define MY_FMINEXP ((FLT_MIN_EXP) - (FLT_MANT_DIG) - 1)
3355 #define FHIGHBIT 0x00800000
3356 #define FMSBIT 0x80000000
3358 #error The following code doesnt work in a non-IEEE FP environment
3361 #ifdef WORDS_BIGENDIAN
3370 StgDouble B__encodeDouble (B* s, I_ e) /* result = s * 2^e */
3375 /* Convert a B to a double; knows a lot about internal rep! */
3376 for(r = 0.0, i = s->used-1; i >= 0; i--)
3377 r = (r * B_BASE_FLT) + s->stuff[i];
3379 /* Now raise to the exponent */
3380 if ( r != 0.0 ) /* Lennart suggests this avoids a bug in MIPS's ldexp */
3383 /* handle the sign */
3384 if (s->sign < 0) r = -r;
3391 #if ! FLOATS_AS_DOUBLES
3392 StgFloat B__encodeFloat (B* s, I_ e) /* result = s * 2^e */
3397 /* Convert a B to a float; knows a lot about internal rep! */
3398 for(r = 0.0, i = s->used-1; i >= 0; i--)
3399 r = (r * B_BASE_FLT) + s->stuff[i];
3401 /* Now raise to the exponent */
3402 if ( r != 0.0 ) /* Lennart suggests this avoids a bug in MIPS's ldexp */
3405 /* handle the sign */
3406 if (s->sign < 0) r = -r;
3410 #endif /* FLOATS_AS_DOUBLES */
3414 /* This only supports IEEE floating point */
3415 void B__decodeDouble (B* man, I_* exp, StgDouble dbl)
3417 /* Do some bit fiddling on IEEE */
3418 nat low, high; /* assuming 32 bit ints */
3420 union { double d; int i[2]; } u; /* assuming 32 bit ints, 64 bit double */
3422 u.d = dbl; /* grab chunks of the double */
3426 ASSERT(B_BASE == 256);
3428 /* Assume that the supplied B is the right size */
3431 if (low == 0 && (high & ~DMSBIT) == 0) {
3432 man->sign = man->used = 0;
3437 iexp = ((high >> 20) & 0x7ff) + MY_DMINEXP;
3441 if (iexp != MY_DMINEXP) /* don't add hidden bit to denorms */
3445 /* A denorm, normalize the mantissa */
3446 while (! (high & DHIGHBIT)) {
3456 man->stuff[7] = (((W_)high) >> 24) & 0xff;
3457 man->stuff[6] = (((W_)high) >> 16) & 0xff;
3458 man->stuff[5] = (((W_)high) >> 8) & 0xff;
3459 man->stuff[4] = (((W_)high) ) & 0xff;
3461 man->stuff[3] = (((W_)low) >> 24) & 0xff;
3462 man->stuff[2] = (((W_)low) >> 16) & 0xff;
3463 man->stuff[1] = (((W_)low) >> 8) & 0xff;
3464 man->stuff[0] = (((W_)low) ) & 0xff;
3466 if (sign < 0) man->sign = -1;
3468 do_renormalise(man);
3472 #if ! FLOATS_AS_DOUBLES
3473 void B__decodeFloat (B* man, I_* exp, StgFloat flt)
3475 /* Do some bit fiddling on IEEE */
3476 int high, sign; /* assuming 32 bit ints */
3477 union { float f; int i; } u; /* assuming 32 bit float and int */
3479 u.f = flt; /* grab the float */
3482 ASSERT(B_BASE == 256);
3484 /* Assume that the supplied B is the right size */
3487 if ((high & ~FMSBIT) == 0) {
3488 man->sign = man->used = 0;
3493 *exp = ((high >> 23) & 0xff) + MY_FMINEXP;
3497 if (*exp != MY_FMINEXP) /* don't add hidden bit to denorms */
3501 /* A denorm, normalize the mantissa */
3502 while (! (high & FHIGHBIT)) {
3507 man->stuff[3] = (((W_)high) >> 24) & 0xff;
3508 man->stuff[2] = (((W_)high) >> 16) & 0xff;
3509 man->stuff[1] = (((W_)high) >> 8) & 0xff;
3510 man->stuff[0] = (((W_)high) ) & 0xff;
3512 if (sign < 0) man->sign = -1;
3514 do_renormalise(man);
3517 #endif /* FLOATS_AS_DOUBLES */
3519 #endif /* INTERPRETER */