2 /* -----------------------------------------------------------------------------
5 * Copyright (c) 1994-2000.
7 * $RCSfile: Interpreter.c,v $
9 * $Date: 2000/12/11 12:55:43 $
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 StgFloat B__encodeFloat (B* s, I_ e);
155 void B__decodeFloat (B* man, I_* exp, StgFloat flt);
156 StgPtr CreateByteArrayToHoldInteger ( int );
157 B* IntegerInsideByteArray ( StgPtr );
158 void SloppifyIntegerEnd ( StgPtr );
163 #define gSp MainRegTable.rSp
164 #define gSu MainRegTable.rSu
165 #define gSpLim MainRegTable.rSpLim
168 /* Macros to save/load local state. */
170 #define SSS { tSp=gSp = xSp; tSu=gSu = xSu; tSpLim=gSpLim = xSpLim; }
171 #define LLL { tSp=xSp = gSp; tSu=xSu = gSu; tSpLim=xSpLim = gSpLim; }
173 #define SSS { gSp = xSp; gSu = xSu; gSpLim = xSpLim; }
174 #define LLL { xSp = gSp; xSu = gSu; xSpLim = gSpLim; }
177 #define RETURN(vvv) { \
178 StgThreadReturnCode retVal=(vvv); \
180 cap->rCurrentTSO->sp = gSp; \
181 cap->rCurrentTSO->su = gSu; \
186 /* Macros to operate directly on the pulled-out machine state.
187 These mirror some of the small procedures used in the primop code
188 below, except you have to be careful about side effects,
189 ie xPushPtr(xStackPtr(n)) won't work! It certainly isn't the
190 same as PushPtr(StackPtr(n)). Also note that (1) some of
191 the macros, in particular xPopTagged*, do not make the tag
192 sanity checks that their non-x cousins do, and (2) some of
193 the macros depend critically on the semantics of C comma
194 expressions to work properly.
196 #define xPushPtr(ppp) { xSp--; *xSp=(StgWord)(ppp); }
197 #define xPopPtr() ((StgPtr)(*xSp++))
199 #define xPushCPtr(ppp) { xSp--; *xSp=(StgWord)(ppp); }
200 #define xPopCPtr() ((StgClosure*)(*xSp++))
202 #define xPushWord(ppp) { xSp--; *xSp=(StgWord)(ppp); }
203 #define xPopWord() ((StgWord)(*xSp++))
205 #define xStackPtr(nnn) ((StgPtr)(*(xSp+(nnn))))
206 #define xStackWord(nnn) ((StgWord)(*(xSp+(nnn))))
207 #define xSetStackWord(iii,www) xSp[iii]=(StgWord)(www)
209 #define xPushTag(ttt) { xSp--; *xSp=(StgWord)(ttt); }
210 #define xPopTag(ttt) { StackTag t = (StackTag)(*xSp++); \
213 #define xPushTaggedInt(xxx) { xSp -= sizeofW(StgInt); \
214 *xSp = (xxx); xPushTag(INT_TAG); }
215 #define xTaggedStackInt(iii) ((StgInt)(*(xSp+1+(iii))))
216 #define xPopTaggedInt() ((xSp++,xSp+=sizeofW(StgInt), \
217 (StgInt)(*(xSp-sizeofW(StgInt)))))
219 #define xPushTaggedWord(xxx) { xSp -= sizeofW(StgWord); \
220 *xSp = (xxx); xPushTag(WORD_TAG); }
221 #define xTaggedStackWord(iii) ((StgWord)(*(xSp+1+(iii))))
222 #define xPopTaggedWord() ((xSp++,xSp+=sizeofW(StgWord), \
223 (StgWord)(*(xSp-sizeofW(StgWord)))))
225 #define xPushTaggedAddr(xxx) { xSp -= sizeofW(StgAddr); \
226 *xSp = (StgWord)(xxx); xPushTag(ADDR_TAG); }
227 #define xTaggedStackAddr(iii) ((StgAddr)(*(xSp+1+(iii))))
228 #define xPopTaggedAddr() ((xSp++,xSp+=sizeofW(StgAddr), \
229 (StgAddr)(*(xSp-sizeofW(StgAddr)))))
231 #define xPushTaggedStable(xxx) { xSp -= sizeofW(StgStablePtr); \
232 *xSp = (StgWord)(xxx); xPushTag(STABLE_TAG); }
233 #define xTaggedStackStable(iii) ((StgStablePtr)(*(xSp+1+(iii))))
234 #define xPopTaggedStable() ((xSp++,xSp+=sizeofW(StgStablePtr), \
235 (StgStablePtr)(*(xSp-sizeofW(StgStablePtr)))))
237 #define xPushTaggedChar(xxx) { xSp -= sizeofW(StgChar); \
238 *xSp = (StgWord)(xxx); xPushTag(CHAR_TAG); }
239 #define xTaggedStackChar(iii) ((StgChar)(*(xSp+1+(iii))))
240 #define xPopTaggedChar() ((xSp++,xSp+=sizeofW(StgChar), \
241 (StgChar)(*(xSp-sizeofW(StgChar)))))
243 #define xPushTaggedFloat(xxx) { xSp -= sizeofW(StgFloat); \
244 ASSIGN_FLT(xSp,xxx); xPushTag(FLOAT_TAG); }
245 #define xTaggedStackFloat(iii) PK_FLT(xSp+1+(iii))
246 #define xPopTaggedFloat() ((xSp++,xSp+=sizeofW(StgFloat), \
247 PK_FLT(xSp-sizeofW(StgFloat))))
249 #define xPushTaggedDouble(xxx) { xSp -= sizeofW(StgDouble); \
250 ASSIGN_DBL(xSp,xxx); xPushTag(DOUBLE_TAG); }
251 #define xTaggedStackDouble(iii) PK_DBL(xSp+1+(iii))
252 #define xPopTaggedDouble() ((xSp++,xSp+=sizeofW(StgDouble), \
253 PK_DBL(xSp-sizeofW(StgDouble))))
256 #define xPushUpdateFrame(target, xSp_offset) \
258 StgUpdateFrame *__frame; \
259 __frame = (StgUpdateFrame *)(xSp + (xSp_offset)) - 1; \
260 SET_INFO(__frame, (StgInfoTable *)&upd_frame_info); \
261 __frame->link = xSu; \
262 __frame->updatee = (StgClosure *)(target); \
266 #define xPopUpdateFrame(ooo) \
268 /* NB: doesn't assume that Sp == Su */ \
269 IF_DEBUG(evaluator, \
270 fprintf(stderr, "Updating "); \
271 printPtr(stgCast(StgPtr,xSu->updatee)); \
272 fprintf(stderr, " with "); \
274 fprintf(stderr,"xSp = %p\txSu = %p\n\n", xSp, xSu); \
276 UPD_IND(xSu->updatee,ooo); \
277 xSp = stgCast(StgStackPtr,xSu) + sizeofW(StgUpdateFrame); \
283 /* Instruction stream macros */
284 #define BCO_INSTR_8 *bciPtr++
285 #define BCO_INSTR_16 ((bciPtr += 2, (*(bciPtr-2) << 8) + *(bciPtr-1)))
286 #define PC (bciPtr - &(bcoInstr(bco,0)))
289 /* State on entry to enter():
290 * - current thread is in cap->rCurrentTSO;
291 * - allocation area is in cap->rCurrentNursery & cap->rNursery
294 StgThreadReturnCode enter( Capability* cap, StgClosure* obj0 )
296 /* use of register here is primarily to make it clear to compilers
297 that these entities are non-aliasable.
299 register StgPtr xSp; /* local state -- stack pointer */
300 register StgUpdateFrame* xSu; /* local state -- frame pointer */
301 register StgPtr xSpLim; /* local state -- stack lim pointer */
302 register StgClosure* obj; /* object currently under evaluation */
303 char eCount; /* enter counter, for context switching */
306 HugsBlock hugsBlock = { NotBlocked, 0 };
310 StgPtr tSp; StgUpdateFrame* tSu; StgPtr tSpLim;
313 gSp = cap->rCurrentTSO->sp;
314 gSu = cap->rCurrentTSO->su;
315 gSpLim = cap->rCurrentTSO->stack + RESERVED_STACK_WORDS;
318 /* use the t values to check that Su/Sp/SpLim do not change unexpectedly */
319 tSp = gSp; tSu = gSu; tSpLim = gSpLim;
325 /* Load the local state from global state, and Party On, Dudes! */
326 /* From here onwards, we operate with the local state and
327 save/reload it as necessary.
338 ASSERT(gSpLim == tSpLim);
342 ASSERT(xSpLim <= xSp && xSp <= stgCast(StgPtr,xSu));
344 "\n---------------------------------------------------------------\n");
345 fprintf(stderr,"(%d) Entering: ",enterCountI); printObj(obj);
346 fprintf(stderr,"xSp = %p\txSu = %p\n", xSp, xSu);
347 fprintf(stderr, "\n" );
348 printStack(xSp,cap->rCurrentTSO->stack+cap->rCurrentTSO->stack_size,xSu);
349 fprintf(stderr, "\n\n");
356 ((++eCount) & 0x0F) == 0
361 if (context_switch) {
362 switch(hugsBlock.reason) {
364 xPushCPtr(obj); /* code to restart with */
365 RETURN(ThreadYielding);
367 case BlockedOnDelay: /* fall through */
368 case BlockedOnRead: /* fall through */
369 case BlockedOnWrite: {
370 ASSERT(cap->rCurrentTSO->why_blocked == NotBlocked);
371 cap->rCurrentTSO->why_blocked = BlockedOnDelay;
372 ACQUIRE_LOCK(&sched_mutex);
374 #if defined(HAVE_SETITIMER) /* || defined(mingw32_TARGET_OS) */
375 cap->rCurrentTSO->block_info.delay
376 = hugsBlock.delay + ticks_since_select;
378 cap->rCurrentTSO->block_info.target
379 = hugsBlock.delay + getourtimeofday();
381 APPEND_TO_BLOCKED_QUEUE(cap->rCurrentTSO);
383 RELEASE_LOCK(&sched_mutex);
385 xPushCPtr(obj); /* code to restart with */
386 RETURN(ThreadBlocked);
389 barf("Unknown context switch reasoning");
394 switch ( get_itbl(obj)->type ) {
396 barf("Invalid object %p",obj);
400 /* ---------------------------------------------------- */
401 /* Start of the bytecode evaluator */
402 /* ---------------------------------------------------- */
405 # define Ins(x) &&l##x
406 static void *labs[] = { INSTRLIST };
408 # define LoopTopLabel
409 # define Case(x) l##x
410 # define Continue goto *labs[BCO_INSTR_8]
411 # define Dispatch Continue;
414 # define LoopTopLabel insnloop:
415 # define Case(x) case x
416 # define Continue goto insnloop
417 # define Dispatch switch (BCO_INSTR_8) {
418 # define EndDispatch }
421 register StgWord8* bciPtr; /* instruction pointer */
422 register StgBCO* bco = (StgBCO*)obj;
425 /* Don't need to SSS ... LLL around doYouWantToGC */
426 wantToGC = doYouWantToGC();
428 xPushCPtr((StgClosure*)bco); /* code to restart with */
429 RETURN(HeapOverflow);
432 bciPtr = &(bcoInstr(bco,0));
436 ASSERT((StgWord)(PC) < bco->n_instrs);
438 fprintf(stderr,"Sp = %p\tSu = %p\tpc = %d\t", xSp, xSu, PC);
442 fprintf(stderr,"\n");
443 for (i = 8; i >= 0; i--)
444 fprintf(stderr, "%d %p\n", i, (StgPtr)(*(gSp+i)));
446 fprintf(stderr,"\n");
452 Case(i_INTERNAL_ERROR):
453 barf("INTERNAL_ERROR at %p:%d",bco,PC-1);
455 barf("PANIC at %p:%d",bco,PC-1);
459 if (xSp - n < xSpLim) {
460 xPushCPtr((StgClosure*)bco); /* code to restart with */
461 RETURN(StackOverflow);
465 Case(i_STK_CHECK_big):
467 int n = BCO_INSTR_16;
468 if (xSp - n < xSpLim) {
469 xPushCPtr((StgClosure*)bco); /* code to restart with */
470 RETURN(StackOverflow);
477 if ((StgPtr*)(xSp + n) > (StgPtr*)xSu) {
478 StgWord words = (P_)xSu - xSp;
480 /* first build a PAP */
481 ASSERT((P_)xSu >= xSp); /* was (words >= 0) but that's always true */
482 if (words == 0) { /* optimisation */
483 /* Skip building the PAP and update with an indirection. */
486 /* In the evaluator, we avoid the need to do
487 * a heap check here by including the size of
488 * the PAP in the heap check we performed
489 * when we entered the BCO.
493 SSS; pap = (StgPAP*)grabHpNonUpd(PAP_sizeW(words)); LLL;
494 SET_HDR(pap,&PAP_info,CC_pap);
497 for (i = 0; i < (I_)words; ++i) {
498 payloadWord(pap,i) = xSp[i];
501 obj = stgCast(StgClosure*,pap);
504 /* now deal with "update frame" */
505 /* as an optimisation, we process all on top of stack */
506 /* instead of just the top one */
507 ASSERT(xSp==(P_)xSu);
509 switch (get_itbl(xSu)->type) {
511 /* Hit a catch frame during an arg satisfaction check,
512 * so the thing returning (1) has not thrown an
513 * exception, and (2) is of functional type. Just
514 * zap the catch frame and carry on down the stack
515 * (looking for more arguments, basically).
517 SSS; PopCatchFrame(); LLL;
520 xPopUpdateFrame(obj);
523 barf("STOP frame during pap update");
525 cap->rCurrentTSO->what_next = ThreadComplete;
526 SSS; PopStopFrame(obj); LLL;
527 RETURN(ThreadFinished);
530 SSS; PopSeqFrame(); LLL;
531 ASSERT(xSp != (P_)xSu);
532 /* Hit a SEQ frame during an arg satisfaction check.
533 * So now return to bco_info which is under the
534 * SEQ frame. The following code is copied from a
535 * case RET_BCO further down. (The reason why we're
536 * here is that something of functional type has
537 * been seq-d on, and we're now returning to the
538 * algebraic-case-continuation which forced the
539 * evaluation in the first place.)
551 barf("Invalid update frame during argcheck");
553 } while (xSp==(P_)xSu);
561 int words = BCO_INSTR_8;
562 SSS; p = grabHpUpd(AP_sizeW(words)); LLL;
566 Case(i_ALLOC_CONSTR):
569 StgInfoTable* info = bcoConstAddr(bco,BCO_INSTR_8);
570 SSS; p = grabHpNonUpd(sizeW_fromITBL(info)); LLL;
571 SET_HDR((StgClosure*)p,info,??);
575 Case(i_ALLOC_CONSTR_big):
578 int x = BCO_INSTR_16;
579 StgInfoTable* info = bcoConstAddr(bco,x);
580 SSS; p = grabHpNonUpd(sizeW_fromITBL(info)); LLL;
581 SET_HDR((StgClosure*)p,info,??);
587 int x = BCO_INSTR_8; /* ToDo: Word not Int! */
589 StgAP_UPD* o = stgCast(StgAP_UPD*,xStackPtr(x));
590 SET_HDR(o,&AP_UPD_info,??);
592 o->fun = stgCast(StgClosure*,xPopPtr());
593 for(x=0; x < y; ++x) {
594 payloadWord(o,x) = xPopWord();
597 fprintf(stderr,"\tBuilt ");
599 printObj(stgCast(StgClosure*,o));
610 o = stgCast(StgAP_UPD*,xStackPtr(x));
611 SET_HDR(o,&AP_UPD_info,??);
613 o->fun = stgCast(StgClosure*,xPopPtr());
614 for(x=0; x < y; ++x) {
615 payloadWord(o,x) = xPopWord();
618 fprintf(stderr,"\tBuilt ");
620 printObj(stgCast(StgClosure*,o));
629 StgPAP* o = stgCast(StgPAP*,xStackPtr(x));
630 SET_HDR(o,&PAP_info,??);
632 o->fun = stgCast(StgClosure*,xPopPtr());
633 for(x=0; x < y; ++x) {
634 payloadWord(o,x) = xPopWord();
637 fprintf(stderr,"\tBuilt ");
639 printObj(stgCast(StgClosure*,o));
646 int offset = BCO_INSTR_8;
647 StgClosure* o = stgCast(StgClosure*,xStackPtr(offset));
648 const StgInfoTable* info = get_itbl(o);
649 nat p = info->layout.payload.ptrs;
650 nat np = info->layout.payload.nptrs;
652 for(i=0; i < p; ++i) {
653 o->payload[i] = xPopCPtr();
655 for(i=0; i < np; ++i) {
656 payloadWord(o,p+i) = 0xdeadbeef;
659 fprintf(stderr,"\tBuilt ");
661 printObj(stgCast(StgClosure*,o));
668 int offset = BCO_INSTR_16;
669 StgClosure* o = stgCast(StgClosure*,xStackPtr(offset));
670 const StgInfoTable* info = get_itbl(o);
671 nat p = info->layout.payload.ptrs;
672 nat np = info->layout.payload.nptrs;
674 for(i=0; i < p; ++i) {
675 o->payload[i] = xPopCPtr();
677 for(i=0; i < np; ++i) {
678 payloadWord(o,p+i) = 0xdeadbeef;
681 fprintf(stderr,"\tBuilt ");
683 printObj(stgCast(StgClosure*,o));
692 ASSERT(xSp+x+y <= stgCast(StgPtr,xSu));
693 /* a_1, .. a_x, b_1, .. b_y, s => a_1, .. a_x, s */
695 xSetStackWord(x+y,xStackWord(x));
705 ASSERT(xSp+x+y <= stgCast(StgPtr,xSu));
706 /* a_1, .. a_x, b_1, .. b_y, s => a_1, .. a_x, s */
708 xSetStackWord(x+y,xStackWord(x));
720 xPushPtr(bcoConstPtr(bco,BCO_INSTR_8));
721 xPushPtr(stgCast(StgPtr,&ret_bco_info));
726 int tag = BCO_INSTR_8;
727 StgWord offset = BCO_INSTR_16;
728 if (constrTag( (StgClosure*)xStackPtr(0) ) != tag) {
735 StgClosure* o = stgCast(StgClosure*,xStackPtr(0));
736 const StgInfoTable* itbl = get_itbl(o);
737 int i = itbl->layout.payload.ptrs;
738 ASSERT( itbl->type == CONSTR
739 || itbl->type == CONSTR_STATIC
740 || itbl->type == CONSTR_NOCAF_STATIC
741 || itbl->type == CONSTR_1_0
742 || itbl->type == CONSTR_0_1
743 || itbl->type == CONSTR_2_0
744 || itbl->type == CONSTR_1_1
745 || itbl->type == CONSTR_0_2
748 xPushCPtr(o->payload[i]);
754 int n = BCO_INSTR_16;
755 StgPtr p = xStackPtr(n);
761 StgPtr p = xStackPtr(BCO_INSTR_8);
767 xPushPtr(stgCast(StgPtr,bcoConstPtr(bco,BCO_INSTR_8)));
772 int n = BCO_INSTR_16;
773 xPushPtr(stgCast(StgPtr,bcoConstPtr(bco,n)));
777 /* allocate rows, implemented on top of (frozen) Arrays */
781 StgWord n = BCO_INSTR_8;
782 SSS; p = stgCast(StgMutArrPtrs*,grabHpNonUpd(sizeofW(StgMutArrPtrs) + n)); LLL;
783 SET_HDR(p,&MUT_ARR_PTRS_FROZEN_info,CCCS);
788 Case(i_ALLOC_ROW_big):
791 StgWord n = BCO_INSTR_16;
792 SSS; p = stgCast(StgMutArrPtrs*,grabHpNonUpd(sizeofW(StgMutArrPtrs) + n)); LLL;
793 SET_HDR(p,&MUT_ARR_PTRS_FROZEN_info,CCCS);
799 /* pack values into a row. */
802 StgWord offset = BCO_INSTR_8;
803 StgMutArrPtrs* p = stgCast(StgMutArrPtrs*,xStackPtr(offset));
809 p->payload[i] = xPopCPtr();
812 fprintf(stderr,"\tBuilt ");
814 printObj(stgCast(StgClosure*,p));
819 Case(i_PACK_ROW_big):
821 StgWord offset = BCO_INSTR_16;
822 StgMutArrPtrs* p = stgCast(StgMutArrPtrs*,xStackPtr(offset));
828 p->payload[i] = xPopCPtr();
831 fprintf(stderr,"\tBuilt ");
833 printObj(stgCast(StgClosure*,p));
839 /* extract all fields of a row */
842 StgMutArrPtrs* p = stgCast(StgMutArrPtrs*,xStackPtr(0));
847 xPushCPtr(p->payload[i]);
852 /* Trivial row (unit) */
853 Case(i_CONST_ROW_TRIV):
856 SSS; p = stgCast(StgMutArrPtrs*,grabHpNonUpd(sizeofW(StgMutArrPtrs) + 0)); LLL;
857 SET_HDR(p,&MUT_ARR_PTRS_FROZEN_info,CCCS);
863 /* pack values into an Inj */
864 Case(i_PACK_INJ_VAR):
866 const int size = CONSTR_sizeW(sizeofW(StgPtr),sizeofW(StgWord));
867 StgWord offset = BCO_INSTR_8;
870 SSS; o = (StgClosure*)grabHpNonUpd(size); LLL;
871 SET_HDR(o,Inj_con_info,??);
873 payloadWord(o,sizeofW(StgPtr)) = xTaggedStackWord(offset);
874 payloadPtr(o,0) = xPopPtr();
877 fprintf(stderr,"\tBuilt ");
879 printObj(stgCast(StgClosure*,o));
882 xPushPtr(stgCast(StgPtr,o));
885 Case(i_PACK_INJ_VAR_big):
887 const int size = CONSTR_sizeW(sizeofW(StgPtr),sizeofW(StgWord));
888 StgWord offset = BCO_INSTR_16;
891 SSS; o = (StgClosure*)grabHpNonUpd(size); LLL;
892 SET_HDR(o,Inj_con_info,??);
894 payloadWord(o,sizeofW(StgPtr)) = xTaggedStackWord(offset);
895 payloadPtr(o,0) = xPopPtr();
898 fprintf(stderr,"\tBuilt ");
900 printObj(stgCast(StgClosure*,o));
903 xPushPtr(stgCast(StgPtr,o));
906 Case(i_PACK_INJ_CONST_8):
908 const int size = CONSTR_sizeW(sizeofW(StgPtr),sizeofW(StgWord));
909 StgWord witness = BCO_INSTR_8;
912 SSS; o = (StgClosure*)grabHpNonUpd(size); LLL;
913 SET_HDR(o,Inj_con_info,??);
915 payloadWord(o,sizeofW(StgPtr)) = witness;
916 payloadPtr(o,0) = xPopPtr();
919 fprintf(stderr,"\tBuilt ");
921 printObj(stgCast(StgClosure*,o));
924 xPushPtr(stgCast(StgPtr,o));
927 Case(i_PACK_INJ_REL_8):
929 const int size = CONSTR_sizeW(sizeofW(StgPtr),sizeofW(StgWord));
930 StgWord offset = BCO_INSTR_8;
931 StgWord cwitness = BCO_INSTR_8;
934 SSS; o = (StgClosure*)grabHpNonUpd(size); LLL;
935 SET_HDR(o,Inj_con_info,??);
937 payloadWord(o,sizeofW(StgPtr)) = xTaggedStackWord(offset) + cwitness;
938 payloadPtr(o,0) = xPopPtr();
941 fprintf(stderr,"\tBuilt ");
943 printObj(stgCast(StgClosure*,o));
946 xPushPtr(stgCast(StgPtr,o));
951 const int size = CONSTR_sizeW(sizeofW(StgPtr),sizeofW(StgWord));
954 SSS; o = (StgClosure*)grabHpNonUpd(size); LLL;
955 SET_HDR(o,Inj_con_info,??);
957 payloadWord(o,sizeofW(StgPtr)) = xPopTaggedWord();
958 payloadPtr(o,0) = xPopPtr();
961 fprintf(stderr,"\tBuilt ");
963 printObj(stgCast(StgClosure*,o));
966 xPushPtr(stgCast(StgPtr,o));
970 /* Test Inj witnesses. */
971 Case(i_TEST_INJ_VAR):
973 StgWord offset = BCO_INSTR_8;
974 StgWord jump = BCO_INSTR_16;
976 StgWord index = payloadWord( (StgClosure*)xStackPtr(0), sizeofW(StgPtr) );
977 if (index != xTaggedStackWord(offset) )
983 Case(i_TEST_INJ_VAR_big):
985 StgWord offset = BCO_INSTR_16;
986 StgWord jump = BCO_INSTR_16;
988 StgWord index = payloadWord( (StgClosure*)xStackPtr(0), sizeofW(StgPtr) );
989 if (index != xTaggedStackWord(offset) )
995 Case(i_TEST_INJ_CONST_8):
997 StgWord cwitness = BCO_INSTR_8;
998 StgWord jump = BCO_INSTR_16;
1000 StgWord witness = payloadWord( (StgClosure*)xStackPtr(0), sizeofW(StgPtr) );
1001 if (witness != cwitness )
1007 Case(i_TEST_INJ_REL_8):
1009 StgWord offset = BCO_INSTR_8;
1010 StgWord cwitness = BCO_INSTR_8;
1011 StgWord jump = BCO_INSTR_16;
1013 StgWord witness = payloadWord( (StgClosure*)xStackPtr(0), sizeofW(StgPtr) );
1014 if (witness != xTaggedStackWord(offset) + cwitness )
1022 StgWord jump = BCO_INSTR_16;
1023 StgWord cwitness = xPopTaggedWord();
1025 StgWord witness = payloadWord( (StgClosure*)xStackPtr(0), sizeofW(StgPtr) );
1026 if (witness != cwitness )
1033 /* extract the value of an INJ */
1036 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1038 ASSERT(get_itbl(con) == Inj_con_info);
1040 xPushPtr(payloadPtr(con,0));
1044 /* optimized witness (word) operations */
1045 Case(i_CONST_WORD_8):
1047 xPushTaggedWord(BCO_INSTR_8);
1050 Case(i_ADD_WORD_VAR):
1052 StgWord offset = BCO_INSTR_8;
1053 StgWord witness = xTaggedStackWord(offset);
1054 witness += xPopTaggedWord();
1055 xPushTaggedWord(witness);
1058 Case(i_ADD_WORD_VAR_big):
1060 StgWord offset = BCO_INSTR_16;
1061 StgWord witness = xTaggedStackWord(offset);
1062 witness += xPopTaggedWord();
1063 xPushTaggedWord(witness);
1066 Case(i_ADD_WORD_VAR_8):
1068 StgWord offset = BCO_INSTR_8;
1069 StgWord inc = BCO_INSTR_8;
1070 StgWord witness = xTaggedStackWord(offset);
1071 xPushTaggedWord(witness + inc);
1074 #endif /* XMLAMBA */
1078 SSS; PushTaggedRealWorld(); LLL;
1083 StgInt i = xTaggedStackInt(BCO_INSTR_8);
1089 xPushTaggedInt(bcoConstInt(bco,BCO_INSTR_8));
1092 Case(i_CONST_INT_big):
1094 int n = BCO_INSTR_16;
1095 xPushTaggedInt(bcoConstInt(bco,n));
1101 SSS; o = (StgClosure*)grabHpNonUpd(Izh_sizeW); LLL;
1102 SET_HDR(o,Izh_con_info,??);
1103 payloadWord(o,0) = xPopTaggedInt();
1105 fprintf(stderr,"\tBuilt ");
1107 printObj(stgCast(StgClosure*,o));
1110 xPushPtr(stgCast(StgPtr,o));
1115 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1116 /* ASSERT(isIntLike(con)); */
1117 xPushTaggedInt(payloadWord(con,0));
1122 StgWord offset = BCO_INSTR_16;
1123 StgInt x = xPopTaggedInt();
1124 StgInt y = xPopTaggedInt();
1130 Case(i_CONST_INTEGER):
1134 char* s = bcoConstAddr(bco,BCO_INSTR_8);
1136 n = size_fromStr(s);
1137 p = CreateByteArrayToHoldInteger(n);
1138 do_fromStr ( s, n, IntegerInsideByteArray(p));
1139 SloppifyIntegerEnd(p);
1146 StgWord w = xTaggedStackWord(BCO_INSTR_8);
1152 xPushTaggedWord(bcoConstWord(bco,BCO_INSTR_8));
1155 Case(i_CONST_WORD_big):
1157 StgWord n = BCO_INSTR_16;
1158 xPushTaggedWord(bcoConstWord(bco,n));
1164 SSS; o = (StgClosure*)grabHpNonUpd(Wzh_sizeW); LLL;
1165 SET_HDR(o,Wzh_con_info,??);
1166 payloadWord(o,0) = xPopTaggedWord();
1168 fprintf(stderr,"\tBuilt ");
1170 printObj(stgCast(StgClosure*,o));
1173 xPushPtr(stgCast(StgPtr,o));
1176 Case(i_UNPACK_WORD):
1178 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1179 /* ASSERT(isWordLike(con)); */
1180 xPushTaggedWord(payloadWord(con,0));
1185 StgAddr a = xTaggedStackAddr(BCO_INSTR_8);
1191 xPushTaggedAddr(bcoConstAddr(bco,BCO_INSTR_8));
1194 Case(i_CONST_ADDR_big):
1196 int n = BCO_INSTR_16;
1197 xPushTaggedAddr(bcoConstAddr(bco,n));
1203 SSS; o = (StgClosure*)grabHpNonUpd(Azh_sizeW); LLL;
1204 SET_HDR(o,Azh_con_info,??);
1205 payloadPtr(o,0) = xPopTaggedAddr();
1207 fprintf(stderr,"\tBuilt ");
1209 printObj(stgCast(StgClosure*,o));
1212 xPushPtr(stgCast(StgPtr,o));
1215 Case(i_UNPACK_ADDR):
1217 StgClosure* con = (StgClosure*)xStackPtr(0);
1218 /* ASSERT(isAddrLike(con)); */
1219 xPushTaggedAddr(payloadPtr(con,0));
1224 StgChar c = xTaggedStackChar(BCO_INSTR_8);
1230 xPushTaggedChar(bcoConstChar(bco,BCO_INSTR_8));
1236 SSS; o = (StgClosure*)grabHpNonUpd(Czh_sizeW); LLL;
1237 SET_HDR(o,Czh_con_info,??);
1238 payloadWord(o,0) = xPopTaggedChar();
1239 xPushPtr(stgCast(StgPtr,o));
1241 fprintf(stderr,"\tBuilt ");
1243 printObj(stgCast(StgClosure*,o));
1248 Case(i_UNPACK_CHAR):
1250 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1251 /* ASSERT(isCharLike(con)); */
1252 xPushTaggedChar(payloadWord(con,0));
1257 StgFloat f = xTaggedStackFloat(BCO_INSTR_8);
1258 xPushTaggedFloat(f);
1261 Case(i_CONST_FLOAT):
1263 xPushTaggedFloat(bcoConstFloat(bco,BCO_INSTR_8));
1269 SSS; o = (StgClosure*)grabHpNonUpd(Fzh_sizeW); LLL;
1270 SET_HDR(o,Fzh_con_info,??);
1271 ASSIGN_FLT(&payloadWord(o,0),xPopTaggedFloat());
1273 fprintf(stderr,"\tBuilt ");
1275 printObj(stgCast(StgClosure*,o));
1278 xPushPtr(stgCast(StgPtr,o));
1281 Case(i_UNPACK_FLOAT):
1283 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1284 /* ASSERT(isFloatLike(con)); */
1285 xPushTaggedFloat(PK_FLT(&payloadWord(con,0)));
1290 StgDouble d = xTaggedStackDouble(BCO_INSTR_8);
1291 xPushTaggedDouble(d);
1294 Case(i_CONST_DOUBLE):
1296 xPushTaggedDouble(bcoConstDouble(bco,BCO_INSTR_8));
1299 Case(i_CONST_DOUBLE_big):
1301 int n = BCO_INSTR_16;
1302 xPushTaggedDouble(bcoConstDouble(bco,n));
1305 Case(i_PACK_DOUBLE):
1308 SSS; o = (StgClosure*)grabHpNonUpd(Dzh_sizeW); LLL;
1309 SET_HDR(o,Dzh_con_info,??);
1310 ASSIGN_DBL(&payloadWord(o,0),xPopTaggedDouble());
1312 fprintf(stderr,"\tBuilt ");
1313 printObj(stgCast(StgClosure*,o));
1315 xPushPtr(stgCast(StgPtr,o));
1318 Case(i_UNPACK_DOUBLE):
1320 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1321 /* ASSERT(isDoubleLike(con)); */
1322 xPushTaggedDouble(PK_DBL(&payloadWord(con,0)));
1327 StgStablePtr s = xTaggedStackStable(BCO_INSTR_8);
1328 xPushTaggedStable(s);
1331 Case(i_PACK_STABLE):
1334 SSS; o = (StgClosure*)grabHpNonUpd(Stablezh_sizeW); LLL;
1335 SET_HDR(o,StablePtr_con_info,??);
1336 payloadWord(o,0) = (W_)xPopTaggedStable();
1338 fprintf(stderr,"\tBuilt ");
1340 printObj(stgCast(StgClosure*,o));
1343 xPushPtr(stgCast(StgPtr,o));
1346 Case(i_UNPACK_STABLE):
1348 StgClosure* con = (StgClosure*)xStackPtr(0);
1349 /* ASSERT(isStableLike(con)); */
1350 xPushTaggedStable(payloadWord(con,0));
1358 SSS; p = enterBCO_primop1 ( i ); LLL;
1359 if (p) { obj = p; goto enterLoop; };
1364 int i, trc, pc_saved;
1367 trc = 12345678; /* Assume != any StgThreadReturnCode */
1372 p = enterBCO_primop2 ( i, &trc, &bco_tmp, cap,
1376 bciPtr = &(bcoInstr(bco,pc_saved));
1378 if (trc == 12345678) {
1379 /* we want to enter p */
1380 obj = p; goto enterLoop;
1382 /* trc is the the StgThreadReturnCode for
1384 RETURN((StgThreadReturnCode)trc);
1390 /* combined insns, created by peephole opt */
1393 int x = BCO_INSTR_8;
1394 int y = BCO_INSTR_8;
1395 ASSERT(xSp+x+y <= stgCast(StgPtr,xSu));
1396 /* a_1, .. a_x, b_1, .. b_y, s => a_1, .. a_x, s */
1403 xSetStackWord(x+y,xStackWord(x));
1413 p = xStackPtr(BCO_INSTR_8);
1415 p = xStackPtr(BCO_INSTR_8);
1422 xPushPtr(bcoConstPtr(bco,BCO_INSTR_8));
1423 xPushPtr(stgCast(StgPtr,&ret_bco_info));
1424 p = xStackPtr(BCO_INSTR_8);
1430 StgPtr retaddr = bcoConstPtr(bco,BCO_INSTR_8);
1431 StgPtr ptr = xStackPtr(BCO_INSTR_8);
1433 /* A shortcut. We're going to push the address of a
1434 return continuation, and then enter a variable, so
1435 that when the var is evaluated, we return to the
1436 continuation. The shortcut is: if the var is a
1437 constructor, don't bother to enter it. Instead,
1438 push the variable on the stack (since this is what
1439 the continuation expects) and jump directly to the
1442 if (get_itbl((StgClosure*)ptr)->type == CONSTR) {
1444 obj = (StgClosure*)retaddr;
1446 fprintf(stderr, "object to enter is a constructor -- "
1447 "jumping directly to return continuation\n" );
1452 /* This is the normal, non-short-cut route */
1454 xPushPtr(stgCast(StgPtr,&ret_bco_info));
1455 obj = (StgClosure*)ptr;
1460 Case(i_VAR_DOUBLE_big):
1461 Case(i_CONST_FLOAT_big):
1462 Case(i_VAR_FLOAT_big):
1463 Case(i_CONST_CHAR_big):
1464 Case(i_VAR_CHAR_big):
1465 Case(i_VAR_ADDR_big):
1466 Case(i_VAR_STABLE_big):
1467 Case(i_CONST_INTEGER_big):
1468 Case(i_VAR_INT_big):
1469 Case(i_VAR_WORD_big):
1470 Case(i_RETADDR_big):
1475 Case(i_TEST_INJ_CONST):
1476 Case(i_TEST_INJ_big):
1478 Case(i_PACK_INJ_CONST):
1479 Case(i_PACK_INJ_big):
1481 Case(i_PACK_ROW_big):
1483 Case(i_ALLOC_ROW_big):
1488 disInstr ( bco, PC );
1489 barf("\nUnrecognised instruction");
1493 barf("enterBCO: ran off end of loop");
1497 # undef LoopTopLabel
1503 /* ---------------------------------------------------- */
1504 /* End of the bytecode evaluator */
1505 /* ---------------------------------------------------- */
1509 StgBlockingQueue* bh;
1510 StgCAF* caf = (StgCAF*)obj;
1511 if (xSp - sizeofW(StgUpdateFrame) < xSpLim) {
1512 xPushCPtr(obj); /* code to restart with */
1513 RETURN(StackOverflow);
1515 SSS; bh = (StgBlockingQueue*)grabHpUpd(BLACKHOLE_sizeW()); LLL;
1516 SET_INFO(bh,&CAF_BLACKHOLE_info);
1517 bh->blocking_queue = EndTSOQueue;
1519 fprintf(stderr,"Created CAF_BLACKHOLE %p for CAF %p"
1520 " in evaluator\n",bh,caf));
1521 SET_INFO(caf,&CAF_ENTERED_info);
1522 caf->value = (StgClosure*)bh;
1524 SSS; newCAF_made_by_Hugs(caf); LLL;
1526 xPushUpdateFrame(bh,0);
1527 xSp -= sizeofW(StgUpdateFrame);
1533 StgCAF* caf = (StgCAF*)obj;
1534 obj = caf->value; /* it's just a fancy indirection */
1540 case SE_CAF_BLACKHOLE:
1542 /* Let the scheduler figure out what to do :-) */
1543 cap->rCurrentTSO->what_next = ThreadEnterGHC;
1545 RETURN(ThreadYielding);
1549 StgAP_UPD* ap = stgCast(StgAP_UPD*,obj);
1551 if (xSp - (i + sizeofW(StgUpdateFrame)) < xSpLim) {
1552 xPushCPtr(obj); /* code to restart with */
1553 RETURN(StackOverflow);
1555 /* ToDo: look for xSp==xSu && stackInt(0) == UPD_FRAME
1556 and insert an indirection immediately */
1557 xPushUpdateFrame(ap,0);
1558 xSp -= sizeofW(StgUpdateFrame);
1560 xPushWord(payloadWord(ap,i));
1563 #ifdef EAGER_BLACKHOLING
1564 #warn LAZY_BLACKHOLING is default for StgHugs
1565 #error Dont know if EAGER_BLACKHOLING works in StgHugs
1567 /* superfluous - but makes debugging easier */
1568 StgBlackHole* bh = stgCast(StgBlackHole*,ap);
1569 SET_INFO(bh,&BLACKHOLE_info);
1570 bh->blocking_queue = EndTSOQueue;
1572 fprintf(stderr,"Eagerly blackholed AP_UPD %p in evaluator\n",bh));
1575 #endif /* EAGER_BLACKHOLING */
1580 StgPAP* pap = stgCast(StgPAP*,obj);
1581 int i = pap->n_args; /* ToDo: stack check */
1582 /* ToDo: if PAP is in whnf, we can update any update frames
1586 xPushWord(payloadWord(pap,i));
1593 obj = stgCast(StgInd*,obj)->indirectee;
1598 obj = stgCast(StgIndOldGen*,obj)->indirectee;
1607 case CONSTR_INTLIKE:
1608 case CONSTR_CHARLIKE:
1610 case CONSTR_NOCAF_STATIC:
1612 /* rows are mutarrays and should be treated as constructors. */
1613 case MUT_ARR_PTRS_FROZEN:
1617 switch (get_itbl(stgCast(StgClosure*,xSp))->type) {
1619 SSS; PopCatchFrame(); LLL;
1622 xPopUpdateFrame(obj);
1625 SSS; PopSeqFrame(); LLL;
1629 ASSERT(xSp==(P_)xSu);
1632 fprintf(stderr, "hit a STOP_FRAME\n");
1634 fprintf(stderr,"xSp = %p\txSu = %p\n", xSp, xSu);
1635 printStack(xSp,cap->rCurrentTSO->stack
1636 + cap->rCurrentTSO->stack_size,xSu);
1639 cap->rCurrentTSO->what_next = ThreadComplete;
1640 SSS; PopStopFrame(obj); LLL;
1642 RETURN(ThreadFinished);
1652 /* was: goto enterLoop;
1653 But we know that obj must be a bco now, so jump directly.
1656 case RET_SMALL: /* return to GHC */
1660 cap->rCurrentTSO->what_next = ThreadEnterGHC;
1662 RETURN(ThreadYielding);
1664 belch("entered CONSTR with invalid continuation on stack");
1667 printObj(stgCast(StgClosure*,xSp));
1670 barf("bailing out");
1677 //fprintf(stderr, "enterCountI = %d\n", enterCountI);
1678 //fprintf(stderr, "entering unknown closure -- yielding to sched\n");
1681 cap->rCurrentTSO->what_next = ThreadEnterGHC;
1682 xPushCPtr(obj); /* code to restart with */
1683 RETURN(ThreadYielding);
1686 barf("Ran off the end of enter - yoiks");
1703 #undef xSetStackWord
1706 #undef xPushTaggedInt
1707 #undef xPopTaggedInt
1708 #undef xTaggedStackInt
1709 #undef xPushTaggedWord
1710 #undef xPopTaggedWord
1711 #undef xTaggedStackWord
1712 #undef xPushTaggedAddr
1713 #undef xTaggedStackAddr
1714 #undef xPopTaggedAddr
1715 #undef xPushTaggedStable
1716 #undef xTaggedStackStable
1717 #undef xPopTaggedStable
1718 #undef xPushTaggedChar
1719 #undef xTaggedStackChar
1720 #undef xPopTaggedChar
1721 #undef xPushTaggedFloat
1722 #undef xTaggedStackFloat
1723 #undef xPopTaggedFloat
1724 #undef xPushTaggedDouble
1725 #undef xTaggedStackDouble
1726 #undef xPopTaggedDouble
1727 #undef xPopUpdateFrame
1728 #undef xPushUpdateFrame
1731 /* --------------------------------------------------------------------------
1732 * Supporting routines for primops
1733 * ------------------------------------------------------------------------*/
1735 static inline void PushTag ( StackTag t )
1737 inline void PushPtr ( StgPtr x )
1738 { *(--stgCast(StgPtr*,gSp)) = x; }
1739 static inline void PushCPtr ( StgClosure* x )
1740 { *(--stgCast(StgClosure**,gSp)) = x; }
1741 static inline void PushInt ( StgInt x )
1742 { *(--stgCast(StgInt*,gSp)) = x; }
1743 static inline void PushWord ( StgWord x )
1744 { *(--stgCast(StgWord*,gSp)) = x; }
1747 static inline void checkTag ( StackTag t1, StackTag t2 )
1748 { ASSERT(t1 == t2);}
1749 static inline void PopTag ( StackTag t )
1750 { checkTag(t,*(gSp++)); }
1751 inline StgPtr PopPtr ( void )
1752 { return *stgCast(StgPtr*,gSp)++; }
1753 static inline StgClosure* PopCPtr ( void )
1754 { return *stgCast(StgClosure**,gSp)++; }
1755 static inline StgInt PopInt ( void )
1756 { return *stgCast(StgInt*,gSp)++; }
1757 static inline StgWord PopWord ( void )
1758 { return *stgCast(StgWord*,gSp)++; }
1760 static inline StgPtr stackPtr ( StgStackOffset i )
1761 { return *stgCast(StgPtr*, gSp+i); }
1762 static inline StgInt stackInt ( StgStackOffset i )
1763 { return *stgCast(StgInt*, gSp+i); }
1764 static inline StgWord stackWord ( StgStackOffset i )
1765 { return *stgCast(StgWord*,gSp+i); }
1767 static inline void setStackWord ( StgStackOffset i, StgWord w )
1771 static inline void setStackPtr ( StgStackOffset i, StgPtr p )
1772 { *(stgCast(StgPtr*, gSp+i)) = p; }
1775 static inline void PushTaggedRealWorld( void )
1776 { PushTag(REALWORLD_TAG); }
1777 inline void PushTaggedInt ( StgInt x )
1778 { gSp -= sizeofW(StgInt); *gSp = x; PushTag(INT_TAG); }
1779 inline void PushTaggedWord ( StgWord x )
1780 { gSp -= sizeofW(StgWord); *gSp = x; PushTag(WORD_TAG); }
1781 inline void PushTaggedAddr ( StgAddr x )
1782 { gSp -= sizeofW(StgAddr); *gSp = (W_)x; PushTag(ADDR_TAG); }
1783 inline void PushTaggedChar ( StgChar x )
1784 { gSp -= sizeofW(StgChar); *gSp = stgCast(StgWord,x); PushTag(CHAR_TAG); }
1785 inline void PushTaggedFloat ( StgFloat x )
1786 { gSp -= sizeofW(StgFloat); ASSIGN_FLT(gSp,x); PushTag(FLOAT_TAG); }
1787 inline void PushTaggedDouble ( StgDouble x )
1788 { gSp -= sizeofW(StgDouble); ASSIGN_DBL(gSp,x); PushTag(DOUBLE_TAG); }
1789 inline void PushTaggedStablePtr ( StgStablePtr x )
1790 { gSp -= sizeofW(StgStablePtr); *gSp = (W_)x; PushTag(STABLE_TAG); }
1791 static inline void PushTaggedBool ( int x )
1792 { PushTaggedInt(x); }
1796 static inline void PopTaggedRealWorld ( void )
1797 { PopTag(REALWORLD_TAG); }
1798 inline StgInt PopTaggedInt ( void )
1799 { StgInt r; PopTag(INT_TAG); r = *stgCast(StgInt*, gSp);
1800 gSp += sizeofW(StgInt); return r;}
1801 inline StgWord PopTaggedWord ( void )
1802 { StgWord r; PopTag(WORD_TAG); r = *stgCast(StgWord*, gSp);
1803 gSp += sizeofW(StgWord); return r;}
1804 inline StgAddr PopTaggedAddr ( void )
1805 { StgAddr r; PopTag(ADDR_TAG); r = *stgCast(StgAddr*, gSp);
1806 gSp += sizeofW(StgAddr); return r;}
1807 inline StgChar PopTaggedChar ( void )
1808 { StgChar r; PopTag(CHAR_TAG); r = stgCast(StgChar, *gSp);
1809 gSp += sizeofW(StgChar); return r;}
1810 inline StgFloat PopTaggedFloat ( void )
1811 { StgFloat r; PopTag(FLOAT_TAG); r = PK_FLT(gSp);
1812 gSp += sizeofW(StgFloat); return r;}
1813 inline StgDouble PopTaggedDouble ( void )
1814 { StgDouble r; PopTag(DOUBLE_TAG); r = PK_DBL(gSp);
1815 gSp += sizeofW(StgDouble); return r;}
1816 inline StgStablePtr PopTaggedStablePtr ( void )
1817 { StgStablePtr r; PopTag(STABLE_TAG); r = *stgCast(StgStablePtr*, gSp);
1818 gSp += sizeofW(StgStablePtr); return r;}
1822 static inline StgInt taggedStackInt ( StgStackOffset i )
1823 { checkTag(INT_TAG,gSp[i]); return *stgCast(StgInt*, gSp+1+i); }
1824 static inline StgWord taggedStackWord ( StgStackOffset i )
1825 { checkTag(WORD_TAG,gSp[i]); return *stgCast(StgWord*, gSp+1+i); }
1826 static inline StgAddr taggedStackAddr ( StgStackOffset i )
1827 { checkTag(ADDR_TAG,gSp[i]); return *stgCast(StgAddr*, gSp+1+i); }
1828 static inline StgChar taggedStackChar ( StgStackOffset i )
1829 { checkTag(CHAR_TAG,gSp[i]); return stgCast(StgChar, *(gSp+1+i)) ; }
1830 static inline StgFloat taggedStackFloat ( StgStackOffset i )
1831 { checkTag(FLOAT_TAG,gSp[i]); return PK_FLT(gSp+1+i); }
1832 static inline StgDouble taggedStackDouble ( StgStackOffset i )
1833 { checkTag(DOUBLE_TAG,gSp[i]); return PK_DBL(gSp+1+i); }
1834 static inline StgStablePtr taggedStackStable ( StgStackOffset i )
1835 { checkTag(STABLE_TAG,gSp[i]); return *stgCast(StgStablePtr*, gSp+1+i); }
1838 /* --------------------------------------------------------------------------
1841 * Should we allocate from a nursery or use the
1842 * doYouWantToGC/allocate interface? We'd already implemented a
1843 * nursery-style scheme when the doYouWantToGC/allocate interface
1845 * One reason to prefer the doYouWantToGC/allocate interface is to
1846 * support operations which allocate an unknown amount in the heap
1847 * (array ops, gmp ops, etc)
1848 * ------------------------------------------------------------------------*/
1850 static inline StgPtr grabHpUpd( nat size )
1852 ASSERT( size >= MIN_UPD_SIZE + sizeofW(StgHeader) );
1853 return allocate(size);
1856 static inline StgPtr grabHpNonUpd( nat size )
1858 ASSERT( size >= MIN_NONUPD_SIZE + sizeofW(StgHeader) );
1859 return allocate(size);
1862 /* --------------------------------------------------------------------------
1863 * Manipulate "update frame" list:
1864 * o Update frames (based on stg_do_update and friends in Updates.hc)
1865 * o Error handling/catching (based on catchzh_fast and friends in Prims.hc)
1866 * o Seq frames (based on seq_frame_entry in Prims.hc)
1868 * ------------------------------------------------------------------------*/
1870 static inline void PopUpdateFrame ( StgClosure* obj )
1872 /* NB: doesn't assume that gSp == gSu */
1874 fprintf(stderr, "Updating ");
1875 printPtr(stgCast(StgPtr,gSu->updatee));
1876 fprintf(stderr, " with ");
1878 fprintf(stderr,"gSp = %p\tgSu = %p\n\n", gSp, gSu);
1880 #ifdef EAGER_BLACKHOLING
1881 #warn LAZY_BLACKHOLING is default for StgHugs
1882 #error Dont know if EAGER_BLACKHOLING works in StgHugs
1883 ASSERT(get_itbl(gSu->updatee)->type == BLACKHOLE
1884 || get_itbl(gSu->updatee)->type == SE_BLACKHOLE
1885 || get_itbl(gSu->updatee)->type == CAF_BLACKHOLE
1886 || get_itbl(gSu->updatee)->type == SE_CAF_BLACKHOLE
1888 #endif /* EAGER_BLACKHOLING */
1889 UPD_IND(gSu->updatee,obj);
1890 gSp = stgCast(StgStackPtr,gSu) + sizeofW(StgUpdateFrame);
1894 static inline void PopStopFrame ( StgClosure* obj )
1896 /* Move gSu just off the end of the stack, we're about to gSpam the
1897 * STOP_FRAME with the return value.
1899 gSu = stgCast(StgUpdateFrame*,gSp+1);
1900 *stgCast(StgClosure**,gSp) = obj;
1903 static inline void PushCatchFrame ( StgClosure* handler )
1906 /* ToDo: stack check! */
1907 gSp -= sizeofW(StgCatchFrame);
1908 fp = stgCast(StgCatchFrame*,gSp);
1909 SET_HDR(fp,(StgInfoTable*)&catch_frame_info,CCCS);
1910 fp->handler = handler;
1912 gSu = stgCast(StgUpdateFrame*,fp);
1915 static inline void PopCatchFrame ( void )
1917 /* NB: doesn't assume that gSp == gSu */
1918 /* fprintf(stderr,"Popping catch frame\n"); */
1919 gSp = stgCast(StgStackPtr,gSu) + sizeofW(StgCatchFrame);
1920 gSu = stgCast(StgCatchFrame*,gSu)->link;
1923 static inline void PushSeqFrame ( void )
1926 /* ToDo: stack check! */
1927 gSp -= sizeofW(StgSeqFrame);
1928 fp = stgCast(StgSeqFrame*,gSp);
1929 SET_HDR(fp,(StgInfoTable*)&seq_frame_info,CCCS);
1931 gSu = stgCast(StgUpdateFrame*,fp);
1934 static inline void PopSeqFrame ( void )
1936 /* NB: doesn't assume that gSp == gSu */
1937 gSp = stgCast(StgStackPtr,gSu) + sizeofW(StgSeqFrame);
1938 gSu = stgCast(StgSeqFrame*,gSu)->link;
1941 static inline StgClosure* raiseAnError ( StgClosure* exception )
1943 /* This closure represents the expression 'primRaise E' where E
1944 * is the exception raised (:: Exception).
1945 * It is used to overwrite all the
1946 * thunks which are currently under evaluation.
1948 HaskellObj primRaiseClosure
1949 = getHugs_BCO_cptr_for("primRaise");
1950 HaskellObj reraiseClosure
1951 = rts_apply ( primRaiseClosure, exception );
1954 switch (get_itbl(gSu)->type) {
1956 UPD_IND(gSu->updatee,reraiseClosure);
1957 gSp = stgCast(StgStackPtr,gSu) + sizeofW(StgUpdateFrame);
1963 case CATCH_FRAME: /* found it! */
1965 StgCatchFrame* fp = stgCast(StgCatchFrame*,gSu);
1966 StgClosure *handler = fp->handler;
1968 gSp += sizeofW(StgCatchFrame); /* Pop */
1969 PushCPtr(exception);
1973 barf("raiseError: uncaught exception: STOP_FRAME");
1975 barf("raiseError: weird activation record");
1981 static StgClosure* makeErrorCall ( const char* msg )
1983 /* Note! the msg string should be allocated in a
1984 place which will not get freed -- preferably
1985 read-only data of the program. That's because
1986 the thunk we build here may linger indefinitely.
1987 (thinks: probably not so, but anyway ...)
1990 = getHugs_BCO_cptr_for("error");
1992 = getHugs_BCO_cptr_for("hugsprimUnpackString");
1994 = rts_apply ( unpack, rts_mkAddr ( (void*)msg ) );
1996 = rts_apply ( error, thunk );
1998 (StgClosure*) thunk;
2001 #define raiseIndex(where) makeErrorCall("Array index out of range in " where)
2002 #define raiseDiv0(where) makeErrorCall("Division by zero in " where)
2004 /* --------------------------------------------------------------------------
2006 * ------------------------------------------------------------------------*/
2008 #define OP_CC_B(e) \
2010 unsigned char x = PopTaggedChar(); \
2011 unsigned char y = PopTaggedChar(); \
2012 PushTaggedBool(e); \
2017 unsigned char x = PopTaggedChar(); \
2026 #define OP_IW_I(e) \
2028 StgInt x = PopTaggedInt(); \
2029 StgWord y = PopTaggedWord(); \
2033 #define OP_II_I(e) \
2035 StgInt x = PopTaggedInt(); \
2036 StgInt y = PopTaggedInt(); \
2040 #define OP_II_B(e) \
2042 StgInt x = PopTaggedInt(); \
2043 StgInt y = PopTaggedInt(); \
2044 PushTaggedBool(e); \
2049 PushTaggedAddr(e); \
2054 StgInt x = PopTaggedInt(); \
2055 PushTaggedAddr(e); \
2060 StgInt x = PopTaggedInt(); \
2066 PushTaggedChar(e); \
2071 StgInt x = PopTaggedInt(); \
2072 PushTaggedChar(e); \
2077 PushTaggedWord(e); \
2082 StgInt x = PopTaggedInt(); \
2083 PushTaggedWord(e); \
2088 StgInt x = PopTaggedInt(); \
2089 PushTaggedStablePtr(e); \
2094 PushTaggedFloat(e); \
2099 StgInt x = PopTaggedInt(); \
2100 PushTaggedFloat(e); \
2105 PushTaggedDouble(e); \
2110 StgInt x = PopTaggedInt(); \
2111 PushTaggedDouble(e); \
2114 #define OP_WW_B(e) \
2116 StgWord x = PopTaggedWord(); \
2117 StgWord y = PopTaggedWord(); \
2118 PushTaggedBool(e); \
2121 #define OP_WW_W(e) \
2123 StgWord x = PopTaggedWord(); \
2124 StgWord y = PopTaggedWord(); \
2125 PushTaggedWord(e); \
2130 StgWord x = PopTaggedWord(); \
2136 StgStablePtr x = PopTaggedStablePtr(); \
2142 StgWord x = PopTaggedWord(); \
2143 PushTaggedWord(e); \
2146 #define OP_AA_B(e) \
2148 StgAddr x = PopTaggedAddr(); \
2149 StgAddr y = PopTaggedAddr(); \
2150 PushTaggedBool(e); \
2154 StgAddr x = PopTaggedAddr(); \
2157 #define OP_AI_C(s) \
2159 StgAddr x = PopTaggedAddr(); \
2160 int y = PopTaggedInt(); \
2163 PushTaggedChar(r); \
2165 #define OP_AI_I(s) \
2167 StgAddr x = PopTaggedAddr(); \
2168 int y = PopTaggedInt(); \
2173 #define OP_AI_A(s) \
2175 StgAddr x = PopTaggedAddr(); \
2176 int y = PopTaggedInt(); \
2179 PushTaggedAddr(s); \
2181 #define OP_AI_F(s) \
2183 StgAddr x = PopTaggedAddr(); \
2184 int y = PopTaggedInt(); \
2187 PushTaggedFloat(r); \
2189 #define OP_AI_D(s) \
2191 StgAddr x = PopTaggedAddr(); \
2192 int y = PopTaggedInt(); \
2195 PushTaggedDouble(r); \
2197 #define OP_AI_s(s) \
2199 StgAddr x = PopTaggedAddr(); \
2200 int y = PopTaggedInt(); \
2203 PushTaggedStablePtr(r); \
2205 #define OP_AIC_(s) \
2207 StgAddr x = PopTaggedAddr(); \
2208 int y = PopTaggedInt(); \
2209 StgChar z = PopTaggedChar(); \
2212 #define OP_AII_(s) \
2214 StgAddr x = PopTaggedAddr(); \
2215 int y = PopTaggedInt(); \
2216 StgInt z = PopTaggedInt(); \
2219 #define OP_AIA_(s) \
2221 StgAddr x = PopTaggedAddr(); \
2222 int y = PopTaggedInt(); \
2223 StgAddr z = PopTaggedAddr(); \
2226 #define OP_AIF_(s) \
2228 StgAddr x = PopTaggedAddr(); \
2229 int y = PopTaggedInt(); \
2230 StgFloat z = PopTaggedFloat(); \
2233 #define OP_AID_(s) \
2235 StgAddr x = PopTaggedAddr(); \
2236 int y = PopTaggedInt(); \
2237 StgDouble z = PopTaggedDouble(); \
2240 #define OP_AIs_(s) \
2242 StgAddr x = PopTaggedAddr(); \
2243 int y = PopTaggedInt(); \
2244 StgStablePtr z = PopTaggedStablePtr(); \
2249 #define OP_FF_B(e) \
2251 StgFloat x = PopTaggedFloat(); \
2252 StgFloat y = PopTaggedFloat(); \
2253 PushTaggedBool(e); \
2256 #define OP_FF_F(e) \
2258 StgFloat x = PopTaggedFloat(); \
2259 StgFloat y = PopTaggedFloat(); \
2260 PushTaggedFloat(e); \
2265 StgFloat x = PopTaggedFloat(); \
2266 PushTaggedFloat(e); \
2271 StgFloat x = PopTaggedFloat(); \
2272 PushTaggedBool(e); \
2277 StgFloat x = PopTaggedFloat(); \
2283 StgFloat x = PopTaggedFloat(); \
2284 PushTaggedDouble(e); \
2287 #define OP_DD_B(e) \
2289 StgDouble x = PopTaggedDouble(); \
2290 StgDouble y = PopTaggedDouble(); \
2291 PushTaggedBool(e); \
2294 #define OP_DD_D(e) \
2296 StgDouble x = PopTaggedDouble(); \
2297 StgDouble y = PopTaggedDouble(); \
2298 PushTaggedDouble(e); \
2303 StgDouble x = PopTaggedDouble(); \
2304 PushTaggedBool(e); \
2309 StgDouble x = PopTaggedDouble(); \
2310 PushTaggedDouble(e); \
2315 StgDouble x = PopTaggedDouble(); \
2321 StgDouble x = PopTaggedDouble(); \
2322 PushTaggedFloat(e); \
2326 StgPtr CreateByteArrayToHoldInteger ( int nbytes )
2328 StgWord words = (nbytes+sizeof(W_)-1)/sizeof(W_);
2329 StgWord size = sizeofW(StgArrWords) + words;
2330 StgArrWords* arr = (StgArrWords*)allocate(size);
2331 SET_HDR(arr,&ARR_WORDS_info,CCCS);
2333 ASSERT((W_)nbytes <= arr->words * sizeof(W_));
2336 for (i = 0; i < words; ++i) {
2337 arr->payload[i] = 0xdeadbeef;
2339 { B* b = (B*) &(arr->payload[0]);
2340 b->used = b->sign = 0;
2346 B* IntegerInsideByteArray ( StgPtr arr0 )
2349 StgArrWords* arr = (StgArrWords*)arr0;
2350 ASSERT(GET_INFO(arr) == &ARR_WORDS_info);
2351 b = (B*) &(arr->payload[0]);
2355 void SloppifyIntegerEnd ( StgPtr arr0 )
2357 StgArrWords* arr = (StgArrWords*)arr0;
2358 B* b = (B*) & (arr->payload[0]);
2359 I_ nwunused = arr->words - sizeofW(B) - (b->used+sizeof(W_)-1)/sizeof(W_);
2360 if (nwunused >= ((I_)sizeofW(StgArrWords))) {
2362 b->size -= nwunused * sizeof(W_);
2363 if (b->size < b->used) b->size = b->used;
2366 arr->words -= nwunused;
2367 slop = (StgArrWords*)&(arr->payload[arr->words]);
2368 SET_HDR(slop,&ARR_WORDS_info,CCCS);
2369 slop->words = nwunused - sizeofW(StgArrWords);
2370 ASSERT( &(slop->payload[slop->words]) ==
2371 &(arr->payload[arr->words + nwunused]) );
2375 #define OP_Z_Z(op) \
2377 B* x = IntegerInsideByteArray(PopPtr()); \
2378 int n = mycat2(size_,op)(x); \
2379 StgPtr p = CreateByteArrayToHoldInteger(n); \
2380 mycat2(do_,op)(x,n,IntegerInsideByteArray(p)); \
2381 SloppifyIntegerEnd(p); \
2384 #define OP_ZZ_Z(op) \
2386 B* x = IntegerInsideByteArray(PopPtr()); \
2387 B* y = IntegerInsideByteArray(PopPtr()); \
2388 int n = mycat2(size_,op)(x,y); \
2389 StgPtr p = CreateByteArrayToHoldInteger(n); \
2390 mycat2(do_,op)(x,y,n,IntegerInsideByteArray(p)); \
2391 SloppifyIntegerEnd(p); \
2398 #define HEADER_mI(ty,where) \
2399 StgArrWords* x = stgCast(StgArrWords*,PopPtr()); \
2400 nat i = PopTaggedInt(); \
2401 if (i * sizeof(ty) + (sizeof(ty)) > sizeof(StgWord) * x->words) { \
2402 return (raiseIndex(where)); \
2404 #define OP_mI_ty(ty,where,s) \
2406 HEADER_mI(mycat2(Stg,ty),where) \
2407 { mycat2(Stg,ty) r; \
2409 mycat2(PushTagged,ty)(r); \
2412 #define OP_mIty_(ty,where,s) \
2414 HEADER_mI(mycat2(Stg,ty),where) \
2416 mycat2(Stg,ty) z = mycat2(PopTagged,ty)(); \
2422 __attribute__ ((unused))
2423 static void myStackCheck ( Capability* cap )
2425 /* fprintf(stderr, "myStackCheck\n"); */
2426 if (!(gSpLim <= gSp && gSp <= stgCast(StgPtr,gSu))) {
2427 fprintf(stderr, "myStackCheck: invalid initial gSp/gSu \n" );
2432 if (!( (P_)gSu >= (P_)cap->rCurrentTSO->stack
2434 (P_)gSu <= (P_)(cap->rCurrentTSO->stack
2435 + cap->rCurrentTSO->stack_size))) {
2436 fprintf ( stderr, "myStackCheck: gSu out of stack\n" );
2440 switch (get_itbl(stgCast(StgClosure*,gSu))->type) {
2442 gSu = (StgUpdateFrame*) ((StgCatchFrame*)(gSu))->link;
2445 gSu = (StgUpdateFrame*) ((StgUpdateFrame*)(gSu))->link;
2448 gSu = (StgUpdateFrame*) ((StgSeqFrame*)(gSu))->link;
2453 fprintf(stderr, "myStackCheck: invalid activation record\n");
2462 /* --------------------------------------------------------------------------
2463 * The new bytecode interpreter
2464 * ------------------------------------------------------------------------*/
2466 /* Sp points to the lowest live word on the stack. */
2468 #define StackWord(n) ((W_*)Sp)[n]
2469 #define BCO_NEXT bco_instrs[bciPtr++]
2470 #define BCO_PTR(n) bco_ptrs[n]
2476 StackWord(-1) = StackWord(o1);
2483 StackWord(-1) = StackWord(o1);
2484 StackWord(-2) = StackWord(o2);
2488 case bci_PUSH_LLL: {
2492 StackWord(-1) = StackWord(o1);
2493 StackWord(-2) = StackWord(o2);
2494 StackWord(-3) = StackWord(o3);
2500 StackWord(-1) = BCO_PTR(o1);
2505 int o_bco = BCO_NEXT;
2506 int o_itbl = BCO_NEXT;
2507 StackWord(-1) = BCO_LITW(o_itbl);
2508 StackWord(-2) = BCO_PTR(o_bco);
2514 StackWord(-1) = BCO_LIT(o);
2518 case bci_PUSH_TAG: {
2519 W_ tag = (W_)(BCO_NEXT);
2520 StackWord(-1) = tag;
2527 ASSERT(Sp+n+by <= (StgPtr)xSu);
2528 /* a_1, .. a_n, b_1, .. b_by, s => a_1, .. a_n, s */
2530 StackWord(n+by) = StackWord(n);
2536 int n_payload = BCO_NEXT;
2537 P_ p = allocate(AP_sizeW(n_payload));
2544 int n_payload = BCO_NEXT - 1;
2545 StgAP_UPD* ap = StackWord(off);
2546 ap->n_args = n_payload;
2547 ap->fun = (StgClosure*)StackWord(0);
2548 for (i = 0; i < n_payload; i++)
2549 ap->payload[i] = StackWord(i+1);
2554 /* Unpack N ptr words from t.o.s constructor */
2555 int n_words = BCO_NEXT;
2556 StgClosure* con = StackWord(0);
2558 for (i = 0; i < n_words; i++)
2559 StackWord(i) = con->payload[i];
2572 /* Control-flow ish things */