2 /* -----------------------------------------------------------------------------
5 * Copyright (c) 1994-1998.
7 * $RCSfile: Evaluator.c,v $
9 * $Date: 2000/06/15 13:23:51 $
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; \
184 cap->rCurrentTSO->splim = gSpLim; \
189 /* Macros to operate directly on the pulled-out machine state.
190 These mirror some of the small procedures used in the primop code
191 below, except you have to be careful about side effects,
192 ie xPushPtr(xStackPtr(n)) won't work! It certainly isn't the
193 same as PushPtr(StackPtr(n)). Also note that (1) some of
194 the macros, in particular xPopTagged*, do not make the tag
195 sanity checks that their non-x cousins do, and (2) some of
196 the macros depend critically on the semantics of C comma
197 expressions to work properly.
199 #define xPushPtr(ppp) { xSp--; *xSp=(StgWord)(ppp); }
200 #define xPopPtr() ((StgPtr)(*xSp++))
202 #define xPushCPtr(ppp) { xSp--; *xSp=(StgWord)(ppp); }
203 #define xPopCPtr() ((StgClosure*)(*xSp++))
205 #define xPushWord(ppp) { xSp--; *xSp=(StgWord)(ppp); }
206 #define xPopWord() ((StgWord)(*xSp++))
208 #define xStackPtr(nnn) ((StgPtr)(*(xSp+(nnn))))
209 #define xStackWord(nnn) ((StgWord)(*(xSp+(nnn))))
210 #define xSetStackWord(iii,www) xSp[iii]=(StgWord)(www)
212 #define xPushTag(ttt) { xSp--; *xSp=(StgWord)(ttt); }
213 #define xPopTag(ttt) { StackTag t = (StackTag)(*xSp++); \
216 #define xPushTaggedInt(xxx) { xSp -= sizeofW(StgInt); \
217 *xSp = (xxx); xPushTag(INT_TAG); }
218 #define xTaggedStackInt(iii) ((StgInt)(*(xSp+1+(iii))))
219 #define xPopTaggedInt() ((xSp++,xSp+=sizeofW(StgInt), \
220 (StgInt)(*(xSp-sizeofW(StgInt)))))
222 #define xPushTaggedWord(xxx) { xSp -= sizeofW(StgWord); \
223 *xSp = (xxx); xPushTag(WORD_TAG); }
224 #define xTaggedStackWord(iii) ((StgWord)(*(xSp+1+(iii))))
225 #define xPopTaggedWord() ((xSp++,xSp+=sizeofW(StgWord), \
226 (StgWord)(*(xSp-sizeofW(StgWord)))))
228 #define xPushTaggedAddr(xxx) { xSp -= sizeofW(StgAddr); \
229 *xSp = (StgWord)(xxx); xPushTag(ADDR_TAG); }
230 #define xTaggedStackAddr(iii) ((StgAddr)(*(xSp+1+(iii))))
231 #define xPopTaggedAddr() ((xSp++,xSp+=sizeofW(StgAddr), \
232 (StgAddr)(*(xSp-sizeofW(StgAddr)))))
234 #define xPushTaggedStable(xxx) { xSp -= sizeofW(StgStablePtr); \
235 *xSp = (StgWord)(xxx); xPushTag(STABLE_TAG); }
236 #define xTaggedStackStable(iii) ((StgStablePtr)(*(xSp+1+(iii))))
237 #define xPopTaggedStable() ((xSp++,xSp+=sizeofW(StgStablePtr), \
238 (StgStablePtr)(*(xSp-sizeofW(StgStablePtr)))))
240 #define xPushTaggedChar(xxx) { xSp -= sizeofW(StgChar); \
241 *xSp = (StgWord)(xxx); xPushTag(CHAR_TAG); }
242 #define xTaggedStackChar(iii) ((StgChar)(*(xSp+1+(iii))))
243 #define xPopTaggedChar() ((xSp++,xSp+=sizeofW(StgChar), \
244 (StgChar)(*(xSp-sizeofW(StgChar)))))
246 #define xPushTaggedFloat(xxx) { xSp -= sizeofW(StgFloat); \
247 ASSIGN_FLT(xSp,xxx); xPushTag(FLOAT_TAG); }
248 #define xTaggedStackFloat(iii) PK_FLT(xSp+1+(iii))
249 #define xPopTaggedFloat() ((xSp++,xSp+=sizeofW(StgFloat), \
250 PK_FLT(xSp-sizeofW(StgFloat))))
252 #define xPushTaggedDouble(xxx) { xSp -= sizeofW(StgDouble); \
253 ASSIGN_DBL(xSp,xxx); xPushTag(DOUBLE_TAG); }
254 #define xTaggedStackDouble(iii) PK_DBL(xSp+1+(iii))
255 #define xPopTaggedDouble() ((xSp++,xSp+=sizeofW(StgDouble), \
256 PK_DBL(xSp-sizeofW(StgDouble))))
259 #define xPushUpdateFrame(target, xSp_offset) \
261 StgUpdateFrame *__frame; \
262 __frame = (StgUpdateFrame *)(xSp + (xSp_offset)) - 1; \
263 SET_INFO(__frame, (StgInfoTable *)&upd_frame_info); \
264 __frame->link = xSu; \
265 __frame->updatee = (StgClosure *)(target); \
269 #define xPopUpdateFrame(ooo) \
271 /* NB: doesn't assume that Sp == Su */ \
272 IF_DEBUG(evaluator, \
273 fprintf(stderr, "Updating "); \
274 printPtr(stgCast(StgPtr,xSu->updatee)); \
275 fprintf(stderr, " with "); \
277 fprintf(stderr,"xSp = %p\txSu = %p\n\n", xSp, xSu); \
279 UPD_IND(xSu->updatee,ooo); \
280 xSp = stgCast(StgStackPtr,xSu) + sizeofW(StgUpdateFrame); \
286 /* Instruction stream macros */
287 #define BCO_INSTR_8 *bciPtr++
288 #define BCO_INSTR_16 ((bciPtr += 2, (*(bciPtr-2) << 8) + *(bciPtr-1)))
289 #define PC (bciPtr - &(bcoInstr(bco,0)))
292 /* State on entry to enter():
293 * - current thread is in cap->rCurrentTSO;
294 * - allocation area is in cap->rCurrentNursery & cap->rNursery
297 StgThreadReturnCode enter( Capability* cap, StgClosure* obj0 )
299 /* use of register here is primarily to make it clear to compilers
300 that these entities are non-aliasable.
302 register StgPtr xSp; /* local state -- stack pointer */
303 register StgUpdateFrame* xSu; /* local state -- frame pointer */
304 register StgPtr xSpLim; /* local state -- stack lim pointer */
305 register StgClosure* obj; /* object currently under evaluation */
306 char eCount; /* enter counter, for context switching */
309 HugsBlock hugsBlock = { NotBlocked, 0 };
313 StgPtr tSp; StgUpdateFrame* tSu; StgPtr tSpLim;
316 gSp = cap->rCurrentTSO->sp;
317 gSu = cap->rCurrentTSO->su;
318 gSpLim = cap->rCurrentTSO->splim;
321 /* use the t values to check that Su/Sp/SpLim do not change unexpectedly */
322 tSp = gSp; tSu = gSu; tSpLim = gSpLim;
328 /* Load the local state from global state, and Party On, Dudes! */
329 /* From here onwards, we operate with the local state and
330 save/reload it as necessary.
341 ASSERT(gSpLim == tSpLim);
345 ASSERT(xSpLim <= xSp && xSp <= stgCast(StgPtr,xSu));
347 "\n---------------------------------------------------------------\n");
348 fprintf(stderr,"(%d) Entering: ",enterCountI); printObj(obj);
349 fprintf(stderr,"xSp = %p\txSu = %p\n", xSp, xSu);
350 fprintf(stderr, "\n" );
351 printStack(xSp,cap->rCurrentTSO->stack+cap->rCurrentTSO->stack_size,xSu);
352 fprintf(stderr, "\n\n");
359 ((++eCount) & 0x0F) == 0
364 if (context_switch) {
365 switch(hugsBlock.reason) {
367 xPushCPtr(obj); /* code to restart with */
368 RETURN(ThreadYielding);
370 case BlockedOnDelay: /* fall through */
371 case BlockedOnRead: /* fall through */
372 case BlockedOnWrite: {
373 ASSERT(cap->rCurrentTSO->why_blocked == NotBlocked);
374 cap->rCurrentTSO->why_blocked = BlockedOnDelay;
375 ACQUIRE_LOCK(&sched_mutex);
377 #if defined(HAVE_SETITIMER) || defined(mingw32_TARGET_OS)
378 cap->rCurrentTSO->block_info.delay
379 = hugsBlock.delay + ticks_since_select;
381 cap->rCurrentTSO->block_info.target
382 = hugsBlock.delay + getourtimeofday();
384 APPEND_TO_BLOCKED_QUEUE(cap->rCurrentTSO);
386 RELEASE_LOCK(&sched_mutex);
388 xPushCPtr(obj); /* code to restart with */
389 RETURN(ThreadBlocked);
392 barf("Unknown context switch reasoning");
397 switch ( get_itbl(obj)->type ) {
399 barf("Invalid object %p",obj);
403 /* ---------------------------------------------------- */
404 /* Start of the bytecode evaluator */
405 /* ---------------------------------------------------- */
408 # define Ins(x) &&l##x
409 static void *labs[] = { INSTRLIST };
411 # define LoopTopLabel
412 # define Case(x) l##x
413 # define Continue goto *labs[BCO_INSTR_8]
414 # define Dispatch Continue;
417 # define LoopTopLabel insnloop:
418 # define Case(x) case x
419 # define Continue goto insnloop
420 # define Dispatch switch (BCO_INSTR_8) {
421 # define EndDispatch }
424 register StgWord8* bciPtr; /* instruction pointer */
425 register StgBCO* bco = (StgBCO*)obj;
428 /* Don't need to SSS ... LLL around doYouWantToGC */
429 wantToGC = doYouWantToGC();
431 xPushCPtr((StgClosure*)bco); /* code to restart with */
432 RETURN(HeapOverflow);
435 bciPtr = &(bcoInstr(bco,0));
439 ASSERT((StgWord)(PC) < bco->n_instrs);
441 fprintf(stderr,"Sp = %p\tSu = %p\tpc = %d\t", xSp, xSu, PC);
445 fprintf(stderr,"\n");
446 for (i = 8; i >= 0; i--)
447 fprintf(stderr, "%d %p\n", i, (StgPtr)(*(gSp+i)));
449 fprintf(stderr,"\n");
455 Case(i_INTERNAL_ERROR):
456 barf("INTERNAL_ERROR at %p:%d",bco,PC-1);
458 barf("PANIC at %p:%d",bco,PC-1);
462 if (xSp - n < xSpLim) {
463 xPushCPtr((StgClosure*)bco); /* code to restart with */
464 RETURN(StackOverflow);
468 Case(i_STK_CHECK_big):
470 int n = BCO_INSTR_16;
471 if (xSp - n < xSpLim) {
472 xPushCPtr((StgClosure*)bco); /* code to restart with */
473 RETURN(StackOverflow);
480 if ((StgPtr*)(xSp + n) > (StgPtr*)xSu) {
481 StgWord words = (P_)xSu - xSp;
483 /* first build a PAP */
484 ASSERT((P_)xSu >= xSp); /* was (words >= 0) but that's always true */
485 if (words == 0) { /* optimisation */
486 /* Skip building the PAP and update with an indirection. */
489 /* In the evaluator, we avoid the need to do
490 * a heap check here by including the size of
491 * the PAP in the heap check we performed
492 * when we entered the BCO.
496 SSS; pap = (StgPAP*)grabHpNonUpd(PAP_sizeW(words)); LLL;
497 SET_HDR(pap,&PAP_info,CC_pap);
500 for (i = 0; i < (I_)words; ++i) {
501 payloadWord(pap,i) = xSp[i];
504 obj = stgCast(StgClosure*,pap);
507 /* now deal with "update frame" */
508 /* as an optimisation, we process all on top of stack */
509 /* instead of just the top one */
510 ASSERT(xSp==(P_)xSu);
512 switch (get_itbl(xSu)->type) {
514 /* Hit a catch frame during an arg satisfaction check,
515 * so the thing returning (1) has not thrown an
516 * exception, and (2) is of functional type. Just
517 * zap the catch frame and carry on down the stack
518 * (looking for more arguments, basically).
520 SSS; PopCatchFrame(); LLL;
523 xPopUpdateFrame(obj);
526 barf("STOP frame during pap update");
528 cap->rCurrentTSO->what_next = ThreadComplete;
529 SSS; PopStopFrame(obj); LLL;
530 RETURN(ThreadFinished);
533 SSS; PopSeqFrame(); LLL;
534 ASSERT(xSp != (P_)xSu);
535 /* Hit a SEQ frame during an arg satisfaction check.
536 * So now return to bco_info which is under the
537 * SEQ frame. The following code is copied from a
538 * case RET_BCO further down. (The reason why we're
539 * here is that something of functional type has
540 * been seq-d on, and we're now returning to the
541 * algebraic-case-continuation which forced the
542 * evaluation in the first place.)
554 barf("Invalid update frame during argcheck");
556 } while (xSp==(P_)xSu);
564 int words = BCO_INSTR_8;
565 SSS; p = grabHpUpd(AP_sizeW(words)); LLL;
569 Case(i_ALLOC_CONSTR):
572 StgInfoTable* info = bcoConstAddr(bco,BCO_INSTR_8);
573 SSS; p = grabHpNonUpd(sizeW_fromITBL(info)); LLL;
574 SET_HDR((StgClosure*)p,info,??);
578 Case(i_ALLOC_CONSTR_big):
581 int x = BCO_INSTR_16;
582 StgInfoTable* info = bcoConstAddr(bco,x);
583 SSS; p = grabHpNonUpd(sizeW_fromITBL(info)); LLL;
584 SET_HDR((StgClosure*)p,info,??);
589 /* allocate rows, implemented on top of Arrays */
594 SSS; p = stgCast(StgMutArrPtrs*,grabHpNonUpd(sizeofW(StgMutArrPtrs) + n)); LLL;
595 SET_HDR(p,&MUT_ARR_PTRS_FROZEN_info,CCCS);
600 Case(i_ALLOC_ROW_big):
603 int n = BCO_INSTR_16;
604 SSS; p = stgCast(StgMutArrPtrs*,grabHpNonUpd(sizeofW(StgMutArrPtrs) + n)); LLL;
605 SET_HDR(p,&MUT_ARR_PTRS_FROZEN_info,CCCS);
613 int x = BCO_INSTR_8; /* ToDo: Word not Int! */
615 StgAP_UPD* o = stgCast(StgAP_UPD*,xStackPtr(x));
616 SET_HDR(o,&AP_UPD_info,??);
618 o->fun = stgCast(StgClosure*,xPopPtr());
619 for(x=0; x < y; ++x) {
620 payloadWord(o,x) = xPopWord();
623 fprintf(stderr,"\tBuilt ");
625 printObj(stgCast(StgClosure*,o));
636 o = stgCast(StgAP_UPD*,xStackPtr(x));
637 SET_HDR(o,&AP_UPD_info,??);
639 o->fun = stgCast(StgClosure*,xPopPtr());
640 for(x=0; x < y; ++x) {
641 payloadWord(o,x) = xPopWord();
644 fprintf(stderr,"\tBuilt ");
646 printObj(stgCast(StgClosure*,o));
655 StgPAP* o = stgCast(StgPAP*,xStackPtr(x));
656 SET_HDR(o,&PAP_info,??);
658 o->fun = stgCast(StgClosure*,xPopPtr());
659 for(x=0; x < y; ++x) {
660 payloadWord(o,x) = xPopWord();
663 fprintf(stderr,"\tBuilt ");
665 printObj(stgCast(StgClosure*,o));
672 int offset = BCO_INSTR_8;
673 StgClosure* o = stgCast(StgClosure*,xStackPtr(offset));
674 const StgInfoTable* info = get_itbl(o);
675 nat p = info->layout.payload.ptrs;
676 nat np = info->layout.payload.nptrs;
678 for(i=0; i < p; ++i) {
679 o->payload[i] = xPopCPtr();
681 for(i=0; i < np; ++i) {
682 payloadWord(o,p+i) = 0xdeadbeef;
685 fprintf(stderr,"\tBuilt ");
687 printObj(stgCast(StgClosure*,o));
694 int offset = BCO_INSTR_16;
695 StgClosure* o = stgCast(StgClosure*,xStackPtr(offset));
696 const StgInfoTable* info = get_itbl(o);
697 nat p = info->layout.payload.ptrs;
698 nat np = info->layout.payload.nptrs;
700 for(i=0; i < p; ++i) {
701 o->payload[i] = xPopCPtr();
703 for(i=0; i < np; ++i) {
704 payloadWord(o,p+i) = 0xdeadbeef;
707 fprintf(stderr,"\tBuilt ");
709 printObj(stgCast(StgClosure*,o));
715 /* pack values into a row. */
718 int offset = BCO_INSTR_8;
719 StgMutArrPtrs* p = stgCast(StgMutArrPtrs*,xStackPtr(offset));
725 p->payload[i] = xPopCPtr();
728 fprintf(stderr,"\tBuilt ");
730 printObj(stgCast(StgClosure*,p));
735 Case(i_PACK_ROW_big):
737 int offset = BCO_INSTR_16;
738 StgMutArrPtrs* p = stgCast(StgMutArrPtrs*,xStackPtr(offset));
744 p->payload[i] = xPopCPtr();
747 fprintf(stderr,"\tBuilt ");
749 printObj(stgCast(StgClosure*,p));
754 /* pack values into an Inj */
757 const int size = CONSTR_sizeW(sizeofW(StgPtr),sizeofW(StgInt));
758 int offset = BCO_INSTR_8;
761 SSS; o = (StgClosure*)grabHpNonUpd(size); LLL;
762 SET_HDR(o,Inj_con_info,??);
764 payloadWord(o,sizeofW(StgPtr)) = xTaggedStackInt(offset);
765 payloadPtr(o,0) = xPopPtr();
768 fprintf(stderr,"\tBuilt ");
770 printObj(stgCast(StgClosure*,o));
773 xPushPtr(stgCast(StgPtr,o));
776 Case(i_PACK_INJ_big):
778 const int size = CONSTR_sizeW(sizeofW(StgPtr),sizeofW(StgInt));
779 int offset = BCO_INSTR_16;
782 SSS; o = (StgClosure*)grabHpNonUpd(size); LLL;
783 SET_HDR(o,Inj_con_info,??);
785 payloadWord(o,sizeofW(StgPtr)) = xTaggedStackInt(offset);
786 payloadPtr(o,0) = xPopPtr();
789 fprintf(stderr,"\tBuilt ");
791 printObj(stgCast(StgClosure*,o));
794 xPushPtr(stgCast(StgPtr,o));
797 Case(i_PACK_INJ_CONST):
799 const int size = CONSTR_sizeW(sizeofW(StgPtr),sizeofW(StgInt));
800 int index = BCO_INSTR_8;
803 SSS; o = (StgClosure*)grabHpNonUpd(size); LLL;
804 SET_HDR(o,Inj_con_info,??);
806 payloadWord(o,sizeofW(StgPtr)) = index;
807 payloadPtr(o,0) = xPopPtr();
810 fprintf(stderr,"\tBuilt ");
812 printObj(stgCast(StgClosure*,o));
815 xPushPtr(stgCast(StgPtr,o));
819 #endif /* XMLAMBDA */
824 ASSERT(xSp+x+y <= stgCast(StgPtr,xSu));
825 /* a_1, .. a_x, b_1, .. b_y, s => a_1, .. a_x, s */
827 xSetStackWord(x+y,xStackWord(x));
837 ASSERT(xSp+x+y <= stgCast(StgPtr,xSu));
838 /* a_1, .. a_x, b_1, .. b_y, s => a_1, .. a_x, s */
840 xSetStackWord(x+y,xStackWord(x));
852 xPushPtr(bcoConstPtr(bco,BCO_INSTR_8));
853 xPushPtr(stgCast(StgPtr,&ret_bco_info));
858 int tag = BCO_INSTR_8;
859 StgWord offset = BCO_INSTR_16;
860 if (constrTag( (StgClosure*)xStackPtr(0) ) != tag) {
866 /* Test Inj indices. */
869 int offset = BCO_INSTR_8;
870 StgWord jump = BCO_INSTR_16;
872 int index = payloadWord( (StgClosure*)xStackPtr(0), sizeofW(StgPtr) );
873 if (index != xTaggedStackInt(offset) )
879 Case(i_TEST_INJ_big):
881 int offset = BCO_INSTR_16;
882 StgWord jump = BCO_INSTR_16;
884 int index = payloadWord( (StgClosure*)xStackPtr(0), sizeofW(StgPtr) );
885 if (index != xTaggedStackInt(offset) )
891 Case(i_TEST_INJ_CONST):
893 int value = BCO_INSTR_8;
894 StgWord jump = BCO_INSTR_16;
896 int index = payloadWord( (StgClosure*)xStackPtr(0), sizeofW(StgPtr) );
903 #endif /* XMLAMBDA */
906 StgClosure* o = stgCast(StgClosure*,xStackPtr(0));
907 const StgInfoTable* itbl = get_itbl(o);
908 int i = itbl->layout.payload.ptrs;
909 ASSERT( itbl->type == CONSTR
910 || itbl->type == CONSTR_STATIC
911 || itbl->type == CONSTR_NOCAF_STATIC
912 || itbl->type == CONSTR_1_0
913 || itbl->type == CONSTR_0_1
914 || itbl->type == CONSTR_2_0
915 || itbl->type == CONSTR_1_1
916 || itbl->type == CONSTR_0_2
919 xPushCPtr(o->payload[i]);
924 /* extract all fields of a row */
927 StgMutArrPtrs* p = stgCast(StgMutArrPtrs*,xStackPtr(0));
931 xPushCPtr(p->payload[i]);
935 /* extract the value of an INJ */
938 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
940 ASSERT(get_itbl(con) == Inj_con_info);
942 xPushPtr(payloadPtr(con,0));
948 int n = BCO_INSTR_16;
949 StgPtr p = xStackPtr(n);
955 StgPtr p = xStackPtr(BCO_INSTR_8);
961 xPushPtr(stgCast(StgPtr,bcoConstPtr(bco,BCO_INSTR_8)));
966 int n = BCO_INSTR_16;
967 xPushPtr(stgCast(StgPtr,bcoConstPtr(bco,n)));
972 SSS; PushTaggedRealWorld(); LLL;
977 StgInt i = xTaggedStackInt(BCO_INSTR_8);
983 xPushTaggedInt(bcoConstInt(bco,BCO_INSTR_8));
986 Case(i_CONST_INT_big):
988 int n = BCO_INSTR_16;
989 xPushTaggedInt(bcoConstInt(bco,n));
995 SSS; o = (StgClosure*)grabHpNonUpd(Izh_sizeW); LLL;
996 SET_HDR(o,Izh_con_info,??);
997 payloadWord(o,0) = xPopTaggedInt();
999 fprintf(stderr,"\tBuilt ");
1001 printObj(stgCast(StgClosure*,o));
1004 xPushPtr(stgCast(StgPtr,o));
1009 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1010 /* ASSERT(isIntLike(con)); */
1011 xPushTaggedInt(payloadWord(con,0));
1016 StgWord offset = BCO_INSTR_16;
1017 StgInt x = xPopTaggedInt();
1018 StgInt y = xPopTaggedInt();
1024 Case(i_CONST_INTEGER):
1028 char* s = bcoConstAddr(bco,BCO_INSTR_8);
1030 n = size_fromStr(s);
1031 p = CreateByteArrayToHoldInteger(n);
1032 do_fromStr ( s, n, IntegerInsideByteArray(p));
1033 SloppifyIntegerEnd(p);
1040 StgWord w = xTaggedStackWord(BCO_INSTR_8);
1046 xPushTaggedWord(bcoConstWord(bco,BCO_INSTR_8));
1052 SSS; o = (StgClosure*)grabHpNonUpd(Wzh_sizeW); LLL;
1053 SET_HDR(o,Wzh_con_info,??);
1054 payloadWord(o,0) = xPopTaggedWord();
1056 fprintf(stderr,"\tBuilt ");
1058 printObj(stgCast(StgClosure*,o));
1061 xPushPtr(stgCast(StgPtr,o));
1064 Case(i_UNPACK_WORD):
1066 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1067 /* ASSERT(isWordLike(con)); */
1068 xPushTaggedWord(payloadWord(con,0));
1073 StgAddr a = xTaggedStackAddr(BCO_INSTR_8);
1079 xPushTaggedAddr(bcoConstAddr(bco,BCO_INSTR_8));
1082 Case(i_CONST_ADDR_big):
1084 int n = BCO_INSTR_16;
1085 xPushTaggedAddr(bcoConstAddr(bco,n));
1091 SSS; o = (StgClosure*)grabHpNonUpd(Azh_sizeW); LLL;
1092 SET_HDR(o,Azh_con_info,??);
1093 payloadPtr(o,0) = xPopTaggedAddr();
1095 fprintf(stderr,"\tBuilt ");
1097 printObj(stgCast(StgClosure*,o));
1100 xPushPtr(stgCast(StgPtr,o));
1103 Case(i_UNPACK_ADDR):
1105 StgClosure* con = (StgClosure*)xStackPtr(0);
1106 /* ASSERT(isAddrLike(con)); */
1107 xPushTaggedAddr(payloadPtr(con,0));
1112 StgChar c = xTaggedStackChar(BCO_INSTR_8);
1118 xPushTaggedChar(bcoConstChar(bco,BCO_INSTR_8));
1124 SSS; o = (StgClosure*)grabHpNonUpd(Czh_sizeW); LLL;
1125 SET_HDR(o,Czh_con_info,??);
1126 payloadWord(o,0) = xPopTaggedChar();
1127 xPushPtr(stgCast(StgPtr,o));
1129 fprintf(stderr,"\tBuilt ");
1131 printObj(stgCast(StgClosure*,o));
1136 Case(i_UNPACK_CHAR):
1138 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1139 /* ASSERT(isCharLike(con)); */
1140 xPushTaggedChar(payloadWord(con,0));
1145 StgFloat f = xTaggedStackFloat(BCO_INSTR_8);
1146 xPushTaggedFloat(f);
1149 Case(i_CONST_FLOAT):
1151 xPushTaggedFloat(bcoConstFloat(bco,BCO_INSTR_8));
1157 SSS; o = (StgClosure*)grabHpNonUpd(Fzh_sizeW); LLL;
1158 SET_HDR(o,Fzh_con_info,??);
1159 ASSIGN_FLT(&payloadWord(o,0),xPopTaggedFloat());
1161 fprintf(stderr,"\tBuilt ");
1163 printObj(stgCast(StgClosure*,o));
1166 xPushPtr(stgCast(StgPtr,o));
1169 Case(i_UNPACK_FLOAT):
1171 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1172 /* ASSERT(isFloatLike(con)); */
1173 xPushTaggedFloat(PK_FLT(&payloadWord(con,0)));
1178 StgDouble d = xTaggedStackDouble(BCO_INSTR_8);
1179 xPushTaggedDouble(d);
1182 Case(i_CONST_DOUBLE):
1184 xPushTaggedDouble(bcoConstDouble(bco,BCO_INSTR_8));
1187 Case(i_CONST_DOUBLE_big):
1189 int n = BCO_INSTR_16;
1190 xPushTaggedDouble(bcoConstDouble(bco,n));
1193 Case(i_PACK_DOUBLE):
1196 SSS; o = (StgClosure*)grabHpNonUpd(Dzh_sizeW); LLL;
1197 SET_HDR(o,Dzh_con_info,??);
1198 ASSIGN_DBL(&payloadWord(o,0),xPopTaggedDouble());
1200 fprintf(stderr,"\tBuilt ");
1201 printObj(stgCast(StgClosure*,o));
1203 xPushPtr(stgCast(StgPtr,o));
1206 Case(i_UNPACK_DOUBLE):
1208 StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
1209 /* ASSERT(isDoubleLike(con)); */
1210 xPushTaggedDouble(PK_DBL(&payloadWord(con,0)));
1215 StgStablePtr s = xTaggedStackStable(BCO_INSTR_8);
1216 xPushTaggedStable(s);
1219 Case(i_PACK_STABLE):
1222 SSS; o = (StgClosure*)grabHpNonUpd(Stablezh_sizeW); LLL;
1223 SET_HDR(o,StablePtr_con_info,??);
1224 payloadWord(o,0) = (W_)xPopTaggedStable();
1226 fprintf(stderr,"\tBuilt ");
1228 printObj(stgCast(StgClosure*,o));
1231 xPushPtr(stgCast(StgPtr,o));
1234 Case(i_UNPACK_STABLE):
1236 StgClosure* con = (StgClosure*)xStackPtr(0);
1237 /* ASSERT(isStableLike(con)); */
1238 xPushTaggedStable(payloadWord(con,0));
1246 SSS; p = enterBCO_primop1 ( i ); LLL;
1247 if (p) { obj = p; goto enterLoop; };
1252 int i, trc, pc_saved;
1255 trc = 12345678; /* Assume != any StgThreadReturnCode */
1260 p = enterBCO_primop2 ( i, &trc, &bco_tmp, cap,
1264 bciPtr = &(bcoInstr(bco,pc_saved));
1266 if (trc == 12345678) {
1267 /* we want to enter p */
1268 obj = p; goto enterLoop;
1270 /* trc is the the StgThreadReturnCode for
1272 RETURN((StgThreadReturnCode)trc);
1278 /* combined insns, created by peephole opt */
1281 int x = BCO_INSTR_8;
1282 int y = BCO_INSTR_8;
1283 ASSERT(xSp+x+y <= stgCast(StgPtr,xSu));
1284 /* a_1, .. a_x, b_1, .. b_y, s => a_1, .. a_x, s */
1291 xSetStackWord(x+y,xStackWord(x));
1301 p = xStackPtr(BCO_INSTR_8);
1303 p = xStackPtr(BCO_INSTR_8);
1310 xPushPtr(bcoConstPtr(bco,BCO_INSTR_8));
1311 xPushPtr(stgCast(StgPtr,&ret_bco_info));
1312 p = xStackPtr(BCO_INSTR_8);
1318 StgPtr retaddr = bcoConstPtr(bco,BCO_INSTR_8);
1319 StgPtr ptr = xStackPtr(BCO_INSTR_8);
1321 /* A shortcut. We're going to push the address of a
1322 return continuation, and then enter a variable, so
1323 that when the var is evaluated, we return to the
1324 continuation. The shortcut is: if the var is a
1325 constructor, don't bother to enter it. Instead,
1326 push the variable on the stack (since this is what
1327 the continuation expects) and jump directly to the
1330 if (get_itbl((StgClosure*)ptr)->type == CONSTR) {
1332 obj = (StgClosure*)retaddr;
1334 fprintf(stderr, "object to enter is a constructor -- "
1335 "jumping directly to return continuation\n" );
1340 /* This is the normal, non-short-cut route */
1342 xPushPtr(stgCast(StgPtr,&ret_bco_info));
1343 obj = (StgClosure*)ptr;
1348 Case(i_VAR_DOUBLE_big):
1349 Case(i_CONST_FLOAT_big):
1350 Case(i_VAR_FLOAT_big):
1351 Case(i_CONST_CHAR_big):
1352 Case(i_VAR_CHAR_big):
1353 Case(i_VAR_ADDR_big):
1354 Case(i_VAR_STABLE_big):
1355 Case(i_CONST_INTEGER_big):
1356 Case(i_VAR_INT_big):
1357 Case(i_VAR_WORD_big):
1358 Case(i_RETADDR_big):
1362 disInstr ( bco, PC );
1363 barf("\nUnrecognised instruction");
1367 barf("enterBCO: ran off end of loop");
1371 # undef LoopTopLabel
1377 /* ---------------------------------------------------- */
1378 /* End of the bytecode evaluator */
1379 /* ---------------------------------------------------- */
1383 StgBlockingQueue* bh;
1384 StgCAF* caf = (StgCAF*)obj;
1385 if (xSp - sizeofW(StgUpdateFrame) < xSpLim) {
1386 xPushCPtr(obj); /* code to restart with */
1387 RETURN(StackOverflow);
1389 SSS; bh = (StgBlockingQueue*)grabHpUpd(BLACKHOLE_sizeW()); LLL;
1390 SET_INFO(bh,&CAF_BLACKHOLE_info);
1391 bh->blocking_queue = EndTSOQueue;
1393 fprintf(stderr,"Created CAF_BLACKHOLE %p for CAF %p"
1394 " in evaluator\n",bh,caf));
1395 SET_INFO(caf,&CAF_ENTERED_info);
1396 caf->value = (StgClosure*)bh;
1398 SSS; newCAF_made_by_Hugs(caf); LLL;
1400 xPushUpdateFrame(bh,0);
1401 xSp -= sizeofW(StgUpdateFrame);
1407 StgCAF* caf = (StgCAF*)obj;
1408 obj = caf->value; /* it's just a fancy indirection */
1414 case SE_CAF_BLACKHOLE:
1416 /* Let the scheduler figure out what to do :-) */
1417 cap->rCurrentTSO->what_next = ThreadEnterGHC;
1419 RETURN(ThreadYielding);
1423 StgAP_UPD* ap = stgCast(StgAP_UPD*,obj);
1425 if (xSp - (i + sizeofW(StgUpdateFrame)) < xSpLim) {
1426 xPushCPtr(obj); /* code to restart with */
1427 RETURN(StackOverflow);
1429 /* ToDo: look for xSp==xSu && stackInt(0) == UPD_FRAME
1430 and insert an indirection immediately */
1431 xPushUpdateFrame(ap,0);
1432 xSp -= sizeofW(StgUpdateFrame);
1434 xPushWord(payloadWord(ap,i));
1437 #ifdef EAGER_BLACKHOLING
1438 #warn LAZY_BLACKHOLING is default for StgHugs
1439 #error Dont know if EAGER_BLACKHOLING works in StgHugs
1441 /* superfluous - but makes debugging easier */
1442 StgBlackHole* bh = stgCast(StgBlackHole*,ap);
1443 SET_INFO(bh,&BLACKHOLE_info);
1444 bh->blocking_queue = EndTSOQueue;
1446 fprintf(stderr,"Eagerly blackholed AP_UPD %p in evaluator\n",bh));
1449 #endif /* EAGER_BLACKHOLING */
1454 StgPAP* pap = stgCast(StgPAP*,obj);
1455 int i = pap->n_args; /* ToDo: stack check */
1456 /* ToDo: if PAP is in whnf, we can update any update frames
1460 xPushWord(payloadWord(pap,i));
1467 obj = stgCast(StgInd*,obj)->indirectee;
1472 obj = stgCast(StgIndOldGen*,obj)->indirectee;
1481 case CONSTR_INTLIKE:
1482 case CONSTR_CHARLIKE:
1484 case CONSTR_NOCAF_STATIC:
1486 /* rows are mutarrays and should be treated as constructors. */
1487 case MUT_ARR_PTRS_FROZEN:
1491 switch (get_itbl(stgCast(StgClosure*,xSp))->type) {
1493 SSS; PopCatchFrame(); LLL;
1496 xPopUpdateFrame(obj);
1499 SSS; PopSeqFrame(); LLL;
1503 ASSERT(xSp==(P_)xSu);
1506 fprintf(stderr, "hit a STOP_FRAME\n");
1508 fprintf(stderr,"xSp = %p\txSu = %p\n", xSp, xSu);
1509 printStack(xSp,cap->rCurrentTSO->stack
1510 + cap->rCurrentTSO->stack_size,xSu);
1513 cap->rCurrentTSO->what_next = ThreadComplete;
1514 SSS; PopStopFrame(obj); LLL;
1516 RETURN(ThreadFinished);
1526 /* was: goto enterLoop;
1527 But we know that obj must be a bco now, so jump directly.
1530 case RET_SMALL: /* return to GHC */
1534 cap->rCurrentTSO->what_next = ThreadEnterGHC;
1536 RETURN(ThreadYielding);
1538 belch("entered CONSTR with invalid continuation on stack");
1541 printObj(stgCast(StgClosure*,xSp));
1544 barf("bailing out");
1551 //fprintf(stderr, "enterCountI = %d\n", enterCountI);
1552 //fprintf(stderr, "entering unknown closure -- yielding to sched\n");
1555 cap->rCurrentTSO->what_next = ThreadEnterGHC;
1556 xPushCPtr(obj); /* code to restart with */
1557 RETURN(ThreadYielding);
1560 barf("Ran off the end of enter - yoiks");
1577 #undef xSetStackWord
1580 #undef xPushTaggedInt
1581 #undef xPopTaggedInt
1582 #undef xTaggedStackInt
1583 #undef xPushTaggedWord
1584 #undef xPopTaggedWord
1585 #undef xTaggedStackWord
1586 #undef xPushTaggedAddr
1587 #undef xTaggedStackAddr
1588 #undef xPopTaggedAddr
1589 #undef xPushTaggedStable
1590 #undef xTaggedStackStable
1591 #undef xPopTaggedStable
1592 #undef xPushTaggedChar
1593 #undef xTaggedStackChar
1594 #undef xPopTaggedChar
1595 #undef xPushTaggedFloat
1596 #undef xTaggedStackFloat
1597 #undef xPopTaggedFloat
1598 #undef xPushTaggedDouble
1599 #undef xTaggedStackDouble
1600 #undef xPopTaggedDouble
1601 #undef xPopUpdateFrame
1602 #undef xPushUpdateFrame
1605 /* --------------------------------------------------------------------------
1606 * Supporting routines for primops
1607 * ------------------------------------------------------------------------*/
1609 static inline void PushTag ( StackTag t )
1611 inline void PushPtr ( StgPtr x )
1612 { *(--stgCast(StgPtr*,gSp)) = x; }
1613 static inline void PushCPtr ( StgClosure* x )
1614 { *(--stgCast(StgClosure**,gSp)) = x; }
1615 static inline void PushInt ( StgInt x )
1616 { *(--stgCast(StgInt*,gSp)) = x; }
1617 static inline void PushWord ( StgWord x )
1618 { *(--stgCast(StgWord*,gSp)) = x; }
1621 static inline void checkTag ( StackTag t1, StackTag t2 )
1622 { ASSERT(t1 == t2);}
1623 static inline void PopTag ( StackTag t )
1624 { checkTag(t,*(gSp++)); }
1625 inline StgPtr PopPtr ( void )
1626 { return *stgCast(StgPtr*,gSp)++; }
1627 static inline StgClosure* PopCPtr ( void )
1628 { return *stgCast(StgClosure**,gSp)++; }
1629 static inline StgInt PopInt ( void )
1630 { return *stgCast(StgInt*,gSp)++; }
1631 static inline StgWord PopWord ( void )
1632 { return *stgCast(StgWord*,gSp)++; }
1634 static inline StgPtr stackPtr ( StgStackOffset i )
1635 { return *stgCast(StgPtr*, gSp+i); }
1636 static inline StgInt stackInt ( StgStackOffset i )
1637 { return *stgCast(StgInt*, gSp+i); }
1638 static inline StgWord stackWord ( StgStackOffset i )
1639 { return *stgCast(StgWord*,gSp+i); }
1641 static inline void setStackWord ( StgStackOffset i, StgWord w )
1645 static inline void setStackPtr ( StgStackOffset i, StgPtr p )
1646 { *(stgCast(StgPtr*, gSp+i)) = p; }
1649 static inline void PushTaggedRealWorld( void )
1650 { PushTag(REALWORLD_TAG); }
1651 inline void PushTaggedInt ( StgInt x )
1652 { gSp -= sizeofW(StgInt); *gSp = x; PushTag(INT_TAG); }
1653 inline void PushTaggedWord ( StgWord x )
1654 { gSp -= sizeofW(StgWord); *gSp = x; PushTag(WORD_TAG); }
1655 inline void PushTaggedAddr ( StgAddr x )
1656 { gSp -= sizeofW(StgAddr); *gSp = (W_)x; PushTag(ADDR_TAG); }
1657 inline void PushTaggedChar ( StgChar x )
1658 { gSp -= sizeofW(StgChar); *gSp = stgCast(StgWord,x); PushTag(CHAR_TAG); }
1659 inline void PushTaggedFloat ( StgFloat x )
1660 { gSp -= sizeofW(StgFloat); ASSIGN_FLT(gSp,x); PushTag(FLOAT_TAG); }
1661 inline void PushTaggedDouble ( StgDouble x )
1662 { gSp -= sizeofW(StgDouble); ASSIGN_DBL(gSp,x); PushTag(DOUBLE_TAG); }
1663 inline void PushTaggedStablePtr ( StgStablePtr x )
1664 { gSp -= sizeofW(StgStablePtr); *gSp = (W_)x; PushTag(STABLE_TAG); }
1665 static inline void PushTaggedBool ( int x )
1666 { PushTaggedInt(x); }
1670 static inline void PopTaggedRealWorld ( void )
1671 { PopTag(REALWORLD_TAG); }
1672 inline StgInt PopTaggedInt ( void )
1673 { StgInt r; PopTag(INT_TAG); r = *stgCast(StgInt*, gSp);
1674 gSp += sizeofW(StgInt); return r;}
1675 inline StgWord PopTaggedWord ( void )
1676 { StgWord r; PopTag(WORD_TAG); r = *stgCast(StgWord*, gSp);
1677 gSp += sizeofW(StgWord); return r;}
1678 inline StgAddr PopTaggedAddr ( void )
1679 { StgAddr r; PopTag(ADDR_TAG); r = *stgCast(StgAddr*, gSp);
1680 gSp += sizeofW(StgAddr); return r;}
1681 inline StgChar PopTaggedChar ( void )
1682 { StgChar r; PopTag(CHAR_TAG); r = stgCast(StgChar, *gSp);
1683 gSp += sizeofW(StgChar); return r;}
1684 inline StgFloat PopTaggedFloat ( void )
1685 { StgFloat r; PopTag(FLOAT_TAG); r = PK_FLT(gSp);
1686 gSp += sizeofW(StgFloat); return r;}
1687 inline StgDouble PopTaggedDouble ( void )
1688 { StgDouble r; PopTag(DOUBLE_TAG); r = PK_DBL(gSp);
1689 gSp += sizeofW(StgDouble); return r;}
1690 inline StgStablePtr PopTaggedStablePtr ( void )
1691 { StgStablePtr r; PopTag(STABLE_TAG); r = *stgCast(StgStablePtr*, gSp);
1692 gSp += sizeofW(StgStablePtr); return r;}
1696 static inline StgInt taggedStackInt ( StgStackOffset i )
1697 { checkTag(INT_TAG,gSp[i]); return *stgCast(StgInt*, gSp+1+i); }
1698 static inline StgWord taggedStackWord ( StgStackOffset i )
1699 { checkTag(WORD_TAG,gSp[i]); return *stgCast(StgWord*, gSp+1+i); }
1700 static inline StgAddr taggedStackAddr ( StgStackOffset i )
1701 { checkTag(ADDR_TAG,gSp[i]); return *stgCast(StgAddr*, gSp+1+i); }
1702 static inline StgChar taggedStackChar ( StgStackOffset i )
1703 { checkTag(CHAR_TAG,gSp[i]); return stgCast(StgChar, *(gSp+1+i)) ; }
1704 static inline StgFloat taggedStackFloat ( StgStackOffset i )
1705 { checkTag(FLOAT_TAG,gSp[i]); return PK_FLT(gSp+1+i); }
1706 static inline StgDouble taggedStackDouble ( StgStackOffset i )
1707 { checkTag(DOUBLE_TAG,gSp[i]); return PK_DBL(gSp+1+i); }
1708 static inline StgStablePtr taggedStackStable ( StgStackOffset i )
1709 { checkTag(STABLE_TAG,gSp[i]); return *stgCast(StgStablePtr*, gSp+1+i); }
1712 /* --------------------------------------------------------------------------
1715 * Should we allocate from a nursery or use the
1716 * doYouWantToGC/allocate interface? We'd already implemented a
1717 * nursery-style scheme when the doYouWantToGC/allocate interface
1719 * One reason to prefer the doYouWantToGC/allocate interface is to
1720 * support operations which allocate an unknown amount in the heap
1721 * (array ops, gmp ops, etc)
1722 * ------------------------------------------------------------------------*/
1724 static inline StgPtr grabHpUpd( nat size )
1726 ASSERT( size >= MIN_UPD_SIZE + sizeofW(StgHeader) );
1727 return allocate(size);
1730 static inline StgPtr grabHpNonUpd( nat size )
1732 ASSERT( size >= MIN_NONUPD_SIZE + sizeofW(StgHeader) );
1733 return allocate(size);
1736 /* --------------------------------------------------------------------------
1737 * Manipulate "update frame" list:
1738 * o Update frames (based on stg_do_update and friends in Updates.hc)
1739 * o Error handling/catching (based on catchzh_fast and friends in Prims.hc)
1740 * o Seq frames (based on seq_frame_entry in Prims.hc)
1742 * ------------------------------------------------------------------------*/
1744 static inline void PopUpdateFrame ( StgClosure* obj )
1746 /* NB: doesn't assume that gSp == gSu */
1748 fprintf(stderr, "Updating ");
1749 printPtr(stgCast(StgPtr,gSu->updatee));
1750 fprintf(stderr, " with ");
1752 fprintf(stderr,"gSp = %p\tgSu = %p\n\n", gSp, gSu);
1754 #ifdef EAGER_BLACKHOLING
1755 #warn LAZY_BLACKHOLING is default for StgHugs
1756 #error Dont know if EAGER_BLACKHOLING works in StgHugs
1757 ASSERT(get_itbl(gSu->updatee)->type == BLACKHOLE
1758 || get_itbl(gSu->updatee)->type == SE_BLACKHOLE
1759 || get_itbl(gSu->updatee)->type == CAF_BLACKHOLE
1760 || get_itbl(gSu->updatee)->type == SE_CAF_BLACKHOLE
1762 #endif /* EAGER_BLACKHOLING */
1763 UPD_IND(gSu->updatee,obj);
1764 gSp = stgCast(StgStackPtr,gSu) + sizeofW(StgUpdateFrame);
1768 static inline void PopStopFrame ( StgClosure* obj )
1770 /* Move gSu just off the end of the stack, we're about to gSpam the
1771 * STOP_FRAME with the return value.
1773 gSu = stgCast(StgUpdateFrame*,gSp+1);
1774 *stgCast(StgClosure**,gSp) = obj;
1777 static inline void PushCatchFrame ( StgClosure* handler )
1780 /* ToDo: stack check! */
1781 gSp -= sizeofW(StgCatchFrame);
1782 fp = stgCast(StgCatchFrame*,gSp);
1783 SET_HDR(fp,(StgInfoTable*)&catch_frame_info,CCCS);
1784 fp->handler = handler;
1786 gSu = stgCast(StgUpdateFrame*,fp);
1789 static inline void PopCatchFrame ( void )
1791 /* NB: doesn't assume that gSp == gSu */
1792 /* fprintf(stderr,"Popping catch frame\n"); */
1793 gSp = stgCast(StgStackPtr,gSu) + sizeofW(StgCatchFrame);
1794 gSu = stgCast(StgCatchFrame*,gSu)->link;
1797 static inline void PushSeqFrame ( void )
1800 /* ToDo: stack check! */
1801 gSp -= sizeofW(StgSeqFrame);
1802 fp = stgCast(StgSeqFrame*,gSp);
1803 SET_HDR(fp,(StgInfoTable*)&seq_frame_info,CCCS);
1805 gSu = stgCast(StgUpdateFrame*,fp);
1808 static inline void PopSeqFrame ( void )
1810 /* NB: doesn't assume that gSp == gSu */
1811 gSp = stgCast(StgStackPtr,gSu) + sizeofW(StgSeqFrame);
1812 gSu = stgCast(StgSeqFrame*,gSu)->link;
1815 static inline StgClosure* raiseAnError ( StgClosure* exception )
1817 /* This closure represents the expression 'primRaise E' where E
1818 * is the exception raised (:: Exception).
1819 * It is used to overwrite all the
1820 * thunks which are currently under evaluation.
1822 HaskellObj primRaiseClosure
1823 = getHugs_BCO_cptr_for("primRaise");
1824 HaskellObj reraiseClosure
1825 = rts_apply ( primRaiseClosure, exception );
1828 switch (get_itbl(gSu)->type) {
1830 UPD_IND(gSu->updatee,reraiseClosure);
1831 gSp = stgCast(StgStackPtr,gSu) + sizeofW(StgUpdateFrame);
1837 case CATCH_FRAME: /* found it! */
1839 StgCatchFrame* fp = stgCast(StgCatchFrame*,gSu);
1840 StgClosure *handler = fp->handler;
1842 gSp += sizeofW(StgCatchFrame); /* Pop */
1843 PushCPtr(exception);
1847 barf("raiseError: uncaught exception: STOP_FRAME");
1849 barf("raiseError: weird activation record");
1855 static StgClosure* makeErrorCall ( const char* msg )
1857 /* Note! the msg string should be allocated in a
1858 place which will not get freed -- preferably
1859 read-only data of the program. That's because
1860 the thunk we build here may linger indefinitely.
1861 (thinks: probably not so, but anyway ...)
1864 = getHugs_BCO_cptr_for("error");
1866 = getHugs_BCO_cptr_for("hugsprimUnpackString");
1868 = rts_apply ( unpack, rts_mkAddr ( (void*)msg ) );
1870 = rts_apply ( error, thunk );
1872 (StgClosure*) thunk;
1875 #define raiseIndex(where) makeErrorCall("Array index out of range in " where)
1876 #define raiseDiv0(where) makeErrorCall("Division by zero in " where)
1878 /* --------------------------------------------------------------------------
1880 * ------------------------------------------------------------------------*/
1882 #define OP_CC_B(e) \
1884 unsigned char x = PopTaggedChar(); \
1885 unsigned char y = PopTaggedChar(); \
1886 PushTaggedBool(e); \
1891 unsigned char x = PopTaggedChar(); \
1900 #define OP_IW_I(e) \
1902 StgInt x = PopTaggedInt(); \
1903 StgWord y = PopTaggedWord(); \
1907 #define OP_II_I(e) \
1909 StgInt x = PopTaggedInt(); \
1910 StgInt y = PopTaggedInt(); \
1914 #define OP_II_B(e) \
1916 StgInt x = PopTaggedInt(); \
1917 StgInt y = PopTaggedInt(); \
1918 PushTaggedBool(e); \
1923 PushTaggedAddr(e); \
1928 StgInt x = PopTaggedInt(); \
1929 PushTaggedAddr(e); \
1934 StgInt x = PopTaggedInt(); \
1940 PushTaggedChar(e); \
1945 StgInt x = PopTaggedInt(); \
1946 PushTaggedChar(e); \
1951 PushTaggedWord(e); \
1956 StgInt x = PopTaggedInt(); \
1957 PushTaggedWord(e); \
1962 StgInt x = PopTaggedInt(); \
1963 PushTaggedStablePtr(e); \
1968 PushTaggedFloat(e); \
1973 StgInt x = PopTaggedInt(); \
1974 PushTaggedFloat(e); \
1979 PushTaggedDouble(e); \
1984 StgInt x = PopTaggedInt(); \
1985 PushTaggedDouble(e); \
1988 #define OP_WW_B(e) \
1990 StgWord x = PopTaggedWord(); \
1991 StgWord y = PopTaggedWord(); \
1992 PushTaggedBool(e); \
1995 #define OP_WW_W(e) \
1997 StgWord x = PopTaggedWord(); \
1998 StgWord y = PopTaggedWord(); \
1999 PushTaggedWord(e); \
2004 StgWord x = PopTaggedWord(); \
2010 StgStablePtr x = PopTaggedStablePtr(); \
2016 StgWord x = PopTaggedWord(); \
2017 PushTaggedWord(e); \
2020 #define OP_AA_B(e) \
2022 StgAddr x = PopTaggedAddr(); \
2023 StgAddr y = PopTaggedAddr(); \
2024 PushTaggedBool(e); \
2028 StgAddr x = PopTaggedAddr(); \
2031 #define OP_AI_C(s) \
2033 StgAddr x = PopTaggedAddr(); \
2034 int y = PopTaggedInt(); \
2037 PushTaggedChar(r); \
2039 #define OP_AI_I(s) \
2041 StgAddr x = PopTaggedAddr(); \
2042 int y = PopTaggedInt(); \
2047 #define OP_AI_A(s) \
2049 StgAddr x = PopTaggedAddr(); \
2050 int y = PopTaggedInt(); \
2053 PushTaggedAddr(s); \
2055 #define OP_AI_F(s) \
2057 StgAddr x = PopTaggedAddr(); \
2058 int y = PopTaggedInt(); \
2061 PushTaggedFloat(r); \
2063 #define OP_AI_D(s) \
2065 StgAddr x = PopTaggedAddr(); \
2066 int y = PopTaggedInt(); \
2069 PushTaggedDouble(r); \
2071 #define OP_AI_s(s) \
2073 StgAddr x = PopTaggedAddr(); \
2074 int y = PopTaggedInt(); \
2077 PushTaggedStablePtr(r); \
2079 #define OP_AIC_(s) \
2081 StgAddr x = PopTaggedAddr(); \
2082 int y = PopTaggedInt(); \
2083 StgChar z = PopTaggedChar(); \
2086 #define OP_AII_(s) \
2088 StgAddr x = PopTaggedAddr(); \
2089 int y = PopTaggedInt(); \
2090 StgInt z = PopTaggedInt(); \
2093 #define OP_AIA_(s) \
2095 StgAddr x = PopTaggedAddr(); \
2096 int y = PopTaggedInt(); \
2097 StgAddr z = PopTaggedAddr(); \
2100 #define OP_AIF_(s) \
2102 StgAddr x = PopTaggedAddr(); \
2103 int y = PopTaggedInt(); \
2104 StgFloat z = PopTaggedFloat(); \
2107 #define OP_AID_(s) \
2109 StgAddr x = PopTaggedAddr(); \
2110 int y = PopTaggedInt(); \
2111 StgDouble z = PopTaggedDouble(); \
2114 #define OP_AIs_(s) \
2116 StgAddr x = PopTaggedAddr(); \
2117 int y = PopTaggedInt(); \
2118 StgStablePtr z = PopTaggedStablePtr(); \
2123 #define OP_FF_B(e) \
2125 StgFloat x = PopTaggedFloat(); \
2126 StgFloat y = PopTaggedFloat(); \
2127 PushTaggedBool(e); \
2130 #define OP_FF_F(e) \
2132 StgFloat x = PopTaggedFloat(); \
2133 StgFloat y = PopTaggedFloat(); \
2134 PushTaggedFloat(e); \
2139 StgFloat x = PopTaggedFloat(); \
2140 PushTaggedFloat(e); \
2145 StgFloat x = PopTaggedFloat(); \
2146 PushTaggedBool(e); \
2151 StgFloat x = PopTaggedFloat(); \
2157 StgFloat x = PopTaggedFloat(); \
2158 PushTaggedDouble(e); \
2161 #define OP_DD_B(e) \
2163 StgDouble x = PopTaggedDouble(); \
2164 StgDouble y = PopTaggedDouble(); \
2165 PushTaggedBool(e); \
2168 #define OP_DD_D(e) \
2170 StgDouble x = PopTaggedDouble(); \
2171 StgDouble y = PopTaggedDouble(); \
2172 PushTaggedDouble(e); \
2177 StgDouble x = PopTaggedDouble(); \
2178 PushTaggedBool(e); \
2183 StgDouble x = PopTaggedDouble(); \
2184 PushTaggedDouble(e); \
2189 StgDouble x = PopTaggedDouble(); \
2195 StgDouble x = PopTaggedDouble(); \
2196 PushTaggedFloat(e); \
2200 StgPtr CreateByteArrayToHoldInteger ( int nbytes )
2202 StgWord words = (nbytes+sizeof(W_)-1)/sizeof(W_);
2203 StgWord size = sizeofW(StgArrWords) + words;
2204 StgArrWords* arr = (StgArrWords*)allocate(size);
2205 SET_HDR(arr,&ARR_WORDS_info,CCCS);
2207 ASSERT((W_)nbytes <= arr->words * sizeof(W_));
2210 for (i = 0; i < words; ++i) {
2211 arr->payload[i] = 0xdeadbeef;
2213 { B* b = (B*) &(arr->payload[0]);
2214 b->used = b->sign = 0;
2220 B* IntegerInsideByteArray ( StgPtr arr0 )
2223 StgArrWords* arr = (StgArrWords*)arr0;
2224 ASSERT(GET_INFO(arr) == &ARR_WORDS_info);
2225 b = (B*) &(arr->payload[0]);
2229 void SloppifyIntegerEnd ( StgPtr arr0 )
2231 StgArrWords* arr = (StgArrWords*)arr0;
2232 B* b = (B*) & (arr->payload[0]);
2233 I_ nwunused = arr->words - sizeofW(B) - (b->used+sizeof(W_)-1)/sizeof(W_);
2234 if (nwunused >= ((I_)sizeofW(StgArrWords))) {
2236 b->size -= nwunused * sizeof(W_);
2237 if (b->size < b->used) b->size = b->used;
2240 arr->words -= nwunused;
2241 slop = (StgArrWords*)&(arr->payload[arr->words]);
2242 SET_HDR(slop,&ARR_WORDS_info,CCCS);
2243 slop->words = nwunused - sizeofW(StgArrWords);
2244 ASSERT( &(slop->payload[slop->words]) ==
2245 &(arr->payload[arr->words + nwunused]) );
2249 #define OP_Z_Z(op) \
2251 B* x = IntegerInsideByteArray(PopPtr()); \
2252 int n = mycat2(size_,op)(x); \
2253 StgPtr p = CreateByteArrayToHoldInteger(n); \
2254 mycat2(do_,op)(x,n,IntegerInsideByteArray(p)); \
2255 SloppifyIntegerEnd(p); \
2258 #define OP_ZZ_Z(op) \
2260 B* x = IntegerInsideByteArray(PopPtr()); \
2261 B* y = IntegerInsideByteArray(PopPtr()); \
2262 int n = mycat2(size_,op)(x,y); \
2263 StgPtr p = CreateByteArrayToHoldInteger(n); \
2264 mycat2(do_,op)(x,y,n,IntegerInsideByteArray(p)); \
2265 SloppifyIntegerEnd(p); \
2272 #define HEADER_mI(ty,where) \
2273 StgArrWords* x = stgCast(StgArrWords*,PopPtr()); \
2274 nat i = PopTaggedInt(); \
2275 if (i * sizeof(ty) + (sizeof(ty)) > sizeof(StgWord) * x->words) { \
2276 return (raiseIndex(where)); \
2278 #define OP_mI_ty(ty,where,s) \
2280 HEADER_mI(mycat2(Stg,ty),where) \
2281 { mycat2(Stg,ty) r; \
2283 mycat2(PushTagged,ty)(r); \
2286 #define OP_mIty_(ty,where,s) \
2288 HEADER_mI(mycat2(Stg,ty),where) \
2290 mycat2(Stg,ty) z = mycat2(PopTagged,ty)(); \
2296 __attribute__ ((unused))
2297 static void myStackCheck ( Capability* cap )
2299 /* fprintf(stderr, "myStackCheck\n"); */
2300 if (!(gSpLim <= gSp && gSp <= stgCast(StgPtr,gSu))) {
2301 fprintf(stderr, "myStackCheck: invalid initial gSp/gSu \n" );
2306 if (!( (P_)gSu >= (P_)cap->rCurrentTSO->stack
2308 (P_)gSu <= (P_)(cap->rCurrentTSO->stack
2309 + cap->rCurrentTSO->stack_size))) {
2310 fprintf ( stderr, "myStackCheck: gSu out of stack\n" );
2314 switch (get_itbl(stgCast(StgClosure*,gSu))->type) {
2316 gSu = (StgUpdateFrame*) ((StgCatchFrame*)(gSu))->link;
2319 gSu = (StgUpdateFrame*) ((StgUpdateFrame*)(gSu))->link;
2322 gSu = (StgUpdateFrame*) ((StgSeqFrame*)(gSu))->link;
2327 fprintf(stderr, "myStackCheck: invalid activation record\n");
2336 /* --------------------------------------------------------------------------
2337 * Primop stuff for bytecode interpreter
2338 * ------------------------------------------------------------------------*/
2340 /* Returns & of the next thing to enter (if throwing an exception),
2341 or NULL in the normal case.
2343 static void* enterBCO_primop1 ( int primop1code )
2346 barf("enterBCO_primop1 in combined mode");
2348 switch (primop1code) {
2349 case i_pushseqframe:
2351 StgClosure* c = PopCPtr();
2356 case i_pushcatchframe:
2358 StgClosure* e = PopCPtr();
2359 StgClosure* h = PopCPtr();
2365 case i_gtChar: OP_CC_B(x>y); break;
2366 case i_geChar: OP_CC_B(x>=y); break;
2367 case i_eqChar: OP_CC_B(x==y); break;
2368 case i_neChar: OP_CC_B(x!=y); break;
2369 case i_ltChar: OP_CC_B(x<y); break;
2370 case i_leChar: OP_CC_B(x<=y); break;
2371 case i_charToInt: OP_C_I(x); break;
2372 case i_intToChar: OP_I_C(x); break;
2374 case i_gtInt: OP_II_B(x>y); break;
2375 case i_geInt: OP_II_B(x>=y); break;
2376 case i_eqInt: OP_II_B(x==y); break;
2377 case i_neInt: OP_II_B(x!=y); break;
2378 case i_ltInt: OP_II_B(x<y); break;
2379 case i_leInt: OP_II_B(x<=y); break;
2380 case i_minInt: OP__I(INT_MIN); break;
2381 case i_maxInt: OP__I(INT_MAX); break;
2382 case i_plusInt: OP_II_I(x+y); break;
2383 case i_minusInt: OP_II_I(x-y); break;
2384 case i_timesInt: OP_II_I(x*y); break;
2387 int x = PopTaggedInt();
2388 int y = PopTaggedInt();
2390 return (raiseDiv0("quotInt"));
2392 /* ToDo: protect against minInt / -1 errors
2393 * (repeat for all other division primops) */
2399 int x = PopTaggedInt();
2400 int y = PopTaggedInt();
2402 return (raiseDiv0("remInt"));
2409 StgInt x = PopTaggedInt();
2410 StgInt y = PopTaggedInt();
2412 return (raiseDiv0("quotRemInt"));
2414 PushTaggedInt(x%y); /* last result */
2415 PushTaggedInt(x/y); /* first result */
2418 case i_negateInt: OP_I_I(-x); break;
2420 case i_andInt: OP_II_I(x&y); break;
2421 case i_orInt: OP_II_I(x|y); break;
2422 case i_xorInt: OP_II_I(x^y); break;
2423 case i_notInt: OP_I_I(~x); break;
2424 case i_shiftLInt: OP_II_I(x<<y); break;
2425 case i_shiftRAInt: OP_II_I(x>>y); break; /* ToDo */
2426 case i_shiftRLInt: OP_II_I(x>>y); break; /* ToDo */
2428 case i_gtWord: OP_WW_B(x>y); break;
2429 case i_geWord: OP_WW_B(x>=y); break;
2430 case i_eqWord: OP_WW_B(x==y); break;
2431 case i_neWord: OP_WW_B(x!=y); break;
2432 case i_ltWord: OP_WW_B(x<y); break;
2433 case i_leWord: OP_WW_B(x<=y); break;
2434 case i_minWord: OP__W(0); break;
2435 case i_maxWord: OP__W(UINT_MAX); break;
2436 case i_plusWord: OP_WW_W(x+y); break;
2437 case i_minusWord: OP_WW_W(x-y); break;
2438 case i_timesWord: OP_WW_W(x*y); break;
2441 StgWord x = PopTaggedWord();
2442 StgWord y = PopTaggedWord();
2444 return (raiseDiv0("quotWord"));
2446 PushTaggedWord(x/y);
2451 StgWord x = PopTaggedWord();
2452 StgWord y = PopTaggedWord();
2454 return (raiseDiv0("remWord"));
2456 PushTaggedWord(x%y);
2461 StgWord x = PopTaggedWord();
2462 StgWord y = PopTaggedWord();
2464 return (raiseDiv0("quotRemWord"));
2466 PushTaggedWord(x%y); /* last result */
2467 PushTaggedWord(x/y); /* first result */
2470 case i_negateWord: OP_W_W(-x); break;
2471 case i_andWord: OP_WW_W(x&y); break;
2472 case i_orWord: OP_WW_W(x|y); break;
2473 case i_xorWord: OP_WW_W(x^y); break;
2474 case i_notWord: OP_W_W(~x); break;
2475 case i_shiftLWord: OP_WW_W(x<<y); break;
2476 case i_shiftRAWord: OP_WW_W(x>>y); break; /* ToDo */
2477 case i_shiftRLWord: OP_WW_W(x>>y); break; /* ToDo */
2478 case i_intToWord: OP_I_W(x); break;
2479 case i_wordToInt: OP_W_I(x); break;
2481 case i_gtAddr: OP_AA_B(x>y); break;
2482 case i_geAddr: OP_AA_B(x>=y); break;
2483 case i_eqAddr: OP_AA_B(x==y); break;
2484 case i_neAddr: OP_AA_B(x!=y); break;
2485 case i_ltAddr: OP_AA_B(x<y); break;
2486 case i_leAddr: OP_AA_B(x<=y); break;
2487 case i_intToAddr: OP_I_A((StgAddr)x); break; /* ToDo */
2488 case i_addrToInt: OP_A_I((StgInt)x); break; /* ToDo */
2490 case i_intToStable: OP_I_s((StgStablePtr)x); break;
2491 case i_stableToInt: OP_s_I((W_)x); break;
2493 case i_indexCharOffAddr: OP_AI_C(indexCharOffAddrzh(r,x,y)); break;
2494 case i_readCharOffAddr: OP_AI_C(indexCharOffAddrzh(r,x,y)); break;
2495 case i_writeCharOffAddr: OP_AIC_(writeCharOffAddrzh(x,y,z)); break;
2497 case i_indexIntOffAddr: OP_AI_I(indexIntOffAddrzh(r,x,y)); break;
2498 case i_readIntOffAddr: OP_AI_I(indexIntOffAddrzh(r,x,y)); break;
2499 case i_writeIntOffAddr: OP_AII_(writeIntOffAddrzh(x,y,z)); break;
2501 case i_indexAddrOffAddr: OP_AI_A(indexAddrOffAddrzh(r,x,y)); break;
2502 case i_readAddrOffAddr: OP_AI_A(indexAddrOffAddrzh(r,x,y)); break;
2503 case i_writeAddrOffAddr: OP_AIA_(writeAddrOffAddrzh(x,y,z)); break;
2505 case i_indexFloatOffAddr: OP_AI_F(indexFloatOffAddrzh(r,x,y)); break;
2506 case i_readFloatOffAddr: OP_AI_F(indexFloatOffAddrzh(r,x,y)); break;
2507 case i_writeFloatOffAddr: OP_AIF_(writeFloatOffAddrzh(x,y,z)); break;
2509 case i_indexDoubleOffAddr: OP_AI_D(indexDoubleOffAddrzh(r,x,y)); break;
2510 case i_readDoubleOffAddr: OP_AI_D(indexDoubleOffAddrzh(r,x,y)); break;
2511 case i_writeDoubleOffAddr: OP_AID_(writeDoubleOffAddrzh(x,y,z)); break;
2513 case i_indexStableOffAddr: OP_AI_s(indexStablePtrOffAddrzh(r,x,y)); break;
2514 case i_readStableOffAddr: OP_AI_s(indexStablePtrOffAddrzh(r,x,y)); break;
2515 case i_writeStableOffAddr: OP_AIs_(writeStablePtrOffAddrzh(x,y,z)); break;
2517 case i_compareInteger:
2519 B* x = IntegerInsideByteArray(PopPtr());
2520 B* y = IntegerInsideByteArray(PopPtr());
2521 StgInt r = do_cmp(x,y);
2522 PushTaggedInt(r<0 ? -1 : (r>0 ? 1 : 0));
2525 case i_negateInteger: OP_Z_Z(neg); break;
2526 case i_plusInteger: OP_ZZ_Z(add); break;
2527 case i_minusInteger: OP_ZZ_Z(sub); break;
2528 case i_timesInteger: OP_ZZ_Z(mul); break;
2529 case i_quotRemInteger:
2531 B* x = IntegerInsideByteArray(PopPtr());
2532 B* y = IntegerInsideByteArray(PopPtr());
2533 int n = size_qrm(x,y);
2534 StgPtr q = CreateByteArrayToHoldInteger(n);
2535 StgPtr r = CreateByteArrayToHoldInteger(n);
2536 if (do_getsign(y)==0)
2537 return (raiseDiv0("quotRemInteger"));
2538 do_qrm(x,y,n,IntegerInsideByteArray(q),
2539 IntegerInsideByteArray(r));
2540 SloppifyIntegerEnd(q);
2541 SloppifyIntegerEnd(r);
2546 case i_intToInteger:
2548 int n = size_fromInt();
2549 StgPtr p = CreateByteArrayToHoldInteger(n);
2550 do_fromInt( PopTaggedInt(), n, IntegerInsideByteArray(p));
2554 case i_wordToInteger:
2556 int n = size_fromWord();
2557 StgPtr p = CreateByteArrayToHoldInteger(n);
2558 do_fromWord( PopTaggedWord(), n, IntegerInsideByteArray(p));
2562 case i_integerToInt: PushTaggedInt(do_toInt(
2563 IntegerInsideByteArray(PopPtr())
2567 case i_integerToWord: PushTaggedWord(do_toWord(
2568 IntegerInsideByteArray(PopPtr())
2572 case i_integerToFloat: PushTaggedFloat(do_toFloat(
2573 IntegerInsideByteArray(PopPtr())
2577 case i_integerToDouble: PushTaggedDouble(do_toDouble(
2578 IntegerInsideByteArray(PopPtr())
2582 case i_gtFloat: OP_FF_B(x>y); break;
2583 case i_geFloat: OP_FF_B(x>=y); break;
2584 case i_eqFloat: OP_FF_B(x==y); break;
2585 case i_neFloat: OP_FF_B(x!=y); break;
2586 case i_ltFloat: OP_FF_B(x<y); break;
2587 case i_leFloat: OP_FF_B(x<=y); break;
2588 case i_minFloat: OP__F(FLT_MIN); break;
2589 case i_maxFloat: OP__F(FLT_MAX); break;
2590 case i_radixFloat: OP__I(FLT_RADIX); break;
2591 case i_digitsFloat: OP__I(FLT_MANT_DIG); break;
2592 case i_minExpFloat: OP__I(FLT_MIN_EXP); break;
2593 case i_maxExpFloat: OP__I(FLT_MAX_EXP); break;
2594 case i_plusFloat: OP_FF_F(x+y); break;
2595 case i_minusFloat: OP_FF_F(x-y); break;
2596 case i_timesFloat: OP_FF_F(x*y); break;
2599 StgFloat x = PopTaggedFloat();
2600 StgFloat y = PopTaggedFloat();
2601 PushTaggedFloat(x/y);
2604 case i_negateFloat: OP_F_F(-x); break;
2605 case i_floatToInt: OP_F_I(x); break;
2606 case i_intToFloat: OP_I_F(x); break;
2607 case i_expFloat: OP_F_F(exp(x)); break;
2608 case i_logFloat: OP_F_F(log(x)); break;
2609 case i_sqrtFloat: OP_F_F(sqrt(x)); break;
2610 case i_sinFloat: OP_F_F(sin(x)); break;
2611 case i_cosFloat: OP_F_F(cos(x)); break;
2612 case i_tanFloat: OP_F_F(tan(x)); break;
2613 case i_asinFloat: OP_F_F(asin(x)); break;
2614 case i_acosFloat: OP_F_F(acos(x)); break;
2615 case i_atanFloat: OP_F_F(atan(x)); break;
2616 case i_sinhFloat: OP_F_F(sinh(x)); break;
2617 case i_coshFloat: OP_F_F(cosh(x)); break;
2618 case i_tanhFloat: OP_F_F(tanh(x)); break;
2619 case i_powerFloat: OP_FF_F(pow(x,y)); break;
2621 case i_encodeFloatZ:
2623 StgPtr sig = PopPtr();
2624 StgInt exp = PopTaggedInt();
2626 B__encodeFloat(IntegerInsideByteArray(sig), exp)
2630 case i_decodeFloatZ:
2632 StgFloat f = PopTaggedFloat();
2633 StgPtr sig = CreateByteArrayToHoldInteger(size_fltmantissa());
2635 B__decodeFloat(IntegerInsideByteArray(sig), &exp, f);
2641 case i_isNaNFloat: OP_F_B(isFloatNaN(x)); break;
2642 case i_isInfiniteFloat: OP_F_B(isFloatInfinite(x)); break;
2643 case i_isNegativeZeroFloat: OP_F_B(isFloatNegativeZero(x)); break;
2644 case i_isDenormalizedFloat: OP_F_B(isFloatDenormalized(x)); break;
2645 case i_gtDouble: OP_DD_B(x>y); break;
2646 case i_geDouble: OP_DD_B(x>=y); break;
2647 case i_eqDouble: OP_DD_B(x==y); break;
2648 case i_neDouble: OP_DD_B(x!=y); break;
2649 case i_ltDouble: OP_DD_B(x<y); break;
2650 case i_leDouble: OP_DD_B(x<=y) break;
2651 case i_minDouble: OP__D(DBL_MIN); break;
2652 case i_maxDouble: OP__D(DBL_MAX); break;
2653 case i_radixDouble: OP__I(FLT_RADIX); break;
2654 case i_digitsDouble: OP__I(DBL_MANT_DIG); break;
2655 case i_minExpDouble: OP__I(DBL_MIN_EXP); break;
2656 case i_maxExpDouble: OP__I(DBL_MAX_EXP); break;
2657 case i_plusDouble: OP_DD_D(x+y); break;
2658 case i_minusDouble: OP_DD_D(x-y); break;
2659 case i_timesDouble: OP_DD_D(x*y); break;
2660 case i_divideDouble:
2662 StgDouble x = PopTaggedDouble();
2663 StgDouble y = PopTaggedDouble();
2664 PushTaggedDouble(x/y);
2667 case i_negateDouble: OP_D_D(-x); break;
2668 case i_doubleToInt: OP_D_I(x); break;
2669 case i_intToDouble: OP_I_D(x); break;
2670 case i_doubleToFloat: OP_D_F(x); break;
2671 case i_floatToDouble: OP_F_F(x); break;
2672 case i_expDouble: OP_D_D(exp(x)); break;
2673 case i_logDouble: OP_D_D(log(x)); break;
2674 case i_sqrtDouble: OP_D_D(sqrt(x)); break;
2675 case i_sinDouble: OP_D_D(sin(x)); break;
2676 case i_cosDouble: OP_D_D(cos(x)); break;
2677 case i_tanDouble: OP_D_D(tan(x)); break;
2678 case i_asinDouble: OP_D_D(asin(x)); break;
2679 case i_acosDouble: OP_D_D(acos(x)); break;
2680 case i_atanDouble: OP_D_D(atan(x)); break;
2681 case i_sinhDouble: OP_D_D(sinh(x)); break;
2682 case i_coshDouble: OP_D_D(cosh(x)); break;
2683 case i_tanhDouble: OP_D_D(tanh(x)); break;
2684 case i_powerDouble: OP_DD_D(pow(x,y)); break;
2686 case i_encodeDoubleZ:
2688 StgPtr sig = PopPtr();
2689 StgInt exp = PopTaggedInt();
2691 B__encodeDouble(IntegerInsideByteArray(sig), exp)
2695 case i_decodeDoubleZ:
2697 StgDouble d = PopTaggedDouble();
2698 StgPtr sig = CreateByteArrayToHoldInteger(size_dblmantissa());
2700 B__decodeDouble(IntegerInsideByteArray(sig), &exp, d);
2706 case i_isNaNDouble: OP_D_B(isDoubleNaN(x)); break;
2707 case i_isInfiniteDouble: OP_D_B(isDoubleInfinite(x)); break;
2708 case i_isNegativeZeroDouble: OP_D_B(isDoubleNegativeZero(x)); break;
2709 case i_isDenormalizedDouble: OP_D_B(isDoubleDenormalized(x)); break;
2710 case i_isIEEEDouble:
2712 PushTaggedBool(rtsTrue);
2716 barf("Unrecognised primop1");
2723 /* For normal cases, return NULL and leave *return2 unchanged.
2724 To return the address of the next thing to enter,
2725 return the address of it and leave *return2 unchanged.
2726 To return a StgThreadReturnCode to the scheduler,
2727 set *return2 to it and return a non-NULL value.
2728 To cause a context switch, set context_switch (its a global),
2729 and optionally set hugsBlock to your rational.
2731 static void* enterBCO_primop2 ( int primop2code,
2732 int* /*StgThreadReturnCode* */ return2,
2735 HugsBlock *hugsBlock )
2738 /* A small concession: we need to allow ccalls,
2739 even in combined mode.
2741 if (primop2code != i_ccall_ccall_IO &&
2742 primop2code != i_ccall_stdcall_IO)
2743 barf("enterBCO_primop2 in combined mode");
2746 switch (primop2code) {
2747 case i_raise: /* raise#{err} */
2749 StgClosure* err = PopCPtr();
2750 return (raiseAnError(err));
2753 /*------------------------------------------------------------------------
2754 Insert and Remove primitives on Rows
2755 ------------------------------------------------------------------------*/
2759 /* get: row, index and value */
2760 StgMutArrPtrs* row = stgCast(StgMutArrPtrs*,PopPtr());
2761 nat i = PopTaggedInt();
2762 StgClosure* x = PopCPtr();
2764 /* allocate new row */
2765 StgWord n = row->ptrs;
2766 StgMutArrPtrs* newRow
2767 = stgCast(StgMutArrPtrs*,allocate(sizeofW(StgMutArrPtrs) + n + 1));
2768 SET_HDR(newRow,&MUT_ARR_PTRS_FROZEN_info,CCCS);
2773 /* copy the fields, inserting the new value */
2774 for (j = 0; j < i; j++) {
2775 newRow->payload[j] = row->payload[j];
2777 newRow->payload[i] = x;
2778 for (j = i+1; j <= n; j++)
2780 newRow->payload[j] = row->payload[j-1];
2783 PushPtr(stgCast(StgPtr,newRow));
2790 /* get row and index */
2791 StgMutArrPtrs* row = stgCast(StgMutArrPtrs*,PopPtr());
2792 nat i = PopTaggedInt(); /* or Word?? */
2794 /* allocate new row */
2795 StgWord n = row->ptrs;
2796 StgMutArrPtrs* newRow
2797 = stgCast(StgMutArrPtrs*,allocate(sizeofW(StgMutArrPtrs) + n - 1));
2798 SET_HDR(newRow,&MUT_ARR_PTRS_FROZEN_info,CCCS);
2803 /* copy the fields, except for the removed value. */
2804 for (j = 0; j < i; j++) {
2805 newRow->payload[j] = row->payload[j];
2807 for (j = i+1; j < n; j++)
2809 newRow->payload[j-1] = row->payload[j];
2812 PushCPtr(row->payload[i]);
2813 PushPtr(stgCast(StgPtr,newRow));
2816 #endif /* XMLAMBDA */
2820 StgClosure* init = PopCPtr();
2822 = stgCast(StgMutVar*,allocate(sizeofW(StgMutVar)));
2823 SET_HDR(mv,&MUT_VAR_info,CCCS);
2825 PushPtr(stgCast(StgPtr,mv));
2830 StgMutVar* mv = stgCast(StgMutVar*,PopPtr());
2836 StgMutVar* mv = stgCast(StgMutVar*,PopPtr());
2837 StgClosure* value = PopCPtr();
2843 nat n = PopTaggedInt(); /* or Word?? */
2844 StgClosure* init = PopCPtr();
2845 StgWord size = sizeofW(StgMutArrPtrs) + n;
2848 = stgCast(StgMutArrPtrs*,allocate(size));
2849 SET_HDR(arr,&MUT_ARR_PTRS_info,CCCS);
2851 for (i = 0; i < n; ++i) {
2852 arr->payload[i] = init;
2854 PushPtr(stgCast(StgPtr,arr));
2860 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
2861 nat i = PopTaggedInt(); /* or Word?? */
2862 StgWord n = arr->ptrs;
2864 return (raiseIndex("{index,read}Array"));
2866 PushCPtr(arr->payload[i]);
2871 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
2872 nat i = PopTaggedInt(); /* or Word? */
2873 StgClosure* v = PopCPtr();
2874 StgWord n = arr->ptrs;
2876 return (raiseIndex("{index,read}Array"));
2878 arr->payload[i] = v;
2882 case i_sizeMutableArray:
2884 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
2885 PushTaggedInt(arr->ptrs);
2888 case i_unsafeFreezeArray:
2890 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
2891 SET_INFO(arr,&MUT_ARR_PTRS_FROZEN_info);
2892 PushPtr(stgCast(StgPtr,arr));
2895 case i_unsafeFreezeByteArray:
2897 /* Delightfully simple :-) */
2901 case i_sameMutableArray:
2902 case i_sameMutableByteArray:
2904 StgPtr x = PopPtr();
2905 StgPtr y = PopPtr();
2906 PushTaggedBool(x==y);
2910 case i_newByteArray:
2912 nat n = PopTaggedInt(); /* or Word?? */
2913 StgInt words = (n+sizeof(W_)-1)/sizeof(W_);
2914 StgWord size = sizeofW(StgArrWords) + words;
2915 StgArrWords* arr = stgCast(StgArrWords*,allocate(size));
2916 SET_HDR(arr,&ARR_WORDS_info,CCCS);
2920 for (i = 0; i < n; ++i) {
2921 arr->payload[i] = 0xdeadbeef;
2924 PushPtr(stgCast(StgPtr,arr));
2928 /* Most of these generate alignment warnings on Sparcs and similar architectures.
2929 * These are harmless and are caused by the cast to C* in BYTE_ARR_CTS.
2931 case i_indexCharArray:
2932 OP_mI_ty(Char,"indexCharArray", indexCharArrayzh(r,x,i)); break;
2933 case i_readCharArray:
2934 OP_mI_ty(Char,"readCharArray", readCharArrayzh(r,x,i)); break;
2935 case i_writeCharArray:
2936 OP_mIty_(Char,"writeCharArray", writeCharArrayzh(x,i,z)); break;
2938 case i_indexIntArray:
2939 OP_mI_ty(Int,"indexIntArray", indexIntArrayzh(r,x,i)); break;
2940 case i_readIntArray:
2941 OP_mI_ty(Int,"readIntArray", readIntArrayzh(r,x,i)); break;
2942 case i_writeIntArray:
2943 OP_mIty_(Int,"writeIntArray", writeIntArrayzh(x,i,z)); break;
2945 case i_indexAddrArray:
2946 OP_mI_ty(Addr,"indexAddrArray", indexAddrArrayzh(r,x,i)); break;
2947 case i_readAddrArray:
2948 OP_mI_ty(Addr,"readAddrArray", readAddrArrayzh(r,x,i)); break;
2949 case i_writeAddrArray:
2950 OP_mIty_(Addr,"writeAddrArray", writeAddrArrayzh(x,i,z)); break;
2952 case i_indexFloatArray:
2953 OP_mI_ty(Float,"indexFloatArray", indexFloatArrayzh(r,x,i)); break;
2954 case i_readFloatArray:
2955 OP_mI_ty(Float,"readFloatArray", readFloatArrayzh(r,x,i)); break;
2956 case i_writeFloatArray:
2957 OP_mIty_(Float,"writeFloatArray", writeFloatArrayzh(x,i,z)); break;
2959 case i_indexDoubleArray:
2960 OP_mI_ty(Double,"indexDoubleArray", indexDoubleArrayzh(r,x,i)); break;
2961 case i_readDoubleArray:
2962 OP_mI_ty(Double,"readDoubleArray", readDoubleArrayzh(r,x,i)); break;
2963 case i_writeDoubleArray:
2964 OP_mIty_(Double,"writeDoubleArray", writeDoubleArrayzh(x,i,z)); break;
2967 #ifdef PROVIDE_STABLE
2968 case i_indexStableArray:
2969 OP_mI_ty(StablePtr,"indexStableArray", indexStablePtrArrayzh(r,x,i)); break;
2970 case i_readStableArray:
2971 OP_mI_ty(StablePtr,"readStableArray", readStablePtrArrayzh(r,x,i)); break;
2972 case i_writeStableArray:
2973 OP_mIty_(StablePtr,"writeStableArray", writeStablePtrArrayzh(x,i,z)); break;
2979 #ifdef PROVIDE_COERCE
2980 case i_unsafeCoerce:
2982 /* Another nullop */
2986 #ifdef PROVIDE_PTREQUALITY
2987 case i_reallyUnsafePtrEquality:
2988 { /* identical to i_sameRef */
2989 StgPtr x = PopPtr();
2990 StgPtr y = PopPtr();
2991 PushTaggedBool(x==y);
2995 #ifdef PROVIDE_FOREIGN
2996 /* ForeignObj# operations */
2997 case i_mkForeignObj:
2999 StgForeignObj *result
3000 = stgCast(StgForeignObj*,allocate(sizeofW(StgForeignObj)));
3001 SET_HDR(result,&FOREIGN_info,CCCS);
3002 result -> data = PopTaggedAddr();
3003 PushPtr(stgCast(StgPtr,result));
3006 #endif /* PROVIDE_FOREIGN */
3011 = stgCast(StgWeak*,allocate(sizeofW(StgWeak)));
3012 SET_HDR(w, &WEAK_info, CCCS);
3014 w->value = PopCPtr();
3015 w->finaliser = PopCPtr();
3016 w->link = weak_ptr_list;
3018 IF_DEBUG(weak, fprintf(stderr,"New weak pointer at %p\n",w));
3019 PushPtr(stgCast(StgPtr,w));
3024 StgWeak *w = stgCast(StgWeak*,PopPtr());
3025 if (w->header.info == &WEAK_info) {
3026 PushCPtr(w->value); /* last result */
3027 PushTaggedInt(1); /* first result */
3029 PushPtr(stgCast(StgPtr,w));
3030 /* ToDo: error thunk would be better */
3035 #endif /* PROVIDE_WEAK */
3037 case i_makeStablePtr:
3039 StgPtr p = PopPtr();
3040 StgStablePtr sp = getStablePtr ( p );
3041 PushTaggedStablePtr(sp);
3044 case i_deRefStablePtr:
3047 StgStablePtr sp = PopTaggedStablePtr();
3048 p = deRefStablePtr(sp);
3052 case i_freeStablePtr:
3054 StgStablePtr sp = PopTaggedStablePtr();
3059 case i_createAdjThunkARCH:
3061 StgStablePtr stableptr = PopTaggedStablePtr();
3062 StgAddr typestr = PopTaggedAddr();
3063 StgChar callconv = PopTaggedChar();
3064 StgAddr adj_thunk = createAdjThunk(stableptr,typestr,callconv);
3065 PushTaggedAddr(adj_thunk);
3071 StgInt n = prog_argc;
3077 StgInt n = PopTaggedInt();
3078 StgAddr a = (StgAddr)prog_argv[n];
3085 StgMVar *mvar = stgCast(StgMVar*,allocate(sizeofW(StgMVar)));
3086 SET_INFO(mvar,&EMPTY_MVAR_info);
3087 mvar->head = mvar->tail = (StgTSO *)&END_TSO_QUEUE_closure;
3088 mvar->value = stgCast(StgClosure*,&END_TSO_QUEUE_closure);
3089 PushPtr(stgCast(StgPtr,mvar));
3094 StgMVar *mvar = (StgMVar*)PopCPtr();
3095 if (GET_INFO(mvar) == &EMPTY_MVAR_info) {
3097 /* The MVar is empty. Attach ourselves to the TSO's
3100 if (mvar->head == (StgTSO *)&END_TSO_QUEUE_closure) {
3101 mvar->head = cap->rCurrentTSO;
3103 mvar->tail->link = cap->rCurrentTSO;
3105 cap->rCurrentTSO->link = (StgTSO *)&END_TSO_QUEUE_closure;
3106 cap->rCurrentTSO->why_blocked = BlockedOnMVar;
3107 cap->rCurrentTSO->block_info.closure = (StgClosure *)mvar;
3108 mvar->tail = cap->rCurrentTSO;
3110 /* At this point, the top-of-stack holds the MVar,
3111 and underneath is the world token (). So the
3112 stack is in the same state as when primTakeMVar
3113 was entered (primTakeMVar is handwritten bytecode).
3114 Push obj, which is this BCO, and return to the
3115 scheduler. When the MVar is filled, the scheduler
3116 will re-enter primTakeMVar, with the args still on
3117 the top of the stack.
3119 PushCPtr((StgClosure*)(*bco));
3120 *return2 = ThreadBlocked;
3121 return (void*)(1+(char*)(NULL));
3124 PushCPtr(mvar->value);
3125 mvar->value = (StgClosure *)&END_TSO_QUEUE_closure;
3126 SET_INFO(mvar,&EMPTY_MVAR_info);
3132 StgMVar* mvar = stgCast(StgMVar*,PopPtr());
3133 StgClosure* value = PopCPtr();
3134 if (GET_INFO(mvar) == &FULL_MVAR_info) {
3135 return (makeErrorCall("putMVar {full MVar}"));
3137 /* wake up the first thread on the
3138 * queue, it will continue with the
3139 * takeMVar operation and mark the
3142 mvar->value = value;
3144 if (mvar->head != (StgTSO *)&END_TSO_QUEUE_closure) {
3145 ASSERT(mvar->head->why_blocked == BlockedOnMVar);
3146 mvar->head = unblockOne(mvar->head);
3147 if (mvar->head == (StgTSO *)&END_TSO_QUEUE_closure) {
3148 mvar->tail = (StgTSO *)&END_TSO_QUEUE_closure;
3152 /* unlocks the MVar in the SMP case */
3153 SET_INFO(mvar,&FULL_MVAR_info);
3155 /* yield for better communication performance */
3161 { /* identical to i_sameRef */
3162 StgMVar* x = (StgMVar*)PopPtr();
3163 StgMVar* y = (StgMVar*)PopPtr();
3164 PushTaggedBool(x==y);
3167 #ifdef PROVIDE_CONCURRENT
3170 StgClosure* closure;
3173 closure = PopCPtr();
3174 tso = createGenThread (RtsFlags.GcFlags.initialStkSize,closure);
3176 scheduleThread(tso);
3178 /* Later: Change to use tso as the ThreadId */
3179 PushTaggedWord(tid);
3185 StgWord n = PopTaggedWord();
3189 // Map from ThreadId to Thread Structure */
3190 for (t = all_threads; t != END_TSO_QUEUE; t = t->global_link) {
3199 while (tso->what_next == ThreadRelocated) {
3204 if (tso == cap->rCurrentTSO) { /* suicide */
3205 *return2 = ThreadFinished;
3206 return (void*)(1+(char*)(NULL));
3210 case i_raiseInThread:
3211 barf("raiseInThread");
3212 ASSERT(0); /* not (yet) supported */
3215 StgInt n = PopTaggedInt();
3217 hugsBlock->reason = BlockedOnDelay;
3218 hugsBlock->delay = n;
3223 StgInt n = PopTaggedInt();
3225 hugsBlock->reason = BlockedOnRead;
3226 hugsBlock->delay = n;
3231 StgInt n = PopTaggedInt();
3233 hugsBlock->reason = BlockedOnWrite;
3234 hugsBlock->delay = n;
3239 /* The definition of yield include an enter right after
3240 * the primYield, at which time context_switch is tested.
3247 StgWord tid = cap->rCurrentTSO->id;
3248 PushTaggedWord(tid);
3251 case i_cmpThreadIds:
3253 StgWord tid1 = PopTaggedWord();
3254 StgWord tid2 = PopTaggedWord();
3255 if (tid1 < tid2) PushTaggedInt(-1);
3256 else if (tid1 > tid2) PushTaggedInt(1);
3257 else PushTaggedInt(0);
3260 #endif /* PROVIDE_CONCURRENT */
3262 case i_ccall_ccall_Id:
3263 case i_ccall_ccall_IO:
3264 case i_ccall_stdcall_Id:
3265 case i_ccall_stdcall_IO:
3268 CFunDescriptor* descriptor;
3269 void (*funPtr)(void);
3271 descriptor = PopTaggedAddr();
3272 funPtr = PopTaggedAddr();
3273 cc = (primop2code == i_ccall_stdcall_Id ||
3274 primop2code == i_ccall_stdcall_IO)
3276 r = ccall(descriptor,funPtr,bco,cc,cap);
3279 return makeErrorCall(
3280 "unhandled type or too many args/results in ccall");
3282 barf("ccall not configured correctly for this platform");
3283 barf("unknown return code from ccall");
3286 barf("Unrecognised primop2");
3292 /* -----------------------------------------------------------------------------
3293 * ccall support code:
3294 * marshall moves args from C stack to Haskell stack
3295 * unmarshall moves args from Haskell stack to C stack
3296 * argSize calculates how much gSpace you need on the C stack
3297 * ---------------------------------------------------------------------------*/
3299 /* Pop arguments off the C stack and Push them onto the Hugs stack.
3300 * Used when preparing for C calling Haskell or in regSponse to
3301 * Haskell calling C.
3303 nat marshall(char arg_ty, void* arg)
3307 PushTaggedInt(*((int*)arg));
3308 return ARG_SIZE(INT_TAG);
3311 PushTaggedInteger(*((mpz_ptr*)arg));
3312 return ARG_SIZE(INTEGER_TAG);
3315 PushTaggedWord(*((unsigned int*)arg));
3316 return ARG_SIZE(WORD_TAG);
3318 PushTaggedChar(*((char*)arg));
3319 return ARG_SIZE(CHAR_TAG);
3321 PushTaggedFloat(*((float*)arg));
3322 return ARG_SIZE(FLOAT_TAG);
3324 PushTaggedDouble(*((double*)arg));
3325 return ARG_SIZE(DOUBLE_TAG);
3327 PushTaggedAddr(*((void**)arg));
3328 return ARG_SIZE(ADDR_TAG);
3330 PushTaggedStablePtr(*((StgStablePtr*)arg));
3331 return ARG_SIZE(STABLE_TAG);
3332 #ifdef PROVIDE_FOREIGN
3334 /* Not allowed in this direction - you have to
3335 * call makeForeignPtr explicitly
3337 barf("marshall: ForeignPtr#\n");
3342 /* Not allowed in this direction */
3343 barf("marshall: [Mutable]ByteArray#\n");
3346 barf("marshall: unrecognised arg type %d\n",arg_ty);
3351 /* Pop arguments off the Hugs stack and Push them onto the C stack.
3352 * Used when preparing for Haskell calling C or in regSponse to
3353 * C calling Haskell.
3355 nat unmarshall(char res_ty, void* res)
3359 *((int*)res) = PopTaggedInt();
3360 return ARG_SIZE(INT_TAG);
3363 *((mpz_ptr*)res) = PopTaggedInteger();
3364 return ARG_SIZE(INTEGER_TAG);
3367 *((unsigned int*)res) = PopTaggedWord();
3368 return ARG_SIZE(WORD_TAG);
3370 *((int*)res) = PopTaggedChar();
3371 return ARG_SIZE(CHAR_TAG);
3373 *((float*)res) = PopTaggedFloat();
3374 return ARG_SIZE(FLOAT_TAG);
3376 *((double*)res) = PopTaggedDouble();
3377 return ARG_SIZE(DOUBLE_TAG);
3379 *((void**)res) = PopTaggedAddr();
3380 return ARG_SIZE(ADDR_TAG);
3382 *((StgStablePtr*)res) = PopTaggedStablePtr();
3383 return ARG_SIZE(STABLE_TAG);
3384 #ifdef PROVIDE_FOREIGN
3387 StgForeignObj *result = stgCast(StgForeignObj*,PopPtr());
3388 *((void**)res) = result->data;
3389 return sizeofW(StgPtr);
3395 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
3396 *((void**)res) = stgCast(void*,&(arr->payload));
3397 return sizeofW(StgPtr);
3400 barf("unmarshall: unrecognised result type %d\n",res_ty);
3404 nat argSize( const char* ks )
3407 for( ; *ks != '\0'; ++ks) {
3410 sz += sizeof(StgWord) * ARG_SIZE(INT_TAG);
3414 sz += sizeof(StgWord) * ARG_SIZE(INTEGER_TAG);
3418 sz += sizeof(StgWord) * ARG_SIZE(WORD_TAG);
3421 sz += sizeof(StgWord) * ARG_SIZE(CHAR_TAG);
3424 sz += sizeof(StgWord) * ARG_SIZE(FLOAT_TAG);
3427 sz += sizeof(StgWord) * ARG_SIZE(DOUBLE_TAG);
3430 sz += sizeof(StgWord) * ARG_SIZE(ADDR_TAG);
3433 sz += sizeof(StgWord) * ARG_SIZE(STABLE_TAG);
3435 #ifdef PROVIDE_FOREIGN
3440 sz += sizeof(StgPtr);
3443 barf("argSize: unrecognised result type %d\n",*ks);
3451 /* -----------------------------------------------------------------------------
3452 * encode/decode Float/Double code for standalone Hugs
3453 * Code based on the HBC code (lib/fltcode.c) and more recently GHC
3454 * (ghc/rts/StgPrimFloat.c)
3455 * ---------------------------------------------------------------------------*/
3457 #if IEEE_FLOATING_POINT
3458 #define MY_DMINEXP ((DBL_MIN_EXP) - (DBL_MANT_DIG) - 1)
3459 /* DMINEXP is defined in values.h on Linux (for example) */
3460 #define DHIGHBIT 0x00100000
3461 #define DMSBIT 0x80000000
3463 #define MY_FMINEXP ((FLT_MIN_EXP) - (FLT_MANT_DIG) - 1)
3464 #define FHIGHBIT 0x00800000
3465 #define FMSBIT 0x80000000
3467 #error The following code doesnt work in a non-IEEE FP environment
3470 #ifdef WORDS_BIGENDIAN
3479 StgDouble B__encodeDouble (B* s, I_ e) /* result = s * 2^e */
3484 /* Convert a B to a double; knows a lot about internal rep! */
3485 for(r = 0.0, i = s->used-1; i >= 0; i--)
3486 r = (r * B_BASE_FLT) + s->stuff[i];
3488 /* Now raise to the exponent */
3489 if ( r != 0.0 ) /* Lennart suggests this avoids a bug in MIPS's ldexp */
3492 /* handle the sign */
3493 if (s->sign < 0) r = -r;
3500 #if ! FLOATS_AS_DOUBLES
3501 StgFloat B__encodeFloat (B* s, I_ e) /* result = s * 2^e */
3506 /* Convert a B to a float; knows a lot about internal rep! */
3507 for(r = 0.0, i = s->used-1; i >= 0; i--)
3508 r = (r * B_BASE_FLT) + s->stuff[i];
3510 /* Now raise to the exponent */
3511 if ( r != 0.0 ) /* Lennart suggests this avoids a bug in MIPS's ldexp */
3514 /* handle the sign */
3515 if (s->sign < 0) r = -r;
3519 #endif /* FLOATS_AS_DOUBLES */
3523 /* This only supports IEEE floating point */
3524 void B__decodeDouble (B* man, I_* exp, StgDouble dbl)
3526 /* Do some bit fiddling on IEEE */
3527 nat low, high; /* assuming 32 bit ints */
3529 union { double d; int i[2]; } u; /* assuming 32 bit ints, 64 bit double */
3531 u.d = dbl; /* grab chunks of the double */
3535 ASSERT(B_BASE == 256);
3537 /* Assume that the supplied B is the right size */
3540 if (low == 0 && (high & ~DMSBIT) == 0) {
3541 man->sign = man->used = 0;
3546 iexp = ((high >> 20) & 0x7ff) + MY_DMINEXP;
3550 if (iexp != MY_DMINEXP) /* don't add hidden bit to denorms */
3554 /* A denorm, normalize the mantissa */
3555 while (! (high & DHIGHBIT)) {
3565 man->stuff[7] = (((W_)high) >> 24) & 0xff;
3566 man->stuff[6] = (((W_)high) >> 16) & 0xff;
3567 man->stuff[5] = (((W_)high) >> 8) & 0xff;
3568 man->stuff[4] = (((W_)high) ) & 0xff;
3570 man->stuff[3] = (((W_)low) >> 24) & 0xff;
3571 man->stuff[2] = (((W_)low) >> 16) & 0xff;
3572 man->stuff[1] = (((W_)low) >> 8) & 0xff;
3573 man->stuff[0] = (((W_)low) ) & 0xff;
3575 if (sign < 0) man->sign = -1;
3577 do_renormalise(man);
3581 #if ! FLOATS_AS_DOUBLES
3582 void B__decodeFloat (B* man, I_* exp, StgFloat flt)
3584 /* Do some bit fiddling on IEEE */
3585 int high, sign; /* assuming 32 bit ints */
3586 union { float f; int i; } u; /* assuming 32 bit float and int */
3588 u.f = flt; /* grab the float */
3591 ASSERT(B_BASE == 256);
3593 /* Assume that the supplied B is the right size */
3596 if ((high & ~FMSBIT) == 0) {
3597 man->sign = man->used = 0;
3602 *exp = ((high >> 23) & 0xff) + MY_FMINEXP;
3606 if (*exp != MY_FMINEXP) /* don't add hidden bit to denorms */
3610 /* A denorm, normalize the mantissa */
3611 while (! (high & FHIGHBIT)) {
3616 man->stuff[3] = (((W_)high) >> 24) & 0xff;
3617 man->stuff[2] = (((W_)high) >> 16) & 0xff;
3618 man->stuff[1] = (((W_)high) >> 8) & 0xff;
3619 man->stuff[0] = (((W_)high) ) & 0xff;
3621 if (sign < 0) man->sign = -1;
3623 do_renormalise(man);
3626 #endif /* FLOATS_AS_DOUBLES */
3627 #endif /* INTERPRETER */