2 /* -----------------------------------------------------------------------------
5 * Copyright (c) 1994-1998.
7 * $RCSfile: Evaluator.c,v $
9 * $Date: 2000/10/09 11:20:16 $
10 * ---------------------------------------------------------------------------*/
20 #include "SchedAPI.h" /* for createGenThread */
21 #include "Schedule.h" /* for context_switch */
22 #include "Bytecodes.h"
23 #include "Assembler.h" /* for CFun stuff */
24 #include "ForeignCall.h"
25 #include "PrimOps.h" /* for __{encode,decode}{Float,Double} */
28 #include "Evaluator.h"
29 #include "sainteger.h"
33 #include "Disassembler.h"
38 #include <math.h> /* These are for primops */
39 #include <limits.h> /* These are for primops */
40 #include <float.h> /* These are for primops */
42 #include <ieee754.h> /* These are for primops */
46 /* Allegedly useful macro, taken from ClosureMacros.h */
47 #define payloadWord( c, i ) (*stgCast(StgWord*, ((c)->payload+(i))))
48 #define payloadPtr( c, i ) (*stgCast(StgPtr*, ((c)->payload+(i))))
50 /* An incredibly useful abbreviation.
51 * Interestingly, there are some uses of END_TSO_QUEUE_closure that
52 * can't use it because they use the closure at type StgClosure* or
53 * even StgPtr*. I suspect they should be changed. -- ADR
55 #define EndTSOQueue stgCast(StgTSO*,(void*)&END_TSO_QUEUE_closure)
57 /* These macros are rather delicate - read a good ANSI C book carefully
61 #define mycat(x,y) x##y
62 #define mycat2(x,y) mycat(x,y)
63 #define mycat3(x,y,z) mycat2(x,mycat2(y,z))
65 #if defined(__GNUC__) && !defined(DEBUG)
66 #define USE_GCC_LABELS 1
68 #define USE_GCC_LABELS 0
71 /* Make it possible for the evaluator to get hold of bytecode
72 for a given function by name. Useful but a hack. Sigh.
74 extern void* /* StgClosure* */ getHugs_BCO_cptr_for ( char* s );
75 extern int /* Bool */ combined;
79 /* --------------------------------------------------------------------------
80 * Hugs Hooks - a bit of a hack
81 * ------------------------------------------------------------------------*/
83 void setRtsFlags( int x );
84 void setRtsFlags( int x )
86 unsigned int w = 0x12345678;
87 unsigned char* pw = (unsigned char *)&w;
90 *(int*)(&(RtsFlags.DebugFlags)) = x;
95 w2 |= (w1 && 0xFF); w2 <<= 8; w1 >>= 8;
96 w2 |= (w1 && 0xFF); w2 <<= 8; w1 >>= 8;
97 w2 |= (w1 && 0xFF); w2 <<= 8; w1 >>= 8;
98 w2 |= (w1 && 0xFF); w2 <<= 8; w1 >>= 8;
99 *(int*)(&(RtsFlags.DebugFlags)) = (int)w2;
105 StgTSOBlockReason reason;
110 /* --------------------------------------------------------------------------
111 * Entering-objects and bytecode interpreter part of evaluator
112 * ------------------------------------------------------------------------*/
114 /* The primop (and all other) parts of this evaluator operate upon the
115 machine state which lives in MainRegTable. enter is different:
116 to make its closure- and bytecode-interpreting loops go fast, some of that
117 state is pulled out into local vars (viz, registers, if we are lucky).
118 That means that we need to save(load) the local state at every exit(reentry)
119 into enter. That is, around every procedure call it makes. Blargh!
120 If you modify this code, __be warned__ it will fail in mysterious ways if
121 you fail to preserve this property.
123 Currently the pulled-out state is Sp in xSp, Su in xSu and SpLim in xSpLim.
124 The SSS macros saves the state back in MainRegTable, and LLL loads it from
125 MainRegTable. RETURN(v) does SSS and then returns v; all exits should
126 be via RETURN and not plain return.
128 Since xSp, xSu and xSpLim are local vars in enter, they are not visible
129 in procedures called from enter. To fix this, either (1) turn the
130 procedures into macros, so they get copied inline, or (2) bracket
131 the procedure call with SSS and LLL so that the local and global
132 machine states are synchronised for the duration of the call.
136 /* Forward decls ... */
137 static void* enterBCO_primop1 ( int );
138 static void* enterBCO_primop2 ( int , int* /*StgThreadReturnCode* */,
139 StgBCO**, Capability*, HugsBlock * );
140 static inline void PopUpdateFrame ( StgClosure* obj );
141 static inline void PopCatchFrame ( void );
142 static inline void PopSeqFrame ( void );
143 static inline void PopStopFrame( StgClosure* obj );
144 static inline void PushTaggedRealWorld( void );
145 /* static inline void PushTaggedInteger ( mpz_ptr ); */
146 static inline StgPtr grabHpUpd( nat size );
147 static inline StgPtr grabHpNonUpd( nat size );
148 static StgClosure* raiseAnError ( StgClosure* exception );
150 static int enterCountI = 0;
152 StgDouble B__encodeDouble (B* s, I_ e);
153 void B__decodeDouble (B* man, I_* exp, StgDouble dbl);
154 #if ! FLOATS_AS_DOUBLES
155 StgFloat B__encodeFloat (B* s, I_ e);
156 void B__decodeFloat (B* man, I_* exp, StgFloat flt);
157 StgPtr CreateByteArrayToHoldInteger ( int );
158 B* IntegerInsideByteArray ( StgPtr );
159 void SloppifyIntegerEnd ( StgPtr );
165 #define gSp MainRegTable.rSp
166 #define gSu MainRegTable.rSu
167 #define gSpLim MainRegTable.rSpLim
170 /* Macros to save/load local state. */
172 #define SSS { tSp=gSp = xSp; tSu=gSu = xSu; tSpLim=gSpLim = xSpLim; }
173 #define LLL { tSp=xSp = gSp; tSu=xSu = gSu; tSpLim=xSpLim = gSpLim; }
175 #define SSS { gSp = xSp; gSu = xSu; gSpLim = xSpLim; }
176 #define LLL { xSp = gSp; xSu = gSu; xSpLim = gSpLim; }
179 #define RETURN(vvv) { \
180 StgThreadReturnCode retVal=(vvv); \
182 cap->rCurrentTSO->sp = gSp; \
183 cap->rCurrentTSO->su = gSu; \
188 /* Macros to operate directly on the pulled-out machine state.
189 These mirror some of the small procedures used in the primop code
190 below, except you have to be careful about side effects,
191 ie xPushPtr(xStackPtr(n)) won't work! It certainly isn't the
192 same as PushPtr(StackPtr(n)). Also note that (1) some of
193 the macros, in particular xPopTagged*, do not make the tag
194 sanity checks that their non-x cousins do, and (2) some of
195 the macros depend critically on the semantics of C comma
196 expressions to work properly.
198 #define xPushPtr(ppp) { xSp--; *xSp=(StgWord)(ppp); }
199 #define xPopPtr() ((StgPtr)(*xSp++))
201 #define xPushCPtr(ppp) { xSp--; *xSp=(StgWord)(ppp); }
202 #define xPopCPtr() ((StgClosure*)(*xSp++))
204 #define xPushWord(ppp) { xSp--; *xSp=(StgWord)(ppp); }
205 #define xPopWord() ((StgWord)(*xSp++))
207 #define xStackPtr(nnn) ((StgPtr)(*(xSp+(nnn))))
208 #define xStackWord(nnn) ((StgWord)(*(xSp+(nnn))))
209 #define xSetStackWord(iii,www) xSp[iii]=(StgWord)(www)
211 #define xPushTag(ttt) { xSp--; *xSp=(StgWord)(ttt); }
212 #define xPopTag(ttt) { StackTag t = (StackTag)(*xSp++); \
215 #define xPushTaggedInt(xxx) { xSp -= sizeofW(StgInt); \
216 *xSp = (xxx); xPushTag(INT_TAG); }
217 #define xTaggedStackInt(iii) ((StgInt)(*(xSp+1+(iii))))
218 #define xPopTaggedInt() ((xSp++,xSp+=sizeofW(StgInt), \
219 (StgInt)(*(xSp-sizeofW(StgInt)))))
221 #define xPushTaggedWord(xxx) { xSp -= sizeofW(StgWord); \
222 *xSp = (xxx); xPushTag(WORD_TAG); }
223 #define xTaggedStackWord(iii) ((StgWord)(*(xSp+1+(iii))))
224 #define xPopTaggedWord() ((xSp++,xSp+=sizeofW(StgWord), \
225 (StgWord)(*(xSp-sizeofW(StgWord)))))
227 #define xPushTaggedAddr(xxx) { xSp -= sizeofW(StgAddr); \
228 *xSp = (StgWord)(xxx); xPushTag(ADDR_TAG); }
229 #define xTaggedStackAddr(iii) ((StgAddr)(*(xSp+1+(iii))))
230 #define xPopTaggedAddr() ((xSp++,xSp+=sizeofW(StgAddr), \
231 (StgAddr)(*(xSp-sizeofW(StgAddr)))))
233 #define xPushTaggedStable(xxx) { xSp -= sizeofW(StgStablePtr); \
234 *xSp = (StgWord)(xxx); xPushTag(STABLE_TAG); }
235 #define xTaggedStackStable(iii) ((StgStablePtr)(*(xSp+1+(iii))))
236 #define xPopTaggedStable() ((xSp++,xSp+=sizeofW(StgStablePtr), \
237 (StgStablePtr)(*(xSp-sizeofW(StgStablePtr)))))
239 #define xPushTaggedChar(xxx) { xSp -= sizeofW(StgChar); \
240 *xSp = (StgWord)(xxx); xPushTag(CHAR_TAG); }
241 #define xTaggedStackChar(iii) ((StgChar)(*(xSp+1+(iii))))
242 #define xPopTaggedChar() ((xSp++,xSp+=sizeofW(StgChar), \
243 (StgChar)(*(xSp-sizeofW(StgChar)))))
245 #define xPushTaggedFloat(xxx) { xSp -= sizeofW(StgFloat); \
246 ASSIGN_FLT(xSp,xxx); xPushTag(FLOAT_TAG); }
247 #define xTaggedStackFloat(iii) PK_FLT(xSp+1+(iii))
248 #define xPopTaggedFloat() ((xSp++,xSp+=sizeofW(StgFloat), \
249 PK_FLT(xSp-sizeofW(StgFloat))))
251 #define xPushTaggedDouble(xxx) { xSp -= sizeofW(StgDouble); \
252 ASSIGN_DBL(xSp,xxx); xPushTag(DOUBLE_TAG); }
253 #define xTaggedStackDouble(iii) PK_DBL(xSp+1+(iii))
254 #define xPopTaggedDouble() ((xSp++,xSp+=sizeofW(StgDouble), \
255 PK_DBL(xSp-sizeofW(StgDouble))))
258 #define xPushUpdateFrame(target, xSp_offset) \
260 StgUpdateFrame *__frame; \
261 __frame = (StgUpdateFrame *)(xSp + (xSp_offset)) - 1; \
262 SET_INFO(__frame, (StgInfoTable *)&upd_frame_info); \
263 __frame->link = xSu; \
264 __frame->updatee = (StgClosure *)(target); \
268 #define xPopUpdateFrame(ooo) \
270 /* NB: doesn't assume that Sp == Su */ \
271 IF_DEBUG(evaluator, \
272 fprintf(stderr, "Updating "); \
273 printPtr(stgCast(StgPtr,xSu->updatee)); \
274 fprintf(stderr, " with "); \
276 fprintf(stderr,"xSp = %p\txSu = %p\n\n", xSp, xSu); \
278 UPD_IND(xSu->updatee,ooo); \
279 xSp = stgCast(StgStackPtr,xSu) + sizeofW(StgUpdateFrame); \
285 /* Instruction stream macros */
286 #define BCO_INSTR_8 *bciPtr++
287 #define BCO_INSTR_16 ((bciPtr += 2, (*(bciPtr-2) << 8) + *(bciPtr-1)))
288 #define PC (bciPtr - &(bcoInstr(bco,0)))
291 /* State on entry to enter():
292 * - current thread is in cap->rCurrentTSO;
293 * - allocation area is in cap->rCurrentNursery & cap->rNursery
296 StgThreadReturnCode enter( Capability* cap, StgClosure* obj0 )
298 /* use of register here is primarily to make it clear to compilers
299 that these entities are non-aliasable.
301 register StgPtr xSp; /* local state -- stack pointer */
302 register StgUpdateFrame* xSu; /* local state -- frame pointer */
303 register StgPtr xSpLim; /* local state -- stack lim pointer */
304 register StgClosure* obj; /* object currently under evaluation */
305 char eCount; /* enter counter, for context switching */
308 HugsBlock hugsBlock = { NotBlocked, 0 };
312 StgPtr tSp; StgUpdateFrame* tSu; StgPtr tSpLim;
315 gSp = cap->rCurrentTSO->sp;
316 gSu = cap->rCurrentTSO->su;
317 gSpLim = cap->rCurrentTSO->stack + RESERVED_STACK_WORDS;
320 /* use the t values to check that Su/Sp/SpLim do not change unexpectedly */
321 tSp = gSp; tSu = gSu; tSpLim = gSpLim;
327 /* Load the local state from global state, and Party On, Dudes! */
328 /* From here onwards, we operate with the local state and
329 save/reload it as necessary.
340 ASSERT(gSpLim == tSpLim);
344 ASSERT(xSpLim <= xSp && xSp <= stgCast(StgPtr,xSu));
346 "\n---------------------------------------------------------------\n");
347 fprintf(stderr,"(%d) Entering: ",enterCountI); printObj(obj);
348 fprintf(stderr,"xSp = %p\txSu = %p\n", xSp, xSu);
349 fprintf(stderr, "\n" );
350 printStack(xSp,cap->rCurrentTSO->stack+cap->rCurrentTSO->stack_size,xSu);
351 fprintf(stderr, "\n\n");
358 ((++eCount) & 0x0F) == 0
363 if (context_switch) {
364 switch(hugsBlock.reason) {
366 xPushCPtr(obj); /* code to restart with */
367 RETURN(ThreadYielding);
369 case BlockedOnDelay: /* fall through */
370 case BlockedOnRead: /* fall through */
371 case BlockedOnWrite: {
372 ASSERT(cap->rCurrentTSO->why_blocked == NotBlocked);
373 cap->rCurrentTSO->why_blocked = BlockedOnDelay;
374 ACQUIRE_LOCK(&sched_mutex);
376 #if defined(HAVE_SETITIMER) /* || defined(mingw32_TARGET_OS) */
377 cap->rCurrentTSO->block_info.delay
378 = hugsBlock.delay + ticks_since_select;
380 cap->rCurrentTSO->block_info.target
381 = hugsBlock.delay + getourtimeofday();
383 APPEND_TO_BLOCKED_QUEUE(cap->rCurrentTSO);
385 RELEASE_LOCK(&sched_mutex);
387 xPushCPtr(obj); /* code to restart with */
388 RETURN(ThreadBlocked);
391 barf("Unknown context switch reasoning");
396 switch ( get_itbl(obj)->type ) {
398 barf("Invalid object %p",obj);
402 /* ---------------------------------------------------- */
403 /* Start of the bytecode evaluator */
404 /* ---------------------------------------------------- */
407 # define Ins(x) &&l##x
408 static void *labs[] = { INSTRLIST };
410 # define LoopTopLabel
411 # define Case(x) l##x
412 # define Continue goto *labs[BCO_INSTR_8]
413 # define Dispatch Continue;
416 # define LoopTopLabel insnloop:
417 # define Case(x) case x
418 # define Continue goto insnloop
419 # define Dispatch switch (BCO_INSTR_8) {
420 # define EndDispatch }
423 register StgWord8* bciPtr; /* instruction pointer */
424 register StgBCO* bco = (StgBCO*)obj;
427 /* Don't need to SSS ... LLL around doYouWantToGC */
428 wantToGC = doYouWantToGC();
430 xPushCPtr((StgClosure*)bco); /* code to restart with */
431 RETURN(HeapOverflow);
434 bciPtr = &(bcoInstr(bco,0));
438 ASSERT((StgWord)(PC) < bco->n_instrs);
440 fprintf(stderr,"Sp = %p\tSu = %p\tpc = %d\t", xSp, xSu, PC);
444 fprintf(stderr,"\n");
445 for (i = 8; i >= 0; i--)
446 fprintf(stderr, "%d %p\n", i, (StgPtr)(*(gSp+i)));
448 fprintf(stderr,"\n");
454 Case(i_INTERNAL_ERROR):
455 barf("INTERNAL_ERROR at %p:%d",bco,PC-1);
457 barf("PANIC at %p:%d",bco,PC-1);
461 if (xSp - n < xSpLim) {
462 xPushCPtr((StgClosure*)bco); /* code to restart with */
463 RETURN(StackOverflow);
467 Case(i_STK_CHECK_big):
469 int n = BCO_INSTR_16;
470 if (xSp - n < xSpLim) {
471 xPushCPtr((StgClosure*)bco); /* code to restart with */
472 RETURN(StackOverflow);
479 if ((StgPtr*)(xSp + n) > (StgPtr*)xSu) {
480 StgWord words = (P_)xSu - xSp;
482 /* first build a PAP */
483 ASSERT((P_)xSu >= xSp); /* was (words >= 0) but that's always true */
484 if (words == 0) { /* optimisation */
485 /* Skip building the PAP and update with an indirection. */
488 /* In the evaluator, we avoid the need to do
489 * a heap check here by including the size of
490 * the PAP in the heap check we performed
491 * when we entered the BCO.
495 SSS; pap = (StgPAP*)grabHpNonUpd(PAP_sizeW(words)); LLL;
496 SET_HDR(pap,&PAP_info,CC_pap);
499 for (i = 0; i < (I_)words; ++i) {
500 payloadWord(pap,i) = xSp[i];
503 obj = stgCast(StgClosure*,pap);
506 /* now deal with "update frame" */
507 /* as an optimisation, we process all on top of stack */
508 /* instead of just the top one */
509 ASSERT(xSp==(P_)xSu);
511 switch (get_itbl(xSu)->type) {
513 /* Hit a catch frame during an arg satisfaction check,
514 * so the thing returning (1) has not thrown an
515 * exception, and (2) is of functional type. Just
516 * zap the catch frame and carry on down the stack
517 * (looking for more arguments, basically).
519 SSS; PopCatchFrame(); LLL;
522 xPopUpdateFrame(obj);
525 barf("STOP frame during pap update");
527 cap->rCurrentTSO->what_next = ThreadComplete;
528 SSS; PopStopFrame(obj); LLL;
529 RETURN(ThreadFinished);
532 SSS; PopSeqFrame(); LLL;
533 ASSERT(xSp != (P_)xSu);
534 /* Hit a SEQ frame during an arg satisfaction check.
535 * So now return to bco_info which is under the
536 * SEQ frame. The following code is copied from a
537 * case RET_BCO further down. (The reason why we're
538 * here is that something of functional type has
539 * been seq-d on, and we're now returning to the
540 * algebraic-case-continuation which forced the
541 * evaluation in the first place.)
553 barf("Invalid update frame during argcheck");
555 } while (xSp==(P_)xSu);
563 int words = BCO_INSTR_8;
564 SSS; p = grabHpUpd(AP_sizeW(words)); LLL;
568 Case(i_ALLOC_CONSTR):
571 StgInfoTable* info = bcoConstAddr(bco,BCO_INSTR_8);
572 SSS; p = grabHpNonUpd(sizeW_fromITBL(info)); LLL;
573 SET_HDR((StgClosure*)p,info,??);
577 Case(i_ALLOC_CONSTR_big):
580 int x = BCO_INSTR_16;
581 StgInfoTable* info = bcoConstAddr(bco,x);
582 SSS; p = grabHpNonUpd(sizeW_fromITBL(info)); LLL;
583 SET_HDR((StgClosure*)p,info,??);
589 int x = BCO_INSTR_8; /* ToDo: Word not Int! */
591 StgAP_UPD* o = stgCast(StgAP_UPD*,xStackPtr(x));
592 SET_HDR(o,&AP_UPD_info,??);
594 o->fun = stgCast(StgClosure*,xPopPtr());
595 for(x=0; x < y; ++x) {
596 payloadWord(o,x) = xPopWord();
599 fprintf(stderr,"\tBuilt ");
601 printObj(stgCast(StgClosure*,o));
612 o = stgCast(StgAP_UPD*,xStackPtr(x));
613 SET_HDR(o,&AP_UPD_info,??);
615 o->fun = stgCast(StgClosure*,xPopPtr());
616 for(x=0; x < y; ++x) {
617 payloadWord(o,x) = xPopWord();
620 fprintf(stderr,"\tBuilt ");
622 printObj(stgCast(StgClosure*,o));
631 StgPAP* o = stgCast(StgPAP*,xStackPtr(x));
632 SET_HDR(o,&PAP_info,??);
634 o->fun = stgCast(StgClosure*,xPopPtr());
635 for(x=0; x < y; ++x) {
636 payloadWord(o,x) = xPopWord();
639 fprintf(stderr,"\tBuilt ");
641 printObj(stgCast(StgClosure*,o));
648 int offset = BCO_INSTR_8;
649 StgClosure* o = stgCast(StgClosure*,xStackPtr(offset));
650 const StgInfoTable* info = get_itbl(o);
651 nat p = info->layout.payload.ptrs;
652 nat np = info->layout.payload.nptrs;
654 for(i=0; i < p; ++i) {
655 o->payload[i] = xPopCPtr();
657 for(i=0; i < np; ++i) {
658 payloadWord(o,p+i) = 0xdeadbeef;
661 fprintf(stderr,"\tBuilt ");
663 printObj(stgCast(StgClosure*,o));
670 int offset = BCO_INSTR_16;
671 StgClosure* o = stgCast(StgClosure*,xStackPtr(offset));
672 const StgInfoTable* info = get_itbl(o);
673 nat p = info->layout.payload.ptrs;
674 nat np = info->layout.payload.nptrs;
676 for(i=0; i < p; ++i) {
677 o->payload[i] = xPopCPtr();
679 for(i=0; i < np; ++i) {
680 payloadWord(o,p+i) = 0xdeadbeef;
683 fprintf(stderr,"\tBuilt ");
685 printObj(stgCast(StgClosure*,o));
694 ASSERT(xSp+x+y <= stgCast(StgPtr,xSu));
695 /* a_1, .. a_x, b_1, .. b_y, s => a_1, .. a_x, s */
697 xSetStackWord(x+y,xStackWord(x));
707 ASSERT(xSp+x+y <= stgCast(StgPtr,xSu));
708 /* a_1, .. a_x, b_1, .. b_y, s => a_1, .. a_x, s */
710 xSetStackWord(x+y,xStackWord(x));
722 xPushPtr(bcoConstPtr(bco,BCO_INSTR_8));
723 xPushPtr(stgCast(StgPtr,&ret_bco_info));
728 int tag = BCO_INSTR_8;
729 StgWord offset = BCO_INSTR_16;
730 if (constrTag( (StgClosure*)xStackPtr(0) ) != tag) {
737 StgClosure* o = stgCast(StgClosure*,xStackPtr(0));
738 const StgInfoTable* itbl = get_itbl(o);
739 int i = itbl->layout.payload.ptrs;
740 ASSERT( itbl->type == CONSTR
741 || itbl->type == CONSTR_STATIC
742 || itbl->type == CONSTR_NOCAF_STATIC
743 || itbl->type == CONSTR_1_0
744 || itbl->type == CONSTR_0_1
745 || itbl->type == CONSTR_2_0
746 || itbl->type == CONSTR_1_1
747 || itbl->type == CONSTR_0_2
750 xPushCPtr(o->payload[i]);
756 int n = BCO_INSTR_16;
757 StgPtr p = xStackPtr(n);
763 StgPtr p = xStackPtr(BCO_INSTR_8);
769 xPushPtr(stgCast(StgPtr,bcoConstPtr(bco,BCO_INSTR_8)));
774 int n = BCO_INSTR_16;
775 xPushPtr(stgCast(StgPtr,bcoConstPtr(bco,n)));
779 /* allocate rows, implemented on top of (frozen) Arrays */
783 StgWord n = BCO_INSTR_8;
784 SSS; p = stgCast(StgMutArrPtrs*,grabHpNonUpd(sizeofW(StgMutArrPtrs) + n)); LLL;
785 SET_HDR(p,&MUT_ARR_PTRS_FROZEN_info,CCCS);
790 Case(i_ALLOC_ROW_big):
793 StgWord n = BCO_INSTR_16;
794 SSS; p = stgCast(StgMutArrPtrs*,grabHpNonUpd(sizeofW(StgMutArrPtrs) + n)); LLL;
795 SET_HDR(p,&MUT_ARR_PTRS_FROZEN_info,CCCS);
801 /* pack values into a row. */
804 StgWord offset = BCO_INSTR_8;
805 StgMutArrPtrs* p = stgCast(StgMutArrPtrs*,xStackPtr(offset));
811 p->payload[i] = xPopCPtr();
814 fprintf(stderr,"\tBuilt ");
816 printObj(stgCast(StgClosure*,p));
821 Case(i_PACK_ROW_big):
823 StgWord offset = BCO_INSTR_16;
824 StgMutArrPtrs* p = stgCast(StgMutArrPtrs*,xStackPtr(offset));
830 p->payload[i] = xPopCPtr();
833 fprintf(stderr,"\tBuilt ");
835 printObj(stgCast(StgClosure*,p));
841 /* extract all fields of a row */
844 StgMutArrPtrs* p = stgCast(StgMutArrPtrs*,xStackPtr(0));
849 xPushCPtr(p->payload[i]);
854 /* Trivial row (unit) */
855 Case(i_CONST_ROW_TRIV):
858 SSS; p = stgCast(StgMutArrPtrs*,grabHpNonUpd(sizeofW(StgMutArrPtrs) + 0)); LLL;
859 SET_HDR(p,&MUT_ARR_PTRS_FROZEN_info,CCCS);
865 /* pack values into an Inj */
866 Case(i_PACK_INJ_VAR):
868 const int size = CONSTR_sizeW(sizeofW(StgPtr),sizeofW(StgWord));
869 StgWord offset = BCO_INSTR_8;
872 SSS; o = (StgClosure*)grabHpNonUpd(size); LLL;
873 SET_HDR(o,Inj_con_info,??);
875 payloadWord(o,sizeofW(StgPtr)) = xTaggedStackWord(offset);
876 payloadPtr(o,0) = xPopPtr();
879 fprintf(stderr,"\tBuilt ");
881 printObj(stgCast(StgClosure*,o));
884 xPushPtr(stgCast(StgPtr,o));
887 Case(i_PACK_INJ_VAR_big):
889 const int size = CONSTR_sizeW(sizeofW(StgPtr),sizeofW(StgWord));
890 StgWord offset = BCO_INSTR_16;
893 SSS; o = (StgClosure*)grabHpNonUpd(size); LLL;
894 SET_HDR(o,Inj_con_info,??);
896 payloadWord(o,sizeofW(StgPtr)) = xTaggedStackWord(offset);
897 payloadPtr(o,0) = xPopPtr();
900 fprintf(stderr,"\tBuilt ");
902 printObj(stgCast(StgClosure*,o));
905 xPushPtr(stgCast(StgPtr,o));
908 Case(i_PACK_INJ_CONST_8):
910 const int size = CONSTR_sizeW(sizeofW(StgPtr),sizeofW(StgWord));
911 StgWord witness = BCO_INSTR_8;
914 SSS; o = (StgClosure*)grabHpNonUpd(size); LLL;
915 SET_HDR(o,Inj_con_info,??);
917 payloadWord(o,sizeofW(StgPtr)) = witness;
918 payloadPtr(o,0) = xPopPtr();
921 fprintf(stderr,"\tBuilt ");
923 printObj(stgCast(StgClosure*,o));
926 xPushPtr(stgCast(StgPtr,o));
929 Case(i_PACK_INJ_REL_8):
931 const int size = CONSTR_sizeW(sizeofW(StgPtr),sizeofW(StgWord));
932 StgWord offset = BCO_INSTR_8;
933 StgWord cwitness = BCO_INSTR_8;
936 SSS; o = (StgClosure*)grabHpNonUpd(size); LLL;
937 SET_HDR(o,Inj_con_info,??);
939 payloadWord(o,sizeofW(StgPtr)) = xTaggedStackWord(offset) + cwitness;
940 payloadPtr(o,0) = xPopPtr();
943 fprintf(stderr,"\tBuilt ");
945 printObj(stgCast(StgClosure*,o));
948 xPushPtr(stgCast(StgPtr,o));
953 const int size = CONSTR_sizeW(sizeofW(StgPtr),sizeofW(StgWord));
956 SSS; o = (StgClosure*)grabHpNonUpd(size); LLL;
957 SET_HDR(o,Inj_con_info,??);
959 payloadWord(o,sizeofW(StgPtr)) = xPopTaggedWord();
960 payloadPtr(o,0) = xPopPtr();
963 fprintf(stderr,"\tBuilt ");
965 printObj(stgCast(StgClosure*,o));
968 xPushPtr(stgCast(StgPtr,o));
972 /* Test Inj witnesses. */
973 Case(i_TEST_INJ_VAR):
975 StgWord offset = BCO_INSTR_8;
976 StgWord jump = BCO_INSTR_16;
978 StgWord index = payloadWord( (StgClosure*)xStackPtr(0), sizeofW(StgPtr) );
979 if (index != xTaggedStackWord(offset) )
985 Case(i_TEST_INJ_VAR_big):
987 StgWord offset = BCO_INSTR_16;
988 StgWord jump = BCO_INSTR_16;
990 StgWord index = payloadWord( (StgClosure*)xStackPtr(0), sizeofW(StgPtr) );
991 if (index != xTaggedStackWord(offset) )
997 Case(i_TEST_INJ_CONST_8):
999 StgWord cwitness = BCO_INSTR_8;
1000 StgWord jump = BCO_INSTR_16;
1002 StgWord witness = payloadWord( (StgClosure*)xStackPtr(0), sizeofW(StgPtr) );
1003 if (witness != cwitness )
1009 Case(i_TEST_INJ_REL_8):
1011 StgWord offset = BCO_INSTR_8;
1012 StgWord cwitness = BCO_INSTR_8;
1013 StgWord jump = BCO_INSTR_16;
1015 StgWord witness = payloadWord( (StgClosure*)xStackPtr(0), sizeofW(StgPtr) );
1016 if (witness != xTaggedStackWord(offset) + cwitness )
1024 StgWord jump = BCO_INSTR_16;
1025 StgWord cwitness = xPopTaggedWord();
1027 StgWord witness = payloadWord( (StgClosure*)xStackPtr(0), sizeofW(StgPtr) );
1028 if (witness != cwitness )
1035 /* extract the value of an INJ */
1038 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1040 ASSERT(get_itbl(con) == Inj_con_info);
1042 xPushPtr(payloadPtr(con,0));
1046 /* optimized witness (word) operations */
1047 Case(i_CONST_WORD_8):
1049 xPushTaggedWord(BCO_INSTR_8);
1052 Case(i_ADD_WORD_VAR):
1054 StgWord offset = BCO_INSTR_8;
1055 StgWord witness = xTaggedStackWord(offset);
1056 witness += xPopTaggedWord();
1057 xPushTaggedWord(witness);
1060 Case(i_ADD_WORD_VAR_big):
1062 StgWord offset = BCO_INSTR_16;
1063 StgWord witness = xTaggedStackWord(offset);
1064 witness += xPopTaggedWord();
1065 xPushTaggedWord(witness);
1068 Case(i_ADD_WORD_VAR_8):
1070 StgWord offset = BCO_INSTR_8;
1071 StgWord inc = BCO_INSTR_8;
1072 StgWord witness = xTaggedStackWord(offset);
1073 xPushTaggedWord(witness + inc);
1076 #endif /* XMLAMBA */
1080 SSS; PushTaggedRealWorld(); LLL;
1085 StgInt i = xTaggedStackInt(BCO_INSTR_8);
1091 xPushTaggedInt(bcoConstInt(bco,BCO_INSTR_8));
1094 Case(i_CONST_INT_big):
1096 int n = BCO_INSTR_16;
1097 xPushTaggedInt(bcoConstInt(bco,n));
1103 SSS; o = (StgClosure*)grabHpNonUpd(Izh_sizeW); LLL;
1104 SET_HDR(o,Izh_con_info,??);
1105 payloadWord(o,0) = xPopTaggedInt();
1107 fprintf(stderr,"\tBuilt ");
1109 printObj(stgCast(StgClosure*,o));
1112 xPushPtr(stgCast(StgPtr,o));
1117 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1118 /* ASSERT(isIntLike(con)); */
1119 xPushTaggedInt(payloadWord(con,0));
1124 StgWord offset = BCO_INSTR_16;
1125 StgInt x = xPopTaggedInt();
1126 StgInt y = xPopTaggedInt();
1132 Case(i_CONST_INTEGER):
1136 char* s = bcoConstAddr(bco,BCO_INSTR_8);
1138 n = size_fromStr(s);
1139 p = CreateByteArrayToHoldInteger(n);
1140 do_fromStr ( s, n, IntegerInsideByteArray(p));
1141 SloppifyIntegerEnd(p);
1148 StgWord w = xTaggedStackWord(BCO_INSTR_8);
1154 xPushTaggedWord(bcoConstWord(bco,BCO_INSTR_8));
1157 Case(i_CONST_WORD_big):
1159 StgWord n = BCO_INSTR_16;
1160 xPushTaggedWord(bcoConstWord(bco,n));
1166 SSS; o = (StgClosure*)grabHpNonUpd(Wzh_sizeW); LLL;
1167 SET_HDR(o,Wzh_con_info,??);
1168 payloadWord(o,0) = xPopTaggedWord();
1170 fprintf(stderr,"\tBuilt ");
1172 printObj(stgCast(StgClosure*,o));
1175 xPushPtr(stgCast(StgPtr,o));
1178 Case(i_UNPACK_WORD):
1180 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1181 /* ASSERT(isWordLike(con)); */
1182 xPushTaggedWord(payloadWord(con,0));
1187 StgAddr a = xTaggedStackAddr(BCO_INSTR_8);
1193 xPushTaggedAddr(bcoConstAddr(bco,BCO_INSTR_8));
1196 Case(i_CONST_ADDR_big):
1198 int n = BCO_INSTR_16;
1199 xPushTaggedAddr(bcoConstAddr(bco,n));
1205 SSS; o = (StgClosure*)grabHpNonUpd(Azh_sizeW); LLL;
1206 SET_HDR(o,Azh_con_info,??);
1207 payloadPtr(o,0) = xPopTaggedAddr();
1209 fprintf(stderr,"\tBuilt ");
1211 printObj(stgCast(StgClosure*,o));
1214 xPushPtr(stgCast(StgPtr,o));
1217 Case(i_UNPACK_ADDR):
1219 StgClosure* con = (StgClosure*)xStackPtr(0);
1220 /* ASSERT(isAddrLike(con)); */
1221 xPushTaggedAddr(payloadPtr(con,0));
1226 StgChar c = xTaggedStackChar(BCO_INSTR_8);
1232 xPushTaggedChar(bcoConstChar(bco,BCO_INSTR_8));
1238 SSS; o = (StgClosure*)grabHpNonUpd(Czh_sizeW); LLL;
1239 SET_HDR(o,Czh_con_info,??);
1240 payloadWord(o,0) = xPopTaggedChar();
1241 xPushPtr(stgCast(StgPtr,o));
1243 fprintf(stderr,"\tBuilt ");
1245 printObj(stgCast(StgClosure*,o));
1250 Case(i_UNPACK_CHAR):
1252 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1253 /* ASSERT(isCharLike(con)); */
1254 xPushTaggedChar(payloadWord(con,0));
1259 StgFloat f = xTaggedStackFloat(BCO_INSTR_8);
1260 xPushTaggedFloat(f);
1263 Case(i_CONST_FLOAT):
1265 xPushTaggedFloat(bcoConstFloat(bco,BCO_INSTR_8));
1271 SSS; o = (StgClosure*)grabHpNonUpd(Fzh_sizeW); LLL;
1272 SET_HDR(o,Fzh_con_info,??);
1273 ASSIGN_FLT(&payloadWord(o,0),xPopTaggedFloat());
1275 fprintf(stderr,"\tBuilt ");
1277 printObj(stgCast(StgClosure*,o));
1280 xPushPtr(stgCast(StgPtr,o));
1283 Case(i_UNPACK_FLOAT):
1285 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1286 /* ASSERT(isFloatLike(con)); */
1287 xPushTaggedFloat(PK_FLT(&payloadWord(con,0)));
1292 StgDouble d = xTaggedStackDouble(BCO_INSTR_8);
1293 xPushTaggedDouble(d);
1296 Case(i_CONST_DOUBLE):
1298 xPushTaggedDouble(bcoConstDouble(bco,BCO_INSTR_8));
1301 Case(i_CONST_DOUBLE_big):
1303 int n = BCO_INSTR_16;
1304 xPushTaggedDouble(bcoConstDouble(bco,n));
1307 Case(i_PACK_DOUBLE):
1310 SSS; o = (StgClosure*)grabHpNonUpd(Dzh_sizeW); LLL;
1311 SET_HDR(o,Dzh_con_info,??);
1312 ASSIGN_DBL(&payloadWord(o,0),xPopTaggedDouble());
1314 fprintf(stderr,"\tBuilt ");
1315 printObj(stgCast(StgClosure*,o));
1317 xPushPtr(stgCast(StgPtr,o));
1320 Case(i_UNPACK_DOUBLE):
1322 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1323 /* ASSERT(isDoubleLike(con)); */
1324 xPushTaggedDouble(PK_DBL(&payloadWord(con,0)));
1329 StgStablePtr s = xTaggedStackStable(BCO_INSTR_8);
1330 xPushTaggedStable(s);
1333 Case(i_PACK_STABLE):
1336 SSS; o = (StgClosure*)grabHpNonUpd(Stablezh_sizeW); LLL;
1337 SET_HDR(o,StablePtr_con_info,??);
1338 payloadWord(o,0) = (W_)xPopTaggedStable();
1340 fprintf(stderr,"\tBuilt ");
1342 printObj(stgCast(StgClosure*,o));
1345 xPushPtr(stgCast(StgPtr,o));
1348 Case(i_UNPACK_STABLE):
1350 StgClosure* con = (StgClosure*)xStackPtr(0);
1351 /* ASSERT(isStableLike(con)); */
1352 xPushTaggedStable(payloadWord(con,0));
1360 SSS; p = enterBCO_primop1 ( i ); LLL;
1361 if (p) { obj = p; goto enterLoop; };
1366 int i, trc, pc_saved;
1369 trc = 12345678; /* Assume != any StgThreadReturnCode */
1374 p = enterBCO_primop2 ( i, &trc, &bco_tmp, cap,
1378 bciPtr = &(bcoInstr(bco,pc_saved));
1380 if (trc == 12345678) {
1381 /* we want to enter p */
1382 obj = p; goto enterLoop;
1384 /* trc is the the StgThreadReturnCode for
1386 RETURN((StgThreadReturnCode)trc);
1392 /* combined insns, created by peephole opt */
1395 int x = BCO_INSTR_8;
1396 int y = BCO_INSTR_8;
1397 ASSERT(xSp+x+y <= stgCast(StgPtr,xSu));
1398 /* a_1, .. a_x, b_1, .. b_y, s => a_1, .. a_x, s */
1405 xSetStackWord(x+y,xStackWord(x));
1415 p = xStackPtr(BCO_INSTR_8);
1417 p = xStackPtr(BCO_INSTR_8);
1424 xPushPtr(bcoConstPtr(bco,BCO_INSTR_8));
1425 xPushPtr(stgCast(StgPtr,&ret_bco_info));
1426 p = xStackPtr(BCO_INSTR_8);
1432 StgPtr retaddr = bcoConstPtr(bco,BCO_INSTR_8);
1433 StgPtr ptr = xStackPtr(BCO_INSTR_8);
1435 /* A shortcut. We're going to push the address of a
1436 return continuation, and then enter a variable, so
1437 that when the var is evaluated, we return to the
1438 continuation. The shortcut is: if the var is a
1439 constructor, don't bother to enter it. Instead,
1440 push the variable on the stack (since this is what
1441 the continuation expects) and jump directly to the
1444 if (get_itbl((StgClosure*)ptr)->type == CONSTR) {
1446 obj = (StgClosure*)retaddr;
1448 fprintf(stderr, "object to enter is a constructor -- "
1449 "jumping directly to return continuation\n" );
1454 /* This is the normal, non-short-cut route */
1456 xPushPtr(stgCast(StgPtr,&ret_bco_info));
1457 obj = (StgClosure*)ptr;
1462 Case(i_VAR_DOUBLE_big):
1463 Case(i_CONST_FLOAT_big):
1464 Case(i_VAR_FLOAT_big):
1465 Case(i_CONST_CHAR_big):
1466 Case(i_VAR_CHAR_big):
1467 Case(i_VAR_ADDR_big):
1468 Case(i_VAR_STABLE_big):
1469 Case(i_CONST_INTEGER_big):
1470 Case(i_VAR_INT_big):
1471 Case(i_VAR_WORD_big):
1472 Case(i_RETADDR_big):
1477 Case(i_TEST_INJ_CONST):
1478 Case(i_TEST_INJ_big):
1480 Case(i_PACK_INJ_CONST):
1481 Case(i_PACK_INJ_big):
1483 Case(i_PACK_ROW_big):
1485 Case(i_ALLOC_ROW_big):
1490 disInstr ( bco, PC );
1491 barf("\nUnrecognised instruction");
1495 barf("enterBCO: ran off end of loop");
1499 # undef LoopTopLabel
1505 /* ---------------------------------------------------- */
1506 /* End of the bytecode evaluator */
1507 /* ---------------------------------------------------- */
1511 StgBlockingQueue* bh;
1512 StgCAF* caf = (StgCAF*)obj;
1513 if (xSp - sizeofW(StgUpdateFrame) < xSpLim) {
1514 xPushCPtr(obj); /* code to restart with */
1515 RETURN(StackOverflow);
1517 SSS; bh = (StgBlockingQueue*)grabHpUpd(BLACKHOLE_sizeW()); LLL;
1518 SET_INFO(bh,&CAF_BLACKHOLE_info);
1519 bh->blocking_queue = EndTSOQueue;
1521 fprintf(stderr,"Created CAF_BLACKHOLE %p for CAF %p"
1522 " in evaluator\n",bh,caf));
1523 SET_INFO(caf,&CAF_ENTERED_info);
1524 caf->value = (StgClosure*)bh;
1526 SSS; newCAF_made_by_Hugs(caf); LLL;
1528 xPushUpdateFrame(bh,0);
1529 xSp -= sizeofW(StgUpdateFrame);
1535 StgCAF* caf = (StgCAF*)obj;
1536 obj = caf->value; /* it's just a fancy indirection */
1542 case SE_CAF_BLACKHOLE:
1544 /* Let the scheduler figure out what to do :-) */
1545 cap->rCurrentTSO->what_next = ThreadEnterGHC;
1547 RETURN(ThreadYielding);
1551 StgAP_UPD* ap = stgCast(StgAP_UPD*,obj);
1553 if (xSp - (i + sizeofW(StgUpdateFrame)) < xSpLim) {
1554 xPushCPtr(obj); /* code to restart with */
1555 RETURN(StackOverflow);
1557 /* ToDo: look for xSp==xSu && stackInt(0) == UPD_FRAME
1558 and insert an indirection immediately */
1559 xPushUpdateFrame(ap,0);
1560 xSp -= sizeofW(StgUpdateFrame);
1562 xPushWord(payloadWord(ap,i));
1565 #ifdef EAGER_BLACKHOLING
1566 #warn LAZY_BLACKHOLING is default for StgHugs
1567 #error Dont know if EAGER_BLACKHOLING works in StgHugs
1569 /* superfluous - but makes debugging easier */
1570 StgBlackHole* bh = stgCast(StgBlackHole*,ap);
1571 SET_INFO(bh,&BLACKHOLE_info);
1572 bh->blocking_queue = EndTSOQueue;
1574 fprintf(stderr,"Eagerly blackholed AP_UPD %p in evaluator\n",bh));
1577 #endif /* EAGER_BLACKHOLING */
1582 StgPAP* pap = stgCast(StgPAP*,obj);
1583 int i = pap->n_args; /* ToDo: stack check */
1584 /* ToDo: if PAP is in whnf, we can update any update frames
1588 xPushWord(payloadWord(pap,i));
1595 obj = stgCast(StgInd*,obj)->indirectee;
1600 obj = stgCast(StgIndOldGen*,obj)->indirectee;
1609 case CONSTR_INTLIKE:
1610 case CONSTR_CHARLIKE:
1612 case CONSTR_NOCAF_STATIC:
1614 /* rows are mutarrays and should be treated as constructors. */
1615 case MUT_ARR_PTRS_FROZEN:
1619 switch (get_itbl(stgCast(StgClosure*,xSp))->type) {
1621 SSS; PopCatchFrame(); LLL;
1624 xPopUpdateFrame(obj);
1627 SSS; PopSeqFrame(); LLL;
1631 ASSERT(xSp==(P_)xSu);
1634 fprintf(stderr, "hit a STOP_FRAME\n");
1636 fprintf(stderr,"xSp = %p\txSu = %p\n", xSp, xSu);
1637 printStack(xSp,cap->rCurrentTSO->stack
1638 + cap->rCurrentTSO->stack_size,xSu);
1641 cap->rCurrentTSO->what_next = ThreadComplete;
1642 SSS; PopStopFrame(obj); LLL;
1644 RETURN(ThreadFinished);
1654 /* was: goto enterLoop;
1655 But we know that obj must be a bco now, so jump directly.
1658 case RET_SMALL: /* return to GHC */
1662 cap->rCurrentTSO->what_next = ThreadEnterGHC;
1664 RETURN(ThreadYielding);
1666 belch("entered CONSTR with invalid continuation on stack");
1669 printObj(stgCast(StgClosure*,xSp));
1672 barf("bailing out");
1679 //fprintf(stderr, "enterCountI = %d\n", enterCountI);
1680 //fprintf(stderr, "entering unknown closure -- yielding to sched\n");
1683 cap->rCurrentTSO->what_next = ThreadEnterGHC;
1684 xPushCPtr(obj); /* code to restart with */
1685 RETURN(ThreadYielding);
1688 barf("Ran off the end of enter - yoiks");
1705 #undef xSetStackWord
1708 #undef xPushTaggedInt
1709 #undef xPopTaggedInt
1710 #undef xTaggedStackInt
1711 #undef xPushTaggedWord
1712 #undef xPopTaggedWord
1713 #undef xTaggedStackWord
1714 #undef xPushTaggedAddr
1715 #undef xTaggedStackAddr
1716 #undef xPopTaggedAddr
1717 #undef xPushTaggedStable
1718 #undef xTaggedStackStable
1719 #undef xPopTaggedStable
1720 #undef xPushTaggedChar
1721 #undef xTaggedStackChar
1722 #undef xPopTaggedChar
1723 #undef xPushTaggedFloat
1724 #undef xTaggedStackFloat
1725 #undef xPopTaggedFloat
1726 #undef xPushTaggedDouble
1727 #undef xTaggedStackDouble
1728 #undef xPopTaggedDouble
1729 #undef xPopUpdateFrame
1730 #undef xPushUpdateFrame
1733 /* --------------------------------------------------------------------------
1734 * Supporting routines for primops
1735 * ------------------------------------------------------------------------*/
1737 static inline void PushTag ( StackTag t )
1739 inline void PushPtr ( StgPtr x )
1740 { *(--stgCast(StgPtr*,gSp)) = x; }
1741 static inline void PushCPtr ( StgClosure* x )
1742 { *(--stgCast(StgClosure**,gSp)) = x; }
1743 static inline void PushInt ( StgInt x )
1744 { *(--stgCast(StgInt*,gSp)) = x; }
1745 static inline void PushWord ( StgWord x )
1746 { *(--stgCast(StgWord*,gSp)) = x; }
1749 static inline void checkTag ( StackTag t1, StackTag t2 )
1750 { ASSERT(t1 == t2);}
1751 static inline void PopTag ( StackTag t )
1752 { checkTag(t,*(gSp++)); }
1753 inline StgPtr PopPtr ( void )
1754 { return *stgCast(StgPtr*,gSp)++; }
1755 static inline StgClosure* PopCPtr ( void )
1756 { return *stgCast(StgClosure**,gSp)++; }
1757 static inline StgInt PopInt ( void )
1758 { return *stgCast(StgInt*,gSp)++; }
1759 static inline StgWord PopWord ( void )
1760 { return *stgCast(StgWord*,gSp)++; }
1762 static inline StgPtr stackPtr ( StgStackOffset i )
1763 { return *stgCast(StgPtr*, gSp+i); }
1764 static inline StgInt stackInt ( StgStackOffset i )
1765 { return *stgCast(StgInt*, gSp+i); }
1766 static inline StgWord stackWord ( StgStackOffset i )
1767 { return *stgCast(StgWord*,gSp+i); }
1769 static inline void setStackWord ( StgStackOffset i, StgWord w )
1773 static inline void setStackPtr ( StgStackOffset i, StgPtr p )
1774 { *(stgCast(StgPtr*, gSp+i)) = p; }
1777 static inline void PushTaggedRealWorld( void )
1778 { PushTag(REALWORLD_TAG); }
1779 inline void PushTaggedInt ( StgInt x )
1780 { gSp -= sizeofW(StgInt); *gSp = x; PushTag(INT_TAG); }
1781 inline void PushTaggedWord ( StgWord x )
1782 { gSp -= sizeofW(StgWord); *gSp = x; PushTag(WORD_TAG); }
1783 inline void PushTaggedAddr ( StgAddr x )
1784 { gSp -= sizeofW(StgAddr); *gSp = (W_)x; PushTag(ADDR_TAG); }
1785 inline void PushTaggedChar ( StgChar x )
1786 { gSp -= sizeofW(StgChar); *gSp = stgCast(StgWord,x); PushTag(CHAR_TAG); }
1787 inline void PushTaggedFloat ( StgFloat x )
1788 { gSp -= sizeofW(StgFloat); ASSIGN_FLT(gSp,x); PushTag(FLOAT_TAG); }
1789 inline void PushTaggedDouble ( StgDouble x )
1790 { gSp -= sizeofW(StgDouble); ASSIGN_DBL(gSp,x); PushTag(DOUBLE_TAG); }
1791 inline void PushTaggedStablePtr ( StgStablePtr x )
1792 { gSp -= sizeofW(StgStablePtr); *gSp = (W_)x; PushTag(STABLE_TAG); }
1793 static inline void PushTaggedBool ( int x )
1794 { PushTaggedInt(x); }
1798 static inline void PopTaggedRealWorld ( void )
1799 { PopTag(REALWORLD_TAG); }
1800 inline StgInt PopTaggedInt ( void )
1801 { StgInt r; PopTag(INT_TAG); r = *stgCast(StgInt*, gSp);
1802 gSp += sizeofW(StgInt); return r;}
1803 inline StgWord PopTaggedWord ( void )
1804 { StgWord r; PopTag(WORD_TAG); r = *stgCast(StgWord*, gSp);
1805 gSp += sizeofW(StgWord); return r;}
1806 inline StgAddr PopTaggedAddr ( void )
1807 { StgAddr r; PopTag(ADDR_TAG); r = *stgCast(StgAddr*, gSp);
1808 gSp += sizeofW(StgAddr); return r;}
1809 inline StgChar PopTaggedChar ( void )
1810 { StgChar r; PopTag(CHAR_TAG); r = stgCast(StgChar, *gSp);
1811 gSp += sizeofW(StgChar); return r;}
1812 inline StgFloat PopTaggedFloat ( void )
1813 { StgFloat r; PopTag(FLOAT_TAG); r = PK_FLT(gSp);
1814 gSp += sizeofW(StgFloat); return r;}
1815 inline StgDouble PopTaggedDouble ( void )
1816 { StgDouble r; PopTag(DOUBLE_TAG); r = PK_DBL(gSp);
1817 gSp += sizeofW(StgDouble); return r;}
1818 inline StgStablePtr PopTaggedStablePtr ( void )
1819 { StgStablePtr r; PopTag(STABLE_TAG); r = *stgCast(StgStablePtr*, gSp);
1820 gSp += sizeofW(StgStablePtr); return r;}
1824 static inline StgInt taggedStackInt ( StgStackOffset i )
1825 { checkTag(INT_TAG,gSp[i]); return *stgCast(StgInt*, gSp+1+i); }
1826 static inline StgWord taggedStackWord ( StgStackOffset i )
1827 { checkTag(WORD_TAG,gSp[i]); return *stgCast(StgWord*, gSp+1+i); }
1828 static inline StgAddr taggedStackAddr ( StgStackOffset i )
1829 { checkTag(ADDR_TAG,gSp[i]); return *stgCast(StgAddr*, gSp+1+i); }
1830 static inline StgChar taggedStackChar ( StgStackOffset i )
1831 { checkTag(CHAR_TAG,gSp[i]); return stgCast(StgChar, *(gSp+1+i)) ; }
1832 static inline StgFloat taggedStackFloat ( StgStackOffset i )
1833 { checkTag(FLOAT_TAG,gSp[i]); return PK_FLT(gSp+1+i); }
1834 static inline StgDouble taggedStackDouble ( StgStackOffset i )
1835 { checkTag(DOUBLE_TAG,gSp[i]); return PK_DBL(gSp+1+i); }
1836 static inline StgStablePtr taggedStackStable ( StgStackOffset i )
1837 { checkTag(STABLE_TAG,gSp[i]); return *stgCast(StgStablePtr*, gSp+1+i); }
1840 /* --------------------------------------------------------------------------
1843 * Should we allocate from a nursery or use the
1844 * doYouWantToGC/allocate interface? We'd already implemented a
1845 * nursery-style scheme when the doYouWantToGC/allocate interface
1847 * One reason to prefer the doYouWantToGC/allocate interface is to
1848 * support operations which allocate an unknown amount in the heap
1849 * (array ops, gmp ops, etc)
1850 * ------------------------------------------------------------------------*/
1852 static inline StgPtr grabHpUpd( nat size )
1854 ASSERT( size >= MIN_UPD_SIZE + sizeofW(StgHeader) );
1855 return allocate(size);
1858 static inline StgPtr grabHpNonUpd( nat size )
1860 ASSERT( size >= MIN_NONUPD_SIZE + sizeofW(StgHeader) );
1861 return allocate(size);
1864 /* --------------------------------------------------------------------------
1865 * Manipulate "update frame" list:
1866 * o Update frames (based on stg_do_update and friends in Updates.hc)
1867 * o Error handling/catching (based on catchzh_fast and friends in Prims.hc)
1868 * o Seq frames (based on seq_frame_entry in Prims.hc)
1870 * ------------------------------------------------------------------------*/
1872 static inline void PopUpdateFrame ( StgClosure* obj )
1874 /* NB: doesn't assume that gSp == gSu */
1876 fprintf(stderr, "Updating ");
1877 printPtr(stgCast(StgPtr,gSu->updatee));
1878 fprintf(stderr, " with ");
1880 fprintf(stderr,"gSp = %p\tgSu = %p\n\n", gSp, gSu);
1882 #ifdef EAGER_BLACKHOLING
1883 #warn LAZY_BLACKHOLING is default for StgHugs
1884 #error Dont know if EAGER_BLACKHOLING works in StgHugs
1885 ASSERT(get_itbl(gSu->updatee)->type == BLACKHOLE
1886 || get_itbl(gSu->updatee)->type == SE_BLACKHOLE
1887 || get_itbl(gSu->updatee)->type == CAF_BLACKHOLE
1888 || get_itbl(gSu->updatee)->type == SE_CAF_BLACKHOLE
1890 #endif /* EAGER_BLACKHOLING */
1891 UPD_IND(gSu->updatee,obj);
1892 gSp = stgCast(StgStackPtr,gSu) + sizeofW(StgUpdateFrame);
1896 static inline void PopStopFrame ( StgClosure* obj )
1898 /* Move gSu just off the end of the stack, we're about to gSpam the
1899 * STOP_FRAME with the return value.
1901 gSu = stgCast(StgUpdateFrame*,gSp+1);
1902 *stgCast(StgClosure**,gSp) = obj;
1905 static inline void PushCatchFrame ( StgClosure* handler )
1908 /* ToDo: stack check! */
1909 gSp -= sizeofW(StgCatchFrame);
1910 fp = stgCast(StgCatchFrame*,gSp);
1911 SET_HDR(fp,(StgInfoTable*)&catch_frame_info,CCCS);
1912 fp->handler = handler;
1914 gSu = stgCast(StgUpdateFrame*,fp);
1917 static inline void PopCatchFrame ( void )
1919 /* NB: doesn't assume that gSp == gSu */
1920 /* fprintf(stderr,"Popping catch frame\n"); */
1921 gSp = stgCast(StgStackPtr,gSu) + sizeofW(StgCatchFrame);
1922 gSu = stgCast(StgCatchFrame*,gSu)->link;
1925 static inline void PushSeqFrame ( void )
1928 /* ToDo: stack check! */
1929 gSp -= sizeofW(StgSeqFrame);
1930 fp = stgCast(StgSeqFrame*,gSp);
1931 SET_HDR(fp,(StgInfoTable*)&seq_frame_info,CCCS);
1933 gSu = stgCast(StgUpdateFrame*,fp);
1936 static inline void PopSeqFrame ( void )
1938 /* NB: doesn't assume that gSp == gSu */
1939 gSp = stgCast(StgStackPtr,gSu) + sizeofW(StgSeqFrame);
1940 gSu = stgCast(StgSeqFrame*,gSu)->link;
1943 static inline StgClosure* raiseAnError ( StgClosure* exception )
1945 /* This closure represents the expression 'primRaise E' where E
1946 * is the exception raised (:: Exception).
1947 * It is used to overwrite all the
1948 * thunks which are currently under evaluation.
1950 HaskellObj primRaiseClosure
1951 = getHugs_BCO_cptr_for("primRaise");
1952 HaskellObj reraiseClosure
1953 = rts_apply ( primRaiseClosure, exception );
1956 switch (get_itbl(gSu)->type) {
1958 UPD_IND(gSu->updatee,reraiseClosure);
1959 gSp = stgCast(StgStackPtr,gSu) + sizeofW(StgUpdateFrame);
1965 case CATCH_FRAME: /* found it! */
1967 StgCatchFrame* fp = stgCast(StgCatchFrame*,gSu);
1968 StgClosure *handler = fp->handler;
1970 gSp += sizeofW(StgCatchFrame); /* Pop */
1971 PushCPtr(exception);
1975 barf("raiseError: uncaught exception: STOP_FRAME");
1977 barf("raiseError: weird activation record");
1983 static StgClosure* makeErrorCall ( const char* msg )
1985 /* Note! the msg string should be allocated in a
1986 place which will not get freed -- preferably
1987 read-only data of the program. That's because
1988 the thunk we build here may linger indefinitely.
1989 (thinks: probably not so, but anyway ...)
1992 = getHugs_BCO_cptr_for("error");
1994 = getHugs_BCO_cptr_for("hugsprimUnpackString");
1996 = rts_apply ( unpack, rts_mkAddr ( (void*)msg ) );
1998 = rts_apply ( error, thunk );
2000 (StgClosure*) thunk;
2003 #define raiseIndex(where) makeErrorCall("Array index out of range in " where)
2004 #define raiseDiv0(where) makeErrorCall("Division by zero in " where)
2006 /* --------------------------------------------------------------------------
2008 * ------------------------------------------------------------------------*/
2010 #define OP_CC_B(e) \
2012 unsigned char x = PopTaggedChar(); \
2013 unsigned char y = PopTaggedChar(); \
2014 PushTaggedBool(e); \
2019 unsigned char x = PopTaggedChar(); \
2028 #define OP_IW_I(e) \
2030 StgInt x = PopTaggedInt(); \
2031 StgWord y = PopTaggedWord(); \
2035 #define OP_II_I(e) \
2037 StgInt x = PopTaggedInt(); \
2038 StgInt y = PopTaggedInt(); \
2042 #define OP_II_B(e) \
2044 StgInt x = PopTaggedInt(); \
2045 StgInt y = PopTaggedInt(); \
2046 PushTaggedBool(e); \
2051 PushTaggedAddr(e); \
2056 StgInt x = PopTaggedInt(); \
2057 PushTaggedAddr(e); \
2062 StgInt x = PopTaggedInt(); \
2068 PushTaggedChar(e); \
2073 StgInt x = PopTaggedInt(); \
2074 PushTaggedChar(e); \
2079 PushTaggedWord(e); \
2084 StgInt x = PopTaggedInt(); \
2085 PushTaggedWord(e); \
2090 StgInt x = PopTaggedInt(); \
2091 PushTaggedStablePtr(e); \
2096 PushTaggedFloat(e); \
2101 StgInt x = PopTaggedInt(); \
2102 PushTaggedFloat(e); \
2107 PushTaggedDouble(e); \
2112 StgInt x = PopTaggedInt(); \
2113 PushTaggedDouble(e); \
2116 #define OP_WW_B(e) \
2118 StgWord x = PopTaggedWord(); \
2119 StgWord y = PopTaggedWord(); \
2120 PushTaggedBool(e); \
2123 #define OP_WW_W(e) \
2125 StgWord x = PopTaggedWord(); \
2126 StgWord y = PopTaggedWord(); \
2127 PushTaggedWord(e); \
2132 StgWord x = PopTaggedWord(); \
2138 StgStablePtr x = PopTaggedStablePtr(); \
2144 StgWord x = PopTaggedWord(); \
2145 PushTaggedWord(e); \
2148 #define OP_AA_B(e) \
2150 StgAddr x = PopTaggedAddr(); \
2151 StgAddr y = PopTaggedAddr(); \
2152 PushTaggedBool(e); \
2156 StgAddr x = PopTaggedAddr(); \
2159 #define OP_AI_C(s) \
2161 StgAddr x = PopTaggedAddr(); \
2162 int y = PopTaggedInt(); \
2165 PushTaggedChar(r); \
2167 #define OP_AI_I(s) \
2169 StgAddr x = PopTaggedAddr(); \
2170 int y = PopTaggedInt(); \
2175 #define OP_AI_A(s) \
2177 StgAddr x = PopTaggedAddr(); \
2178 int y = PopTaggedInt(); \
2181 PushTaggedAddr(s); \
2183 #define OP_AI_F(s) \
2185 StgAddr x = PopTaggedAddr(); \
2186 int y = PopTaggedInt(); \
2189 PushTaggedFloat(r); \
2191 #define OP_AI_D(s) \
2193 StgAddr x = PopTaggedAddr(); \
2194 int y = PopTaggedInt(); \
2197 PushTaggedDouble(r); \
2199 #define OP_AI_s(s) \
2201 StgAddr x = PopTaggedAddr(); \
2202 int y = PopTaggedInt(); \
2205 PushTaggedStablePtr(r); \
2207 #define OP_AIC_(s) \
2209 StgAddr x = PopTaggedAddr(); \
2210 int y = PopTaggedInt(); \
2211 StgChar z = PopTaggedChar(); \
2214 #define OP_AII_(s) \
2216 StgAddr x = PopTaggedAddr(); \
2217 int y = PopTaggedInt(); \
2218 StgInt z = PopTaggedInt(); \
2221 #define OP_AIA_(s) \
2223 StgAddr x = PopTaggedAddr(); \
2224 int y = PopTaggedInt(); \
2225 StgAddr z = PopTaggedAddr(); \
2228 #define OP_AIF_(s) \
2230 StgAddr x = PopTaggedAddr(); \
2231 int y = PopTaggedInt(); \
2232 StgFloat z = PopTaggedFloat(); \
2235 #define OP_AID_(s) \
2237 StgAddr x = PopTaggedAddr(); \
2238 int y = PopTaggedInt(); \
2239 StgDouble z = PopTaggedDouble(); \
2242 #define OP_AIs_(s) \
2244 StgAddr x = PopTaggedAddr(); \
2245 int y = PopTaggedInt(); \
2246 StgStablePtr z = PopTaggedStablePtr(); \
2251 #define OP_FF_B(e) \
2253 StgFloat x = PopTaggedFloat(); \
2254 StgFloat y = PopTaggedFloat(); \
2255 PushTaggedBool(e); \
2258 #define OP_FF_F(e) \
2260 StgFloat x = PopTaggedFloat(); \
2261 StgFloat y = PopTaggedFloat(); \
2262 PushTaggedFloat(e); \
2267 StgFloat x = PopTaggedFloat(); \
2268 PushTaggedFloat(e); \
2273 StgFloat x = PopTaggedFloat(); \
2274 PushTaggedBool(e); \
2279 StgFloat x = PopTaggedFloat(); \
2285 StgFloat x = PopTaggedFloat(); \
2286 PushTaggedDouble(e); \
2289 #define OP_DD_B(e) \
2291 StgDouble x = PopTaggedDouble(); \
2292 StgDouble y = PopTaggedDouble(); \
2293 PushTaggedBool(e); \
2296 #define OP_DD_D(e) \
2298 StgDouble x = PopTaggedDouble(); \
2299 StgDouble y = PopTaggedDouble(); \
2300 PushTaggedDouble(e); \
2305 StgDouble x = PopTaggedDouble(); \
2306 PushTaggedBool(e); \
2311 StgDouble x = PopTaggedDouble(); \
2312 PushTaggedDouble(e); \
2317 StgDouble x = PopTaggedDouble(); \
2323 StgDouble x = PopTaggedDouble(); \
2324 PushTaggedFloat(e); \
2328 StgPtr CreateByteArrayToHoldInteger ( int nbytes )
2330 StgWord words = (nbytes+sizeof(W_)-1)/sizeof(W_);
2331 StgWord size = sizeofW(StgArrWords) + words;
2332 StgArrWords* arr = (StgArrWords*)allocate(size);
2333 SET_HDR(arr,&ARR_WORDS_info,CCCS);
2335 ASSERT((W_)nbytes <= arr->words * sizeof(W_));
2338 for (i = 0; i < words; ++i) {
2339 arr->payload[i] = 0xdeadbeef;
2341 { B* b = (B*) &(arr->payload[0]);
2342 b->used = b->sign = 0;
2348 B* IntegerInsideByteArray ( StgPtr arr0 )
2351 StgArrWords* arr = (StgArrWords*)arr0;
2352 ASSERT(GET_INFO(arr) == &ARR_WORDS_info);
2353 b = (B*) &(arr->payload[0]);
2357 void SloppifyIntegerEnd ( StgPtr arr0 )
2359 StgArrWords* arr = (StgArrWords*)arr0;
2360 B* b = (B*) & (arr->payload[0]);
2361 I_ nwunused = arr->words - sizeofW(B) - (b->used+sizeof(W_)-1)/sizeof(W_);
2362 if (nwunused >= ((I_)sizeofW(StgArrWords))) {
2364 b->size -= nwunused * sizeof(W_);
2365 if (b->size < b->used) b->size = b->used;
2368 arr->words -= nwunused;
2369 slop = (StgArrWords*)&(arr->payload[arr->words]);
2370 SET_HDR(slop,&ARR_WORDS_info,CCCS);
2371 slop->words = nwunused - sizeofW(StgArrWords);
2372 ASSERT( &(slop->payload[slop->words]) ==
2373 &(arr->payload[arr->words + nwunused]) );
2377 #define OP_Z_Z(op) \
2379 B* x = IntegerInsideByteArray(PopPtr()); \
2380 int n = mycat2(size_,op)(x); \
2381 StgPtr p = CreateByteArrayToHoldInteger(n); \
2382 mycat2(do_,op)(x,n,IntegerInsideByteArray(p)); \
2383 SloppifyIntegerEnd(p); \
2386 #define OP_ZZ_Z(op) \
2388 B* x = IntegerInsideByteArray(PopPtr()); \
2389 B* y = IntegerInsideByteArray(PopPtr()); \
2390 int n = mycat2(size_,op)(x,y); \
2391 StgPtr p = CreateByteArrayToHoldInteger(n); \
2392 mycat2(do_,op)(x,y,n,IntegerInsideByteArray(p)); \
2393 SloppifyIntegerEnd(p); \
2400 #define HEADER_mI(ty,where) \
2401 StgArrWords* x = stgCast(StgArrWords*,PopPtr()); \
2402 nat i = PopTaggedInt(); \
2403 if (i * sizeof(ty) + (sizeof(ty)) > sizeof(StgWord) * x->words) { \
2404 return (raiseIndex(where)); \
2406 #define OP_mI_ty(ty,where,s) \
2408 HEADER_mI(mycat2(Stg,ty),where) \
2409 { mycat2(Stg,ty) r; \
2411 mycat2(PushTagged,ty)(r); \
2414 #define OP_mIty_(ty,where,s) \
2416 HEADER_mI(mycat2(Stg,ty),where) \
2418 mycat2(Stg,ty) z = mycat2(PopTagged,ty)(); \
2424 __attribute__ ((unused))
2425 static void myStackCheck ( Capability* cap )
2427 /* fprintf(stderr, "myStackCheck\n"); */
2428 if (!(gSpLim <= gSp && gSp <= stgCast(StgPtr,gSu))) {
2429 fprintf(stderr, "myStackCheck: invalid initial gSp/gSu \n" );
2434 if (!( (P_)gSu >= (P_)cap->rCurrentTSO->stack
2436 (P_)gSu <= (P_)(cap->rCurrentTSO->stack
2437 + cap->rCurrentTSO->stack_size))) {
2438 fprintf ( stderr, "myStackCheck: gSu out of stack\n" );
2442 switch (get_itbl(stgCast(StgClosure*,gSu))->type) {
2444 gSu = (StgUpdateFrame*) ((StgCatchFrame*)(gSu))->link;
2447 gSu = (StgUpdateFrame*) ((StgUpdateFrame*)(gSu))->link;
2450 gSu = (StgUpdateFrame*) ((StgSeqFrame*)(gSu))->link;
2455 fprintf(stderr, "myStackCheck: invalid activation record\n");
2464 /* --------------------------------------------------------------------------
2465 * Primop stuff for bytecode interpreter
2466 * ------------------------------------------------------------------------*/
2468 /* Returns & of the next thing to enter (if throwing an exception),
2469 or NULL in the normal case.
2471 static void* enterBCO_primop1 ( int primop1code )
2474 barf("enterBCO_primop1 in combined mode");
2476 switch (primop1code) {
2477 case i_pushseqframe:
2479 StgClosure* c = PopCPtr();
2484 case i_pushcatchframe:
2486 StgClosure* e = PopCPtr();
2487 StgClosure* h = PopCPtr();
2493 case i_gtChar: OP_CC_B(x>y); break;
2494 case i_geChar: OP_CC_B(x>=y); break;
2495 case i_eqChar: OP_CC_B(x==y); break;
2496 case i_neChar: OP_CC_B(x!=y); break;
2497 case i_ltChar: OP_CC_B(x<y); break;
2498 case i_leChar: OP_CC_B(x<=y); break;
2499 case i_charToInt: OP_C_I(x); break;
2500 case i_intToChar: OP_I_C(x); break;
2502 case i_gtInt: OP_II_B(x>y); break;
2503 case i_geInt: OP_II_B(x>=y); break;
2504 case i_eqInt: OP_II_B(x==y); break;
2505 case i_neInt: OP_II_B(x!=y); break;
2506 case i_ltInt: OP_II_B(x<y); break;
2507 case i_leInt: OP_II_B(x<=y); break;
2508 case i_minInt: OP__I(INT_MIN); break;
2509 case i_maxInt: OP__I(INT_MAX); break;
2510 case i_plusInt: OP_II_I(x+y); break;
2511 case i_minusInt: OP_II_I(x-y); break;
2512 case i_timesInt: OP_II_I(x*y); break;
2515 int x = PopTaggedInt();
2516 int y = PopTaggedInt();
2518 return (raiseDiv0("quotInt"));
2520 /* ToDo: protect against minInt / -1 errors
2521 * (repeat for all other division primops) */
2527 int x = PopTaggedInt();
2528 int y = PopTaggedInt();
2530 return (raiseDiv0("remInt"));
2537 StgInt x = PopTaggedInt();
2538 StgInt y = PopTaggedInt();
2540 return (raiseDiv0("quotRemInt"));
2542 PushTaggedInt(x%y); /* last result */
2543 PushTaggedInt(x/y); /* first result */
2546 case i_negateInt: OP_I_I(-x); break;
2548 case i_andInt: OP_II_I(x&y); break;
2549 case i_orInt: OP_II_I(x|y); break;
2550 case i_xorInt: OP_II_I(x^y); break;
2551 case i_notInt: OP_I_I(~x); break;
2552 case i_shiftLInt: OP_II_I(x<<y); break;
2553 case i_shiftRAInt: OP_II_I(x>>y); break; /* ToDo */
2554 case i_shiftRLInt: OP_II_I(x>>y); break; /* ToDo */
2556 case i_gtWord: OP_WW_B(x>y); break;
2557 case i_geWord: OP_WW_B(x>=y); break;
2558 case i_eqWord: OP_WW_B(x==y); break;
2559 case i_neWord: OP_WW_B(x!=y); break;
2560 case i_ltWord: OP_WW_B(x<y); break;
2561 case i_leWord: OP_WW_B(x<=y); break;
2562 case i_minWord: OP__W(0); break;
2563 case i_maxWord: OP__W(UINT_MAX); break;
2564 case i_plusWord: OP_WW_W(x+y); break;
2565 case i_minusWord: OP_WW_W(x-y); break;
2566 case i_timesWord: OP_WW_W(x*y); break;
2569 StgWord x = PopTaggedWord();
2570 StgWord y = PopTaggedWord();
2572 return (raiseDiv0("quotWord"));
2574 PushTaggedWord(x/y);
2579 StgWord x = PopTaggedWord();
2580 StgWord y = PopTaggedWord();
2582 return (raiseDiv0("remWord"));
2584 PushTaggedWord(x%y);
2589 StgWord x = PopTaggedWord();
2590 StgWord y = PopTaggedWord();
2592 return (raiseDiv0("quotRemWord"));
2594 PushTaggedWord(x%y); /* last result */
2595 PushTaggedWord(x/y); /* first result */
2598 case i_negateWord: OP_W_W(-x); break;
2599 case i_andWord: OP_WW_W(x&y); break;
2600 case i_orWord: OP_WW_W(x|y); break;
2601 case i_xorWord: OP_WW_W(x^y); break;
2602 case i_notWord: OP_W_W(~x); break;
2603 case i_shiftLWord: OP_WW_W(x<<y); break;
2604 case i_shiftRAWord: OP_WW_W(x>>y); break; /* ToDo */
2605 case i_shiftRLWord: OP_WW_W(x>>y); break; /* ToDo */
2606 case i_intToWord: OP_I_W(x); break;
2607 case i_wordToInt: OP_W_I(x); break;
2609 case i_gtAddr: OP_AA_B(x>y); break;
2610 case i_geAddr: OP_AA_B(x>=y); break;
2611 case i_eqAddr: OP_AA_B(x==y); break;
2612 case i_neAddr: OP_AA_B(x!=y); break;
2613 case i_ltAddr: OP_AA_B(x<y); break;
2614 case i_leAddr: OP_AA_B(x<=y); break;
2615 case i_intToAddr: OP_I_A((StgAddr)x); break; /* ToDo */
2616 case i_addrToInt: OP_A_I((StgInt)x); break; /* ToDo */
2618 case i_intToStable: OP_I_s((StgStablePtr)x); break;
2619 case i_stableToInt: OP_s_I((W_)x); break;
2621 case i_indexCharOffAddr: OP_AI_C(indexCharOffAddrzh(r,x,y)); break;
2622 case i_readCharOffAddr: OP_AI_C(indexCharOffAddrzh(r,x,y)); break;
2623 case i_writeCharOffAddr: OP_AIC_(writeCharOffAddrzh(x,y,z)); break;
2625 case i_indexIntOffAddr: OP_AI_I(indexIntOffAddrzh(r,x,y)); break;
2626 case i_readIntOffAddr: OP_AI_I(indexIntOffAddrzh(r,x,y)); break;
2627 case i_writeIntOffAddr: OP_AII_(writeIntOffAddrzh(x,y,z)); break;
2629 case i_indexAddrOffAddr: OP_AI_A(indexAddrOffAddrzh(r,x,y)); break;
2630 case i_readAddrOffAddr: OP_AI_A(indexAddrOffAddrzh(r,x,y)); break;
2631 case i_writeAddrOffAddr: OP_AIA_(writeAddrOffAddrzh(x,y,z)); break;
2633 case i_indexFloatOffAddr: OP_AI_F(indexFloatOffAddrzh(r,x,y)); break;
2634 case i_readFloatOffAddr: OP_AI_F(indexFloatOffAddrzh(r,x,y)); break;
2635 case i_writeFloatOffAddr: OP_AIF_(writeFloatOffAddrzh(x,y,z)); break;
2637 case i_indexDoubleOffAddr: OP_AI_D(indexDoubleOffAddrzh(r,x,y)); break;
2638 case i_readDoubleOffAddr: OP_AI_D(indexDoubleOffAddrzh(r,x,y)); break;
2639 case i_writeDoubleOffAddr: OP_AID_(writeDoubleOffAddrzh(x,y,z)); break;
2641 case i_indexStableOffAddr: OP_AI_s(indexStablePtrOffAddrzh(r,x,y)); break;
2642 case i_readStableOffAddr: OP_AI_s(indexStablePtrOffAddrzh(r,x,y)); break;
2643 case i_writeStableOffAddr: OP_AIs_(writeStablePtrOffAddrzh(x,y,z)); break;
2645 case i_compareInteger:
2647 B* x = IntegerInsideByteArray(PopPtr());
2648 B* y = IntegerInsideByteArray(PopPtr());
2649 StgInt r = do_cmp(x,y);
2650 PushTaggedInt(r<0 ? -1 : (r>0 ? 1 : 0));
2653 case i_negateInteger: OP_Z_Z(neg); break;
2654 case i_plusInteger: OP_ZZ_Z(add); break;
2655 case i_minusInteger: OP_ZZ_Z(sub); break;
2656 case i_timesInteger: OP_ZZ_Z(mul); break;
2657 case i_quotRemInteger:
2659 B* x = IntegerInsideByteArray(PopPtr());
2660 B* y = IntegerInsideByteArray(PopPtr());
2661 int n = size_qrm(x,y);
2662 StgPtr q = CreateByteArrayToHoldInteger(n);
2663 StgPtr r = CreateByteArrayToHoldInteger(n);
2664 if (do_getsign(y)==0)
2665 return (raiseDiv0("quotRemInteger"));
2666 do_qrm(x,y,n,IntegerInsideByteArray(q),
2667 IntegerInsideByteArray(r));
2668 SloppifyIntegerEnd(q);
2669 SloppifyIntegerEnd(r);
2674 case i_intToInteger:
2676 int n = size_fromInt();
2677 StgPtr p = CreateByteArrayToHoldInteger(n);
2678 do_fromInt( PopTaggedInt(), n, IntegerInsideByteArray(p));
2682 case i_wordToInteger:
2684 int n = size_fromWord();
2685 StgPtr p = CreateByteArrayToHoldInteger(n);
2686 do_fromWord( PopTaggedWord(), n, IntegerInsideByteArray(p));
2690 case i_integerToInt: PushTaggedInt(do_toInt(
2691 IntegerInsideByteArray(PopPtr())
2695 case i_integerToWord: PushTaggedWord(do_toWord(
2696 IntegerInsideByteArray(PopPtr())
2700 case i_integerToFloat: PushTaggedFloat(do_toFloat(
2701 IntegerInsideByteArray(PopPtr())
2705 case i_integerToDouble: PushTaggedDouble(do_toDouble(
2706 IntegerInsideByteArray(PopPtr())
2710 case i_gtFloat: OP_FF_B(x>y); break;
2711 case i_geFloat: OP_FF_B(x>=y); break;
2712 case i_eqFloat: OP_FF_B(x==y); break;
2713 case i_neFloat: OP_FF_B(x!=y); break;
2714 case i_ltFloat: OP_FF_B(x<y); break;
2715 case i_leFloat: OP_FF_B(x<=y); break;
2716 case i_minFloat: OP__F(FLT_MIN); break;
2717 case i_maxFloat: OP__F(FLT_MAX); break;
2718 case i_radixFloat: OP__I(FLT_RADIX); break;
2719 case i_digitsFloat: OP__I(FLT_MANT_DIG); break;
2720 case i_minExpFloat: OP__I(FLT_MIN_EXP); break;
2721 case i_maxExpFloat: OP__I(FLT_MAX_EXP); break;
2722 case i_plusFloat: OP_FF_F(x+y); break;
2723 case i_minusFloat: OP_FF_F(x-y); break;
2724 case i_timesFloat: OP_FF_F(x*y); break;
2727 StgFloat x = PopTaggedFloat();
2728 StgFloat y = PopTaggedFloat();
2729 PushTaggedFloat(x/y);
2732 case i_negateFloat: OP_F_F(-x); break;
2733 case i_floatToInt: OP_F_I(x); break;
2734 case i_intToFloat: OP_I_F(x); break;
2735 case i_expFloat: OP_F_F(exp(x)); break;
2736 case i_logFloat: OP_F_F(log(x)); break;
2737 case i_sqrtFloat: OP_F_F(sqrt(x)); break;
2738 case i_sinFloat: OP_F_F(sin(x)); break;
2739 case i_cosFloat: OP_F_F(cos(x)); break;
2740 case i_tanFloat: OP_F_F(tan(x)); break;
2741 case i_asinFloat: OP_F_F(asin(x)); break;
2742 case i_acosFloat: OP_F_F(acos(x)); break;
2743 case i_atanFloat: OP_F_F(atan(x)); break;
2744 case i_sinhFloat: OP_F_F(sinh(x)); break;
2745 case i_coshFloat: OP_F_F(cosh(x)); break;
2746 case i_tanhFloat: OP_F_F(tanh(x)); break;
2747 case i_powerFloat: OP_FF_F(pow(x,y)); break;
2749 case i_encodeFloatZ:
2751 StgPtr sig = PopPtr();
2752 StgInt exp = PopTaggedInt();
2754 B__encodeFloat(IntegerInsideByteArray(sig), exp)
2758 case i_decodeFloatZ:
2760 StgFloat f = PopTaggedFloat();
2761 StgPtr sig = CreateByteArrayToHoldInteger(size_fltmantissa());
2763 B__decodeFloat(IntegerInsideByteArray(sig), &exp, f);
2769 case i_isNaNFloat: OP_F_B(isFloatNaN(x)); break;
2770 case i_isInfiniteFloat: OP_F_B(isFloatInfinite(x)); break;
2771 case i_isNegativeZeroFloat: OP_F_B(isFloatNegativeZero(x)); break;
2772 case i_isDenormalizedFloat: OP_F_B(isFloatDenormalized(x)); break;
2773 case i_gtDouble: OP_DD_B(x>y); break;
2774 case i_geDouble: OP_DD_B(x>=y); break;
2775 case i_eqDouble: OP_DD_B(x==y); break;
2776 case i_neDouble: OP_DD_B(x!=y); break;
2777 case i_ltDouble: OP_DD_B(x<y); break;
2778 case i_leDouble: OP_DD_B(x<=y) break;
2779 case i_minDouble: OP__D(DBL_MIN); break;
2780 case i_maxDouble: OP__D(DBL_MAX); break;
2781 case i_radixDouble: OP__I(FLT_RADIX); break;
2782 case i_digitsDouble: OP__I(DBL_MANT_DIG); break;
2783 case i_minExpDouble: OP__I(DBL_MIN_EXP); break;
2784 case i_maxExpDouble: OP__I(DBL_MAX_EXP); break;
2785 case i_plusDouble: OP_DD_D(x+y); break;
2786 case i_minusDouble: OP_DD_D(x-y); break;
2787 case i_timesDouble: OP_DD_D(x*y); break;
2788 case i_divideDouble:
2790 StgDouble x = PopTaggedDouble();
2791 StgDouble y = PopTaggedDouble();
2792 PushTaggedDouble(x/y);
2795 case i_negateDouble: OP_D_D(-x); break;
2796 case i_doubleToInt: OP_D_I(x); break;
2797 case i_intToDouble: OP_I_D(x); break;
2798 case i_doubleToFloat: OP_D_F(x); break;
2799 case i_floatToDouble: OP_F_F(x); break;
2800 case i_expDouble: OP_D_D(exp(x)); break;
2801 case i_logDouble: OP_D_D(log(x)); break;
2802 case i_sqrtDouble: OP_D_D(sqrt(x)); break;
2803 case i_sinDouble: OP_D_D(sin(x)); break;
2804 case i_cosDouble: OP_D_D(cos(x)); break;
2805 case i_tanDouble: OP_D_D(tan(x)); break;
2806 case i_asinDouble: OP_D_D(asin(x)); break;
2807 case i_acosDouble: OP_D_D(acos(x)); break;
2808 case i_atanDouble: OP_D_D(atan(x)); break;
2809 case i_sinhDouble: OP_D_D(sinh(x)); break;
2810 case i_coshDouble: OP_D_D(cosh(x)); break;
2811 case i_tanhDouble: OP_D_D(tanh(x)); break;
2812 case i_powerDouble: OP_DD_D(pow(x,y)); break;
2814 case i_encodeDoubleZ:
2816 StgPtr sig = PopPtr();
2817 StgInt exp = PopTaggedInt();
2819 B__encodeDouble(IntegerInsideByteArray(sig), exp)
2823 case i_decodeDoubleZ:
2825 StgDouble d = PopTaggedDouble();
2826 StgPtr sig = CreateByteArrayToHoldInteger(size_dblmantissa());
2828 B__decodeDouble(IntegerInsideByteArray(sig), &exp, d);
2834 case i_isNaNDouble: OP_D_B(isDoubleNaN(x)); break;
2835 case i_isInfiniteDouble: OP_D_B(isDoubleInfinite(x)); break;
2836 case i_isNegativeZeroDouble: OP_D_B(isDoubleNegativeZero(x)); break;
2837 case i_isDenormalizedDouble: OP_D_B(isDoubleDenormalized(x)); break;
2838 case i_isIEEEDouble:
2840 PushTaggedBool(rtsTrue);
2844 barf("Unrecognised primop1");
2851 /* For normal cases, return NULL and leave *return2 unchanged.
2852 To return the address of the next thing to enter,
2853 return the address of it and leave *return2 unchanged.
2854 To return a StgThreadReturnCode to the scheduler,
2855 set *return2 to it and return a non-NULL value.
2856 To cause a context switch, set context_switch (its a global),
2857 and optionally set hugsBlock to your rational.
2859 static void* enterBCO_primop2 ( int primop2code,
2860 int* /*StgThreadReturnCode* */ return2,
2863 HugsBlock *hugsBlock )
2866 /* A small concession: we need to allow ccalls,
2867 even in combined mode.
2869 if (primop2code != i_ccall_ccall_IO &&
2870 primop2code != i_ccall_stdcall_IO)
2871 barf("enterBCO_primop2 in combined mode");
2874 switch (primop2code) {
2875 case i_raise: /* raise#{err} */
2877 StgClosure* err = PopCPtr();
2878 return (raiseAnError(err));
2881 /*------------------------------------------------------------------------
2882 Insert and Remove primitives on Rows. This is important stuff for
2883 XMlambda, these prims are called *all* the time. That's the reason
2884 for all the specialized versions of the basic instructions.
2885 note: A Gc might move rows around => allocate first, than pop the arguments.
2886 ------------------------------------------------------------------------*/
2888 /*------------------------------------------------------------------------
2889 i_rowInsertAt: insert an element into a row
2890 ------------------------------------------------------------------------*/
2898 /* allocate a new row before popping arguments */
2899 StgMutArrPtrs* row = stgCast(StgMutArrPtrs*,stackPtr(0));
2900 StgMutArrPtrs* newRow
2901 = stgCast(StgMutArrPtrs*,allocate(sizeofW(StgMutArrPtrs) + row->ptrs + 1));
2902 SET_HDR(newRow,&MUT_ARR_PTRS_FROZEN_info,CCCS);
2904 /* pop row again and pop index and value */
2905 row = stgCast(StgMutArrPtrs*,PopPtr());
2909 i = PopTaggedWord();
2914 /* copy the fields, inserting the new value */
2915 for (j = 0; j < i; j++) {
2916 newRow->payload[j] = row->payload[j];
2918 newRow->payload[i] = x;
2919 for (j = i+1; j <= n; j++)
2921 newRow->payload[j] = row->payload[j-1];
2924 PushPtr(stgCast(StgPtr,newRow));
2928 /*------------------------------------------------------------------------
2929 i_rowChainInsert: behaves like a chain of [i_rowInsertAt] calls. This
2930 instruction is vital for XMLambda since we would otherwise allocate
2931 a lot of intermediate rows.
2932 It assumes that the RTS has no NULL pointers.
2933 It behaves 'optimal' if the witnesses are ordered, (lowest on the
2934 bottom of the stack).
2935 ------------------------------------------------------------------------*/
2937 case i_rowChainInsert:
2939 StgWord witness, topWitness;
2944 /* pop the number of arguments (=witness/value pairs) */
2945 StgWord n = PopTaggedWord();
2947 /* allocate a new row before popping boxed arguments */
2948 StgMutArrPtrs* row = stgCast(StgMutArrPtrs*,stackPtr(0));
2949 StgMutArrPtrs* newRow
2950 = stgCast(StgMutArrPtrs*,allocate(sizeofW(StgMutArrPtrs) + n + row->ptrs));
2951 SET_HDR(newRow,&MUT_ARR_PTRS_FROZEN_info,CCCS);
2953 /* pop the row and assign again (it may have moved during gc!) */
2954 row = stgCast(StgMutArrPtrs*,PopPtr());
2955 newRow->ptrs = n + row->ptrs;
2957 /* zero the fields */
2958 for (i = 0; i < newRow->ptrs; i++)
2960 newRow->payload[i] = ROW_HOLE;
2963 /* insert all values */
2964 topWitness = 0; /*invariant: 1 + maximal witness */
2965 for (i = 0; i < n; i++)
2967 witness = PopTaggedWord();
2969 if (witness < topWitness)
2971 /* shoot, unordered witnesses, we have to bump up everything */
2972 for (j = topWitness; j > witness; j--)
2974 newRow->payload[j] = newRow->payload[j-1];
2980 topWitness = witness+1;
2983 ASSERT(topWitness <= n);
2984 ASSERT(witness < n);
2985 newRow->payload[witness] = value;
2988 /* copy the values from the old row into the holes */
2989 for (j =0, i = 0; i < row->ptrs; j++,i++)
2991 while (newRow->payload[j] != ROW_HOLE) j++;
2993 newRow->payload[j] = row->payload[i];
2996 /* push the result */
2997 PushPtr(stgCast(StgPtr,newRow));
3001 /*------------------------------------------------------------------------
3002 i_rowChainBuild: exactly as [i_rowChainInsert] but builds a row from scratch.
3003 ------------------------------------------------------------------------*/
3004 case i_rowChainBuild:
3006 StgWord witness, topWitness;
3011 /* pop the number of arguments (=witness/value pairs) */
3012 StgWord n = PopTaggedWord();
3014 /* allocate a new row before popping boxed arguments */
3015 StgMutArrPtrs* newRow
3016 = stgCast(StgMutArrPtrs*,allocate(sizeofW(StgMutArrPtrs) + n));
3017 SET_HDR(newRow,&MUT_ARR_PTRS_FROZEN_info,CCCS);
3020 /* insert all values */
3021 topWitness = 0; /*invariant: 1 + maximal witness */
3022 for (i = 0; i < n; i++)
3024 witness = PopTaggedWord();
3026 if (witness < topWitness)
3028 /* shoot, unordered witnesses, we have to bump up everything */
3029 for (j = topWitness; j > witness; j--)
3031 newRow->payload[j] = newRow->payload[j-1];
3037 topWitness = witness+1;
3040 ASSERT(topWitness <= n);
3041 ASSERT(witness < n);
3042 newRow->payload[witness] = value;
3045 /* push the result */
3046 PushPtr(stgCast(StgPtr,newRow));
3050 /*------------------------------------------------------------------------
3051 i_rowRemoveAt: remove an element from a row
3052 ------------------------------------------------------------------------*/
3059 /* allocate new row before popping the arguments */
3060 StgMutArrPtrs* row = stgCast(StgMutArrPtrs*,stackPtr(0));
3061 StgMutArrPtrs* newRow
3062 = stgCast(StgMutArrPtrs*,allocate(sizeofW(StgMutArrPtrs) + row->ptrs - 1));
3063 SET_HDR(newRow,&MUT_ARR_PTRS_FROZEN_info,CCCS);
3065 /* pop row again and pop the index */
3066 row = stgCast(StgMutArrPtrs*,PopPtr());
3070 i = PopTaggedWord();
3074 /* copy the fields, except for the removed value. */
3075 for (j = 0; j < i; j++) {
3076 newRow->payload[j] = row->payload[j];
3078 for (j = i+1; j < n; j++)
3080 newRow->payload[j-1] = row->payload[j];
3083 PushCPtr(row->payload[i]);
3084 PushPtr(stgCast(StgPtr,newRow));
3088 /*------------------------------------------------------------------------
3089 i_rowChainRemove: behaves like a chain of [i_rowRemoveAt] calls. Again,
3090 this is a vital instruction to avoid lots of intermediate rows.
3091 It behaves 'optimal' if the witnessses are ordered, lowest on the
3092 bottom of the stack.
3093 The implementation is quite dirty, blame Daan for this :-)
3094 (It overwrites witnesses on the stack with results and marks pointers
3095 using their lowest bit.)
3096 ------------------------------------------------------------------------*/
3097 #define MARK(p) (stgCast(StgClosure*,(stgCast(StgWord,(p)) | 0x01)))
3098 #define UNMARK(p) (stgCast(StgClosure*,(stgCast(StgWord,(p)) & ~0x01)))
3099 #define ISMARKED(p) ((stgCast(StgWord,(p)) & 0x01) == 0x01)
3101 case i_rowChainRemove:
3103 const nat sizeofTaggedWord = sizeofW(StgWord) + sizeofW(StackTag);
3111 /* pop number of arguments (=witnesses) */
3112 StgWord n = PopTaggedWord();
3114 /* allocate new row before popping boxed arguments */
3115 StgMutArrPtrs* row = stgCast(StgMutArrPtrs*,stackPtr(0));
3116 StgMutArrPtrs* newRow
3117 = stgCast(StgMutArrPtrs*,allocate(sizeofW(StgMutArrPtrs) + row->ptrs - n));
3118 SET_HDR(newRow,&MUT_ARR_PTRS_FROZEN_info,CCCS);
3120 /* pop row and assign again (gc might have moved it) */
3121 row = stgCast(StgMutArrPtrs*,PopPtr());
3122 newRow->ptrs = row->ptrs - n;
3123 ASSERT( row->ptrs > n );
3125 /* 'push' all elements that are removed */
3126 base = n*sizeofTaggedWord;
3127 minWitness = row->ptrs;
3128 for (i = 1; i <= n; i++)
3132 witness = taggedStackWord( base - i*sizeofTaggedWord );
3133 if (witness >= minWitness)
3135 /* shoot, unordered witnesses, we have to search for the value */
3138 count = witness - minWitness;
3139 witness = minWitness;
3142 do{ witness++; } while (ISMARKED(row->payload[witness]));
3143 if (count == 0) break;
3149 minWitness = witness;
3151 ASSERT( witness < row->ptrs );
3152 ASSERT( !ISMARKED(row->payload[witness]) );
3154 /* mark the element */
3155 value = row->payload[witness];
3156 row->payload[witness] = MARK(value);
3158 /* set the value in the stack (overwriting old witnesses!) */
3159 setStackPtr( base - i*sizeofW(StgPtr), stgCast(StgPtr,value) );
3162 /* pop the garbage from the stack */
3163 gSp = gSp + base - n*sizeofW(StgPtr);
3165 /* copy all remaining elements and clear the marks */
3166 for (j = 0, i = 0; i < newRow->ptrs; j++,i++)
3168 while (ISMARKED(row->payload[j]))
3170 row->payload[j] = UNMARK(row->payload[j]);
3173 newRow->payload[i] = row->payload[j];
3177 while (j < row->ptrs)
3179 value = row->payload[j];
3180 if (ISMARKED(value)) row->payload[j] = UNMARK(value);
3185 for (i = 0; i < row->ptrs; i++)
3187 ASSERT(!ISMARKED(row->payload[i]));
3191 /* and push the result row */
3192 PushPtr(stgCast(StgPtr,newRow));
3196 /*------------------------------------------------------------------------
3197 i_rowChainSelect: behaves exactly like [i_rowChainRemove] but doesn't return
3198 the resulting row, only the removed elements.
3199 ------------------------------------------------------------------------*/
3200 case i_rowChainSelect:
3202 const nat sizeofTaggedWord = sizeofW(StgWord) + sizeofW(StackTag);
3208 /* pop number of arguments (=witnesses) and row*/
3209 StgWord n = PopTaggedWord();
3210 StgMutArrPtrs* row = stgCast(StgMutArrPtrs*,PopPtr());
3211 ASSERT( row->ptrs > n );
3213 /* 'push' all elements that are removed */
3214 base = n*sizeofTaggedWord;
3215 minWitness = row->ptrs;
3216 for (i = 1; i <= n; i++)
3220 witness = taggedStackWord( base - i*sizeofTaggedWord );
3221 if (witness >= minWitness)
3223 /* shoot, unordered witnesses, we have to search for the value */
3226 count = witness - minWitness;
3227 witness = minWitness;
3230 do{ witness++; } while (ISMARKED(row->payload[witness]));
3231 if (count == 0) break;
3237 minWitness = witness;
3239 ASSERT( witness < row->ptrs );
3240 ASSERT( !ISMARKED(row->payload[witness]) );
3242 /* mark the element */
3243 value = row->payload[witness];
3244 row->payload[witness] = MARK(value);
3246 /* set the value in the stack (overwriting old witnesses!) */
3247 setStackPtr( base - i*sizeofW(StgPtr), stgCast(StgPtr,value) );
3250 /* pop the garbage from the stack */
3251 gSp = gSp + base - n*sizeofW(StgPtr);
3253 /* unmark elements */
3254 for( i = 0; i < row->ptrs; i++)
3256 value = row->payload[i];
3257 if (ISMARKED(value)) row->payload[i] = UNMARK(value);
3261 for (i = 0; i < row->ptrs; i++)
3263 ASSERT(!ISMARKED(row->payload[i]));
3269 #endif /* XMLAMBDA */
3273 StgClosure* init = PopCPtr();
3275 = stgCast(StgMutVar*,allocate(sizeofW(StgMutVar)));
3276 SET_HDR(mv,&MUT_VAR_info,CCCS);
3278 PushPtr(stgCast(StgPtr,mv));
3283 StgMutVar* mv = stgCast(StgMutVar*,PopPtr());
3289 StgMutVar* mv = stgCast(StgMutVar*,PopPtr());
3290 StgClosure* value = PopCPtr();
3296 nat n = PopTaggedInt(); /* or Word?? */
3297 StgClosure* init = PopCPtr();
3298 StgWord size = sizeofW(StgMutArrPtrs) + n;
3301 = stgCast(StgMutArrPtrs*,allocate(size));
3302 SET_HDR(arr,&MUT_ARR_PTRS_info,CCCS);
3304 for (i = 0; i < n; ++i) {
3305 arr->payload[i] = init;
3307 PushPtr(stgCast(StgPtr,arr));
3313 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
3314 nat i = PopTaggedInt(); /* or Word?? */
3315 StgWord n = arr->ptrs;
3317 return (raiseIndex("{index,read}Array"));
3319 PushCPtr(arr->payload[i]);
3324 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
3325 nat i = PopTaggedInt(); /* or Word? */
3326 StgClosure* v = PopCPtr();
3327 StgWord n = arr->ptrs;
3329 return (raiseIndex("{index,read}Array"));
3331 arr->payload[i] = v;
3335 case i_sizeMutableArray:
3337 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
3338 PushTaggedInt(arr->ptrs);
3341 case i_unsafeFreezeArray:
3343 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
3344 SET_INFO(arr,&MUT_ARR_PTRS_FROZEN_info);
3345 PushPtr(stgCast(StgPtr,arr));
3348 case i_unsafeFreezeByteArray:
3350 /* Delightfully simple :-) */
3354 case i_sameMutableArray:
3355 case i_sameMutableByteArray:
3357 StgPtr x = PopPtr();
3358 StgPtr y = PopPtr();
3359 PushTaggedBool(x==y);
3363 case i_newByteArray:
3365 nat n = PopTaggedInt(); /* or Word?? */
3366 StgInt words = (n+sizeof(W_)-1)/sizeof(W_);
3367 StgWord size = sizeofW(StgArrWords) + words;
3368 StgArrWords* arr = stgCast(StgArrWords*,allocate(size));
3369 SET_HDR(arr,&ARR_WORDS_info,CCCS);
3373 for (i = 0; i < n; ++i) {
3374 arr->payload[i] = 0xdeadbeef;
3377 PushPtr(stgCast(StgPtr,arr));
3381 /* Most of these generate alignment warnings on Sparcs and similar architectures.
3382 * These are harmless and are caused by the cast to C* in BYTE_ARR_CTS.
3384 case i_indexCharArray:
3385 OP_mI_ty(Char,"indexCharArray", indexCharArrayzh(r,x,i)); break;
3386 case i_readCharArray:
3387 OP_mI_ty(Char,"readCharArray", readCharArrayzh(r,x,i)); break;
3388 case i_writeCharArray:
3389 OP_mIty_(Char,"writeCharArray", writeCharArrayzh(x,i,z)); break;
3391 case i_indexIntArray:
3392 OP_mI_ty(Int,"indexIntArray", indexIntArrayzh(r,x,i)); break;
3393 case i_readIntArray:
3394 OP_mI_ty(Int,"readIntArray", readIntArrayzh(r,x,i)); break;
3395 case i_writeIntArray:
3396 OP_mIty_(Int,"writeIntArray", writeIntArrayzh(x,i,z)); break;
3398 case i_indexAddrArray:
3399 OP_mI_ty(Addr,"indexAddrArray", indexAddrArrayzh(r,x,i)); break;
3400 case i_readAddrArray:
3401 OP_mI_ty(Addr,"readAddrArray", readAddrArrayzh(r,x,i)); break;
3402 case i_writeAddrArray:
3403 OP_mIty_(Addr,"writeAddrArray", writeAddrArrayzh(x,i,z)); break;
3405 case i_indexFloatArray:
3406 OP_mI_ty(Float,"indexFloatArray", indexFloatArrayzh(r,x,i)); break;
3407 case i_readFloatArray:
3408 OP_mI_ty(Float,"readFloatArray", readFloatArrayzh(r,x,i)); break;
3409 case i_writeFloatArray:
3410 OP_mIty_(Float,"writeFloatArray", writeFloatArrayzh(x,i,z)); break;
3412 case i_indexDoubleArray:
3413 OP_mI_ty(Double,"indexDoubleArray", indexDoubleArrayzh(r,x,i)); break;
3414 case i_readDoubleArray:
3415 OP_mI_ty(Double,"readDoubleArray", readDoubleArrayzh(r,x,i)); break;
3416 case i_writeDoubleArray:
3417 OP_mIty_(Double,"writeDoubleArray", writeDoubleArrayzh(x,i,z)); break;
3420 #ifdef PROVIDE_STABLE
3421 case i_indexStableArray:
3422 OP_mI_ty(StablePtr,"indexStableArray", indexStablePtrArrayzh(r,x,i)); break;
3423 case i_readStableArray:
3424 OP_mI_ty(StablePtr,"readStableArray", readStablePtrArrayzh(r,x,i)); break;
3425 case i_writeStableArray:
3426 OP_mIty_(StablePtr,"writeStableArray", writeStablePtrArrayzh(x,i,z)); break;
3432 #ifdef PROVIDE_COERCE
3433 case i_unsafeCoerce:
3435 /* Another nullop */
3439 #ifdef PROVIDE_PTREQUALITY
3440 case i_reallyUnsafePtrEquality:
3441 { /* identical to i_sameRef */
3442 StgPtr x = PopPtr();
3443 StgPtr y = PopPtr();
3444 PushTaggedBool(x==y);
3448 #ifdef PROVIDE_FOREIGN
3449 /* ForeignObj# operations */
3450 case i_mkForeignObj:
3452 StgForeignObj *result
3453 = stgCast(StgForeignObj*,allocate(sizeofW(StgForeignObj)));
3454 SET_HDR(result,&FOREIGN_info,CCCS);
3455 result -> data = PopTaggedAddr();
3456 PushPtr(stgCast(StgPtr,result));
3459 #endif /* PROVIDE_FOREIGN */
3464 = stgCast(StgWeak*,allocate(sizeofW(StgWeak)));
3465 SET_HDR(w, &WEAK_info, CCCS);
3467 w->value = PopCPtr();
3468 w->finaliser = PopCPtr();
3469 w->link = weak_ptr_list;
3471 IF_DEBUG(weak, fprintf(stderr,"New weak pointer at %p\n",w));
3472 PushPtr(stgCast(StgPtr,w));
3477 StgWeak *w = stgCast(StgWeak*,PopPtr());
3478 if (w->header.info == &WEAK_info) {
3479 PushCPtr(w->value); /* last result */
3480 PushTaggedInt(1); /* first result */
3482 PushPtr(stgCast(StgPtr,w));
3483 /* ToDo: error thunk would be better */
3488 #endif /* PROVIDE_WEAK */
3490 case i_makeStablePtr:
3492 StgPtr p = PopPtr();
3493 StgStablePtr sp = getStablePtr ( p );
3494 PushTaggedStablePtr(sp);
3497 case i_deRefStablePtr:
3500 StgStablePtr sp = PopTaggedStablePtr();
3501 p = deRefStablePtr(sp);
3505 case i_freeStablePtr:
3507 StgStablePtr sp = PopTaggedStablePtr();
3512 case i_createAdjThunkARCH:
3514 StgStablePtr stableptr = PopTaggedStablePtr();
3515 StgAddr typestr = PopTaggedAddr();
3516 StgChar callconv = PopTaggedChar();
3517 StgAddr adj_thunk = createAdjThunk(stableptr,typestr,callconv);
3518 PushTaggedAddr(adj_thunk);
3524 StgInt n = prog_argc;
3530 StgInt n = PopTaggedInt();
3531 StgAddr a = (StgAddr)prog_argv[n];
3538 StgMVar *mvar = stgCast(StgMVar*,allocate(sizeofW(StgMVar)));
3539 SET_INFO(mvar,&EMPTY_MVAR_info);
3540 mvar->head = mvar->tail = (StgTSO *)&END_TSO_QUEUE_closure;
3541 mvar->value = stgCast(StgClosure*,&END_TSO_QUEUE_closure);
3542 PushPtr(stgCast(StgPtr,mvar));
3547 StgMVar *mvar = (StgMVar*)PopCPtr();
3548 if (GET_INFO(mvar) == &EMPTY_MVAR_info) {
3550 /* The MVar is empty. Attach ourselves to the TSO's
3553 if (mvar->head == (StgTSO *)&END_TSO_QUEUE_closure) {
3554 mvar->head = cap->rCurrentTSO;
3556 mvar->tail->link = cap->rCurrentTSO;
3558 cap->rCurrentTSO->link = (StgTSO *)&END_TSO_QUEUE_closure;
3559 cap->rCurrentTSO->why_blocked = BlockedOnMVar;
3560 cap->rCurrentTSO->block_info.closure = (StgClosure *)mvar;
3561 mvar->tail = cap->rCurrentTSO;
3563 /* At this point, the top-of-stack holds the MVar,
3564 and underneath is the world token (). So the
3565 stack is in the same state as when primTakeMVar
3566 was entered (primTakeMVar is handwritten bytecode).
3567 Push obj, which is this BCO, and return to the
3568 scheduler. When the MVar is filled, the scheduler
3569 will re-enter primTakeMVar, with the args still on
3570 the top of the stack.
3572 PushCPtr((StgClosure*)(*bco));
3573 *return2 = ThreadBlocked;
3574 return (void*)(1+(char*)(NULL));
3577 PushCPtr(mvar->value);
3578 mvar->value = (StgClosure *)&END_TSO_QUEUE_closure;
3579 SET_INFO(mvar,&EMPTY_MVAR_info);
3585 StgMVar* mvar = stgCast(StgMVar*,PopPtr());
3586 StgClosure* value = PopCPtr();
3587 if (GET_INFO(mvar) == &FULL_MVAR_info) {
3588 return (makeErrorCall("putMVar {full MVar}"));
3590 /* wake up the first thread on the
3591 * queue, it will continue with the
3592 * takeMVar operation and mark the
3595 mvar->value = value;
3597 if (mvar->head != (StgTSO *)&END_TSO_QUEUE_closure) {
3598 ASSERT(mvar->head->why_blocked == BlockedOnMVar);
3599 mvar->head = unblockOne(mvar->head);
3600 if (mvar->head == (StgTSO *)&END_TSO_QUEUE_closure) {
3601 mvar->tail = (StgTSO *)&END_TSO_QUEUE_closure;
3605 /* unlocks the MVar in the SMP case */
3606 SET_INFO(mvar,&FULL_MVAR_info);
3608 /* yield for better communication performance */
3614 { /* identical to i_sameRef */
3615 StgMVar* x = (StgMVar*)PopPtr();
3616 StgMVar* y = (StgMVar*)PopPtr();
3617 PushTaggedBool(x==y);
3620 #ifdef PROVIDE_CONCURRENT
3623 StgClosure* closure;
3626 closure = PopCPtr();
3627 tso = createGenThread (RtsFlags.GcFlags.initialStkSize,closure);
3629 scheduleThread(tso);
3631 /* Later: Change to use tso as the ThreadId */
3632 PushTaggedWord(tid);
3638 StgWord n = PopTaggedWord();
3642 // Map from ThreadId to Thread Structure */
3643 for (t = all_threads; t != END_TSO_QUEUE; t = t->global_link) {
3652 while (tso->what_next == ThreadRelocated) {
3657 if (tso == cap->rCurrentTSO) { /* suicide */
3658 *return2 = ThreadFinished;
3659 return (void*)(1+(char*)(NULL));
3663 case i_raiseInThread:
3664 barf("raiseInThread");
3665 ASSERT(0); /* not (yet) supported */
3668 StgInt n = PopTaggedInt();
3670 hugsBlock->reason = BlockedOnDelay;
3671 hugsBlock->delay = n;
3676 StgInt n = PopTaggedInt();
3678 hugsBlock->reason = BlockedOnRead;
3679 hugsBlock->delay = n;
3684 StgInt n = PopTaggedInt();
3686 hugsBlock->reason = BlockedOnWrite;
3687 hugsBlock->delay = n;
3692 /* The definition of yield include an enter right after
3693 * the primYield, at which time context_switch is tested.
3700 StgWord tid = cap->rCurrentTSO->id;
3701 PushTaggedWord(tid);
3704 case i_cmpThreadIds:
3706 StgWord tid1 = PopTaggedWord();
3707 StgWord tid2 = PopTaggedWord();
3708 if (tid1 < tid2) PushTaggedInt(-1);
3709 else if (tid1 > tid2) PushTaggedInt(1);
3710 else PushTaggedInt(0);
3713 #endif /* PROVIDE_CONCURRENT */
3718 CFunDescriptor descriptor;
3719 void (*funPtr)(void);
3721 StgWord offset = PopTaggedWord(); /* offset into bco nonptr section */
3722 funPtr = PopTaggedAddr();
3724 ASSERT(funPtr != NULL);
3726 /* copy the complete callinfo, the bco might move during GC! */
3727 callInfo = *stgCast(CallInfo*, (*bco)->payload + (*bco)->n_ptrs + offset);
3729 /* copy info to a CFunDescriptor. just for compatibility. */
3730 descriptor.num_args = callInfo.argCount;
3731 descriptor.arg_tys = callInfo.data;
3732 descriptor.num_results = callInfo.resultCount;
3733 descriptor.result_tys = callInfo.data + callInfo.argCount + 1;
3736 switch (ccall( &descriptor, funPtr, bco, callInfo.callConv, cap ))
3739 case 1: barf( "unhandled type or too many args/results in ccall"); break;
3740 case 2: barf("ccall not configured correctly for this platform"); break;
3741 default: barf("unknown return code from ccall"); break;
3748 case i_ccall_ccall_Id:
3749 case i_ccall_ccall_IO:
3750 case i_ccall_stdcall_Id:
3751 case i_ccall_stdcall_IO:
3754 CFunDescriptor* descriptor;
3755 void (*funPtr)(void);
3757 descriptor = PopTaggedAddr();
3758 funPtr = PopTaggedAddr();
3759 cc = (primop2code == i_ccall_stdcall_Id ||
3760 primop2code == i_ccall_stdcall_IO)
3762 r = ccall(descriptor,funPtr,bco,cc,cap);
3765 return makeErrorCall(
3766 "unhandled type or too many args/results in ccall");
3768 barf("ccall not configured correctly for this platform");
3769 barf("unknown return code from ccall");
3772 barf("Unrecognised primop2");
3778 /* -----------------------------------------------------------------------------
3779 * ccall support code:
3780 * marshall moves args from C stack to Haskell stack
3781 * unmarshall moves args from Haskell stack to C stack
3782 * argSize calculates how much gSpace you need on the C stack
3783 * ---------------------------------------------------------------------------*/
3785 /* Pop arguments off the C stack and Push them onto the Hugs stack.
3786 * Used when preparing for C calling Haskell or in regSponse to
3787 * Haskell calling C.
3789 nat marshall(char arg_ty, void* arg)
3793 PushTaggedInt(*((int*)arg));
3794 return ARG_SIZE(INT_TAG);
3797 PushTaggedInteger(*((mpz_ptr*)arg));
3798 return ARG_SIZE(INTEGER_TAG);
3801 PushTaggedWord(*((unsigned int*)arg));
3802 return ARG_SIZE(WORD_TAG);
3804 PushTaggedChar(*((char*)arg));
3805 return ARG_SIZE(CHAR_TAG);
3807 PushTaggedFloat(*((float*)arg));
3808 return ARG_SIZE(FLOAT_TAG);
3810 PushTaggedDouble(*((double*)arg));
3811 return ARG_SIZE(DOUBLE_TAG);
3813 PushTaggedAddr(*((void**)arg));
3814 return ARG_SIZE(ADDR_TAG);
3816 PushTaggedStablePtr(*((StgStablePtr*)arg));
3817 return ARG_SIZE(STABLE_TAG);
3818 #ifdef PROVIDE_FOREIGN
3820 /* Not allowed in this direction - you have to
3821 * call makeForeignPtr explicitly
3823 barf("marshall: ForeignPtr#\n");
3828 /* Not allowed in this direction */
3829 barf("marshall: [Mutable]ByteArray#\n");
3832 barf("marshall: unrecognised arg type %d\n",arg_ty);
3837 /* Pop arguments off the Hugs stack and Push them onto the C stack.
3838 * Used when preparing for Haskell calling C or in regSponse to
3839 * C calling Haskell.
3841 nat unmarshall(char res_ty, void* res)
3845 *((int*)res) = PopTaggedInt();
3846 return ARG_SIZE(INT_TAG);
3849 *((mpz_ptr*)res) = PopTaggedInteger();
3850 return ARG_SIZE(INTEGER_TAG);
3853 *((unsigned int*)res) = PopTaggedWord();
3854 return ARG_SIZE(WORD_TAG);
3856 *((int*)res) = PopTaggedChar();
3857 return ARG_SIZE(CHAR_TAG);
3859 *((float*)res) = PopTaggedFloat();
3860 return ARG_SIZE(FLOAT_TAG);
3862 *((double*)res) = PopTaggedDouble();
3863 return ARG_SIZE(DOUBLE_TAG);
3865 *((void**)res) = PopTaggedAddr();
3866 return ARG_SIZE(ADDR_TAG);
3868 *((StgStablePtr*)res) = PopTaggedStablePtr();
3869 return ARG_SIZE(STABLE_TAG);
3870 #ifdef PROVIDE_FOREIGN
3873 StgForeignObj *result = stgCast(StgForeignObj*,PopPtr());
3874 *((void**)res) = result->data;
3875 return sizeofW(StgPtr);
3881 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
3882 *((void**)res) = stgCast(void*,&(arr->payload));
3883 return sizeofW(StgPtr);
3886 barf("unmarshall: unrecognised result type %d\n",res_ty);
3890 nat argSize( const char* ks )
3893 for( ; *ks != '\0'; ++ks) {
3896 sz += sizeof(StgWord) * ARG_SIZE(INT_TAG);
3900 sz += sizeof(StgWord) * ARG_SIZE(INTEGER_TAG);
3904 sz += sizeof(StgWord) * ARG_SIZE(WORD_TAG);
3907 sz += sizeof(StgWord) * ARG_SIZE(CHAR_TAG);
3910 sz += sizeof(StgWord) * ARG_SIZE(FLOAT_TAG);
3913 sz += sizeof(StgWord) * ARG_SIZE(DOUBLE_TAG);
3916 sz += sizeof(StgWord) * ARG_SIZE(ADDR_TAG);
3919 sz += sizeof(StgWord) * ARG_SIZE(STABLE_TAG);
3921 #ifdef PROVIDE_FOREIGN
3926 sz += sizeof(StgPtr);
3929 barf("argSize: unrecognised result type %d\n",*ks);
3937 /* -----------------------------------------------------------------------------
3938 * encode/decode Float/Double code for standalone Hugs
3939 * Code based on the HBC code (lib/fltcode.c) and more recently GHC
3940 * (ghc/rts/StgPrimFloat.c)
3941 * ---------------------------------------------------------------------------*/
3943 #if IEEE_FLOATING_POINT
3944 #define MY_DMINEXP ((DBL_MIN_EXP) - (DBL_MANT_DIG) - 1)
3945 /* DMINEXP is defined in values.h on Linux (for example) */
3946 #define DHIGHBIT 0x00100000
3947 #define DMSBIT 0x80000000
3949 #define MY_FMINEXP ((FLT_MIN_EXP) - (FLT_MANT_DIG) - 1)
3950 #define FHIGHBIT 0x00800000
3951 #define FMSBIT 0x80000000
3953 #error The following code doesnt work in a non-IEEE FP environment
3956 #ifdef WORDS_BIGENDIAN
3965 StgDouble B__encodeDouble (B* s, I_ e) /* result = s * 2^e */
3970 /* Convert a B to a double; knows a lot about internal rep! */
3971 for(r = 0.0, i = s->used-1; i >= 0; i--)
3972 r = (r * B_BASE_FLT) + s->stuff[i];
3974 /* Now raise to the exponent */
3975 if ( r != 0.0 ) /* Lennart suggests this avoids a bug in MIPS's ldexp */
3978 /* handle the sign */
3979 if (s->sign < 0) r = -r;
3986 #if ! FLOATS_AS_DOUBLES
3987 StgFloat B__encodeFloat (B* s, I_ e) /* result = s * 2^e */
3992 /* Convert a B to a float; knows a lot about internal rep! */
3993 for(r = 0.0, i = s->used-1; i >= 0; i--)
3994 r = (r * B_BASE_FLT) + s->stuff[i];
3996 /* Now raise to the exponent */
3997 if ( r != 0.0 ) /* Lennart suggests this avoids a bug in MIPS's ldexp */
4000 /* handle the sign */
4001 if (s->sign < 0) r = -r;
4005 #endif /* FLOATS_AS_DOUBLES */
4009 /* This only supports IEEE floating point */
4010 void B__decodeDouble (B* man, I_* exp, StgDouble dbl)
4012 /* Do some bit fiddling on IEEE */
4013 nat low, high; /* assuming 32 bit ints */
4015 union { double d; int i[2]; } u; /* assuming 32 bit ints, 64 bit double */
4017 u.d = dbl; /* grab chunks of the double */
4021 ASSERT(B_BASE == 256);
4023 /* Assume that the supplied B is the right size */
4026 if (low == 0 && (high & ~DMSBIT) == 0) {
4027 man->sign = man->used = 0;
4032 iexp = ((high >> 20) & 0x7ff) + MY_DMINEXP;
4036 if (iexp != MY_DMINEXP) /* don't add hidden bit to denorms */
4040 /* A denorm, normalize the mantissa */
4041 while (! (high & DHIGHBIT)) {
4051 man->stuff[7] = (((W_)high) >> 24) & 0xff;
4052 man->stuff[6] = (((W_)high) >> 16) & 0xff;
4053 man->stuff[5] = (((W_)high) >> 8) & 0xff;
4054 man->stuff[4] = (((W_)high) ) & 0xff;
4056 man->stuff[3] = (((W_)low) >> 24) & 0xff;
4057 man->stuff[2] = (((W_)low) >> 16) & 0xff;
4058 man->stuff[1] = (((W_)low) >> 8) & 0xff;
4059 man->stuff[0] = (((W_)low) ) & 0xff;
4061 if (sign < 0) man->sign = -1;
4063 do_renormalise(man);
4067 #if ! FLOATS_AS_DOUBLES
4068 void B__decodeFloat (B* man, I_* exp, StgFloat flt)
4070 /* Do some bit fiddling on IEEE */
4071 int high, sign; /* assuming 32 bit ints */
4072 union { float f; int i; } u; /* assuming 32 bit float and int */
4074 u.f = flt; /* grab the float */
4077 ASSERT(B_BASE == 256);
4079 /* Assume that the supplied B is the right size */
4082 if ((high & ~FMSBIT) == 0) {
4083 man->sign = man->used = 0;
4088 *exp = ((high >> 23) & 0xff) + MY_FMINEXP;
4092 if (*exp != MY_FMINEXP) /* don't add hidden bit to denorms */
4096 /* A denorm, normalize the mantissa */
4097 while (! (high & FHIGHBIT)) {
4102 man->stuff[3] = (((W_)high) >> 24) & 0xff;
4103 man->stuff[2] = (((W_)high) >> 16) & 0xff;
4104 man->stuff[1] = (((W_)high) >> 8) & 0xff;
4105 man->stuff[0] = (((W_)high) ) & 0xff;
4107 if (sign < 0) man->sign = -1;
4109 do_renormalise(man);
4112 #endif /* FLOATS_AS_DOUBLES */
4113 #endif /* INTERPRETER */