2 /* -----------------------------------------------------------------------------
5 * Copyright (c) 1994-1998.
7 * $RCSfile: Evaluator.c,v $
9 * $Date: 1999/03/01 14:47:03 $
10 * ---------------------------------------------------------------------------*/
20 #include "SchedAPI.h" /* for createGenThread */
21 #include "Schedule.h" /* for context_switch */
23 #include "Bytecodes.h"
24 #include "Assembler.h" /* for CFun stuff */
25 #include "ForeignCall.h"
26 #include "StablePriv.h"
27 #include "PrimOps.h" /* for __{encode,decode}{Float,Double} */
28 #include "Evaluator.h"
32 #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 */
44 #ifdef PROVIDE_INTEGER
45 #include "gmp.h" /* These are for primops */
48 /* An incredibly useful abbreviation.
49 * Interestingly, there are some uses of END_TSO_QUEUE_closure that
50 * can't use it because they use the closure at type StgClosure* or
51 * even StgPtr*. I suspect they should be changed. -- ADR
53 #define EndTSOQueue stgCast(StgTSO*,(void*)&END_TSO_QUEUE_closure)
55 /* These macros are rather delicate - read a good ANSI C book carefully
59 #define mycat(x,y) x##y
60 #define mycat2(x,y) mycat(x,y)
61 #define mycat3(x,y,z) mycat2(x,mycat2(y,z))
63 /* --------------------------------------------------------------------------
64 * Hugs Hooks - a bit of a hack
65 * ------------------------------------------------------------------------*/
67 void setRtsFlags( int x );
68 void setRtsFlags( int x )
70 *(int*)(&(RtsFlags.DebugFlags)) = x;
73 /* --------------------------------------------------------------------------
76 * ToDo: figure out why these are being used and crush them!
77 * ------------------------------------------------------------------------*/
79 void OnExitHook (void)
82 void StackOverflowHook (unsigned long stack_size)
84 fprintf(stderr,"Stack Overflow\n");
87 void OutOfHeapHook (unsigned long request_size, unsigned long heap_size)
89 fprintf(stderr,"Out Of Heap\n");
92 void MallocFailHook (unsigned long request_size /* in bytes */, char *msg)
94 fprintf(stderr,"Malloc Fail\n");
97 void defaultsHook (void)
102 /* --------------------------------------------------------------------------
104 * ------------------------------------------------------------------------*/
106 #ifdef PROVIDE_INTEGER
107 static /*inline*/ mpz_ptr mpz_alloc ( void );
108 //static /*inline*/ void mpz_free ( mpz_ptr );
110 static /*inline*/ mpz_ptr mpz_alloc ( void )
112 mpz_ptr r = stgCast(mpz_ptr,stgMallocBytes( sizeof(mpz_t),"mpz_alloc"));
117 #if 0 /* apparently unused */
118 static /*inline*/ void mpz_free ( mpz_ptr a )
126 /* --------------------------------------------------------------------------
128 * ------------------------------------------------------------------------*/
130 /*static*/ /*inline*/ void PushTag ( StackTag t );
131 /*static*/ /*inline*/ void PushPtr ( StgPtr x );
132 /*static*/ /*inline*/ void PushCPtr ( StgClosure* x );
133 /*static*/ /*inline*/ void PushInt ( StgInt x );
134 /*static*/ /*inline*/ void PushWord ( StgWord x );
136 /*static*/ /*inline*/ void PushTag ( StackTag t ) { *(--Sp) = t; }
137 /*static*/ /*inline*/ void PushPtr ( StgPtr x ) { *(--stgCast(StgPtr*,Sp)) = x; }
138 /*static*/ /*inline*/ void PushCPtr ( StgClosure* x ) { *(--stgCast(StgClosure**,Sp)) = x; }
139 /*static*/ /*inline*/ void PushInt ( StgInt x ) { *(--stgCast(StgInt*,Sp)) = x; }
140 /*static*/ /*inline*/ void PushWord ( StgWord x ) { *(--stgCast(StgWord*,Sp)) = x; }
142 /*static*/ /*inline*/ void checkTag ( StackTag t1, StackTag t2 );
143 /*static*/ /*inline*/ void PopTag ( StackTag t );
144 /*static*/ /*inline*/ StgPtr PopPtr ( void );
145 /*static*/ /*inline*/ StgClosure* PopCPtr ( void );
146 /*static*/ /*inline*/ StgInt PopInt ( void );
147 /*static*/ /*inline*/ StgWord PopWord ( void );
149 /*static*/ /*inline*/ void checkTag ( StackTag t1, StackTag t2 ) { ASSERT(t1 == t2);}
150 /*static*/ /*inline*/ void PopTag ( StackTag t ) { checkTag(t,*(Sp++)); }
151 /*static*/ /*inline*/ StgPtr PopPtr ( void ) { return *stgCast(StgPtr*,Sp)++; }
152 /*static*/ /*inline*/ StgClosure* PopCPtr ( void ) { return *stgCast(StgClosure**,Sp)++; }
153 /*static*/ /*inline*/ StgInt PopInt ( void ) { return *stgCast(StgInt*,Sp)++; }
154 /*static*/ /*inline*/ StgWord PopWord ( void ) { return *stgCast(StgWord*,Sp)++; }
156 /*static*/ /*inline*/ StgPtr stackPtr ( StgStackOffset i );
157 /*static*/ /*inline*/ StgInt stackInt ( StgStackOffset i );
158 /*static*/ /*inline*/ StgWord stackWord ( StgStackOffset i );
160 /*static*/ /*inline*/ StgPtr stackPtr ( StgStackOffset i ) { return *stgCast(StgPtr*, Sp+i); }
161 /*static*/ /*inline*/ StgInt stackInt ( StgStackOffset i ) { return *stgCast(StgInt*, Sp+i); }
162 /*static*/ /*inline*/ StgWord stackWord ( StgStackOffset i ) { return *stgCast(StgWord*,Sp+i); }
164 /*static*/ /*inline*/ void setStackWord ( StgStackOffset i, StgWord w );
166 /*static*/ /*inline*/ void setStackWord ( StgStackOffset i, StgWord w ) { Sp[i] = w; }
168 /*static*/ /*inline*/ void PushTaggedRealWorld( void );
169 /*static*/ /*inline*/ void PushTaggedInt ( StgInt x );
171 /*static*/ /*inline*/ void PushTaggedInt64 ( StgInt64 x );
173 #ifdef PROVIDE_INTEGER
174 /*static*/ /*inline*/ void PushTaggedInteger ( mpz_ptr x );
177 /*static*/ /*inline*/ void PushTaggedWord ( StgWord x );
180 /*static*/ /*inline*/ void PushTaggedAddr ( StgAddr x );
182 /*static*/ /*inline*/ void PushTaggedChar ( StgChar x );
183 /*static*/ /*inline*/ void PushTaggedFloat ( StgFloat x );
184 /*static*/ /*inline*/ void PushTaggedDouble ( StgDouble x );
185 /*static*/ /*inline*/ void PushTaggedStablePtr ( StgStablePtr x );
186 /*static*/ /*inline*/ void PushTaggedBool ( int x );
188 /*static*/ /*inline*/ void PushTaggedRealWorld( void ) { PushTag(REALWORLD_TAG); }
189 /*static*/ /*inline*/ void PushTaggedInt ( StgInt x ) { Sp -= sizeofW(StgInt); *Sp = x; PushTag(INT_TAG); }
191 /*static*/ /*inline*/ void PushTaggedInt64 ( StgInt64 x ) { Sp -= sizeofW(StgInt64); ASSIGN_Int64(Sp,x); PushTag(INT64_TAG); }
193 #ifdef PROVIDE_INTEGER
194 /*static*/ /*inline*/ void PushTaggedInteger ( mpz_ptr x )
196 StgForeignObj *result;
199 result = stgCast(StgForeignObj*,allocate(sizeofW(StgForeignObj)));
200 SET_HDR(result,&FOREIGN_info,CCCS);
203 #if 0 /* For now we don't deallocate Integer's at all */
204 w = stgCast(StgWeak*,allocate(sizeofW(StgWeak)));
205 SET_HDR(w, &WEAK_info, CCCS);
206 w->key = stgCast(StgClosure*,result);
207 w->value = stgCast(StgClosure*,result); /* or any other closure you have handy */
208 w->finaliser = funPtrToIO(mpz_free);
209 w->link = weak_ptr_list;
211 IF_DEBUG(weak, fprintf(stderr,"New weak pointer watching Foreign MPZ at %p\n",w));
214 PushPtr(stgCast(StgPtr,result));
218 /*static*/ /*inline*/ void PushTaggedWord ( StgWord x ) { Sp -= sizeofW(StgWord); *Sp = x; PushTag(WORD_TAG); }
221 /*static*/ /*inline*/ void PushTaggedAddr ( StgAddr x ) { Sp -= sizeofW(StgAddr); *Sp = (W_)x; PushTag(ADDR_TAG); }
223 /*static*/ /*inline*/ void PushTaggedChar ( StgChar x )
224 { Sp -= sizeofW(StgChar); *Sp = stgCast(StgWord,x); PushTag(CHAR_TAG); }
226 /*static*/ /*inline*/ void PushTaggedFloat ( StgFloat x ) { Sp -= sizeofW(StgFloat); ASSIGN_FLT(Sp,x); PushTag(FLOAT_TAG); }
227 /*static*/ /*inline*/ void PushTaggedDouble ( StgDouble x ) { Sp -= sizeofW(StgDouble); ASSIGN_DBL(Sp,x); PushTag(DOUBLE_TAG); }
228 /*static*/ /*inline*/ void PushTaggedStablePtr ( StgStablePtr x ) { Sp -= sizeofW(StgStablePtr); *Sp = x; PushTag(STABLE_TAG); }
229 /*static*/ /*inline*/ void PushTaggedBool ( int x ) { PushTaggedInt(x); }
231 /*static*/ /*inline*/ void PopTaggedRealWorld ( void );
232 /*static*/ /*inline*/ StgInt PopTaggedInt ( void );
234 /*static*/ /*inline*/ StgInt64 PopTaggedInt64 ( void );
236 #ifdef PROVIDE_INTEGER
237 /*static*/ /*inline*/ mpz_ptr PopTaggedInteger ( void );
240 /*static*/ /*inline*/ StgWord PopTaggedWord ( void );
243 /*static*/ /*inline*/ StgAddr PopTaggedAddr ( void );
245 /*static*/ /*inline*/ StgChar PopTaggedChar ( void );
246 /*static*/ /*inline*/ StgFloat PopTaggedFloat ( void );
247 /*static*/ /*inline*/ StgDouble PopTaggedDouble ( void );
248 /*static*/ /*inline*/ StgStablePtr PopTaggedStablePtr ( void );
250 /*static*/ /*inline*/ void PopTaggedRealWorld ( void ) { PopTag(REALWORLD_TAG); }
251 /*static*/ /*inline*/ StgInt PopTaggedInt ( void ) { StgInt r; PopTag(INT_TAG); r = *stgCast(StgInt*, Sp); Sp += sizeofW(StgInt); return r;}
253 /*static*/ /*inline*/ StgInt64 PopTaggedInt64 ( void ) { StgInt64 r; PopTag(INT64_TAG); r = PK_Int64(Sp); Sp += sizeofW(StgInt64); return r;}
255 #ifdef PROVIDE_INTEGER
256 /*static*/ /*inline*/ mpz_ptr PopTaggedInteger ( void ) { StgForeignObj *r = *stgCast(StgForeignObj**,Sp); Sp += sizeofW(StgPtr); return stgCast(mpz_ptr,r->data);}
259 /*static*/ /*inline*/ StgWord PopTaggedWord ( void ) { StgWord r; PopTag(WORD_TAG); r = *stgCast(StgWord*, Sp); Sp += sizeofW(StgWord); return r;}
262 /*static*/ /*inline*/ StgAddr PopTaggedAddr ( void ) { StgAddr r; PopTag(ADDR_TAG); r = *stgCast(StgAddr*, Sp); Sp += sizeofW(StgAddr); return r;}
264 /*static*/ /*inline*/ StgChar PopTaggedChar ( void ) { StgChar r; PopTag(CHAR_TAG); r = stgCast(StgChar, *Sp); Sp += sizeofW(StgChar); return r;}
265 /*static*/ /*inline*/ StgFloat PopTaggedFloat ( void ) { StgFloat r; PopTag(FLOAT_TAG); r = PK_FLT(Sp); Sp += sizeofW(StgFloat); return r;}
266 /*static*/ /*inline*/ StgDouble PopTaggedDouble ( void ) { StgDouble r; PopTag(DOUBLE_TAG); r = PK_DBL(Sp); Sp += sizeofW(StgDouble); return r;}
267 /*static*/ /*inline*/ StgStablePtr PopTaggedStablePtr ( void ) { StgInt r; PopTag(STABLE_TAG); r = *stgCast(StgStablePtr*, Sp); Sp += sizeofW(StgStablePtr); return r;}
269 /*static*/ /*inline*/ StgInt taggedStackInt ( StgStackOffset i );
271 /*static*/ /*inline*/ StgInt64 taggedStackInt64 ( StgStackOffset i );
274 /*static*/ /*inline*/ StgWord taggedStackWord ( StgStackOffset i );
277 /*static*/ /*inline*/ StgAddr taggedStackAddr ( StgStackOffset i );
279 /*static*/ /*inline*/ StgChar taggedStackChar ( StgStackOffset i );
280 /*static*/ /*inline*/ StgFloat taggedStackFloat ( StgStackOffset i );
281 /*static*/ /*inline*/ StgDouble taggedStackDouble ( StgStackOffset i );
282 /*static*/ /*inline*/ StgStablePtr taggedStackStable ( StgStackOffset i );
284 /*static*/ /*inline*/ StgInt taggedStackInt ( StgStackOffset i ) { checkTag(INT_TAG,Sp[i]); return *stgCast(StgInt*, Sp+1+i); }
286 /*static*/ /*inline*/ StgInt64 taggedStackInt64 ( StgStackOffset i ) { checkTag(INT64_TAG,Sp[i]); return PK_Int64(Sp+1+i); }
289 /*static*/ /*inline*/ StgWord taggedStackWord ( StgStackOffset i ) { checkTag(WORD_TAG,Sp[i]); return *stgCast(StgWord*, Sp+1+i); }
292 /*static*/ /*inline*/ StgAddr taggedStackAddr ( StgStackOffset i ) { checkTag(ADDR_TAG,Sp[i]); return *stgCast(StgAddr*, Sp+1+i); }
295 /*static*/ /*inline*/ StgChar taggedStackChar ( StgStackOffset i ) { checkTag(CHAR_TAG,Sp[i]); return stgCast(StgChar, *(Sp+1+i)) ; }
298 /*static*/ /*inline*/ StgFloat taggedStackFloat ( StgStackOffset i ) { checkTag(FLOAT_TAG,Sp[i]); return PK_FLT(Sp+1+i); }
299 /*static*/ /*inline*/ StgDouble taggedStackDouble ( StgStackOffset i ) { checkTag(DOUBLE_TAG,Sp[i]); return PK_DBL(Sp+1+i); }
300 /*static*/ /*inline*/ StgStablePtr taggedStackStable ( StgStackOffset i ) { checkTag(STABLE_TAG,Sp[i]); return *stgCast(StgStablePtr*, Sp+1+i); }
303 /* --------------------------------------------------------------------------
306 * Should we allocate from a nursery or use the
307 * doYouWantToGC/allocate interface? We'd already implemented a
308 * nursery-style scheme when the doYouWantToGC/allocate interface
310 * One reason to prefer the doYouWantToGC/allocate interface is to
311 * support operations which allocate an unknown amount in the heap
312 * (array ops, gmp ops, etc)
313 * ------------------------------------------------------------------------*/
315 static /*inline*/ StgPtr grabHpUpd( nat size )
317 ASSERT( size >= MIN_UPD_SIZE + sizeofW(StgHeader) );
318 return allocate(size);
321 static /*inline*/ StgPtr grabHpNonUpd( nat size )
323 ASSERT( size >= MIN_NONUPD_SIZE + sizeofW(StgHeader) );
324 return allocate(size);
327 /* --------------------------------------------------------------------------
328 * Manipulate "update frame" list:
329 * o Update frames (based on stg_do_update and friends in Updates.hc)
330 * o Error handling/catching (based on catchzh_fast and friends in Prims.hc)
331 * o Seq frames (based on seq_frame_entry in Prims.hc)
333 * ------------------------------------------------------------------------*/
335 static /*inline*/ void PopUpdateFrame ( StgClosure* obj );
336 static /*inline*/ void PushCatchFrame ( StgClosure* catcher );
337 static /*inline*/ void PopCatchFrame ( void );
338 static /*inline*/ void PushSeqFrame ( void );
339 static /*inline*/ void PopSeqFrame ( void );
341 static /*inline*/ StgClosure* raiseAnError ( StgClosure* errObj );
343 static /*inline*/ void PopUpdateFrame( StgClosure* obj )
345 /* NB: doesn't assume that Sp == Su */
347 fprintf(stderr, "Updating ");
348 printPtr(stgCast(StgPtr,Su->updatee));
349 fprintf(stderr, " with ");
351 fprintf(stderr,"Sp = %p\tSu = %p\n\n", Sp, Su);
353 #ifndef LAZY_BLACKHOLING
354 ASSERT(get_itbl(Su->updatee)->type == BLACKHOLE
355 || get_itbl(Su->updatee)->type == CAF_BLACKHOLE
357 #endif /* LAZY_BLACKHOLING */
358 UPD_IND(Su->updatee,obj);
359 Sp = stgCast(StgStackPtr,Su) + sizeofW(StgUpdateFrame);
363 static /*inline*/ void PopStopFrame( StgClosure* obj )
365 /* Move Su just off the end of the stack, we're about to spam the
366 * STOP_FRAME with the return value.
368 Su = stgCast(StgUpdateFrame*,Sp+1);
369 *stgCast(StgClosure**,Sp) = obj;
372 static /*inline*/ void PushCatchFrame( StgClosure* handler )
375 /* ToDo: stack check! */
376 Sp -= sizeofW(StgCatchFrame);
377 fp = stgCast(StgCatchFrame*,Sp);
378 SET_HDR(fp,&catch_frame_info,CCCS);
379 fp->handler = handler;
381 Su = stgCast(StgUpdateFrame*,fp);
384 static /*inline*/ void PopCatchFrame( void )
386 /* NB: doesn't assume that Sp == Su */
387 /* fprintf(stderr,"Popping catch frame\n"); */
388 Sp = stgCast(StgStackPtr,Su) + sizeofW(StgCatchFrame);
389 Su = stgCast(StgCatchFrame*,Su)->link;
392 static /*inline*/ void PushSeqFrame( void )
395 /* ToDo: stack check! */
396 Sp -= sizeofW(StgSeqFrame);
397 fp = stgCast(StgSeqFrame*,Sp);
398 SET_HDR(fp,&seq_frame_info,CCCS);
400 Su = stgCast(StgUpdateFrame*,fp);
403 static /*inline*/ void PopSeqFrame( void )
405 /* NB: doesn't assume that Sp == Su */
406 Sp = stgCast(StgStackPtr,Su) + sizeofW(StgSeqFrame);
407 Su = stgCast(StgSeqFrame*,Su)->link;
410 static /*inline*/ StgClosure* raiseAnError( StgClosure* errObj )
412 StgClosure *raise_closure;
414 /* This closure represents the expression 'raise# E' where E
415 * is the exception raised. It is used to overwrite all the
416 * thunks which are currently under evaluataion.
418 raise_closure = (StgClosure *)allocate(sizeofW(StgClosure)+1);
419 raise_closure->header.info = &raise_info;
420 raise_closure->payload[0] = R1.cl;
423 switch (get_itbl(Su)->type) {
425 UPD_IND(Su->updatee,raise_closure);
426 Sp = stgCast(StgStackPtr,Su) + sizeofW(StgUpdateFrame);
432 case CATCH_FRAME: /* found it! */
434 StgCatchFrame* fp = stgCast(StgCatchFrame*,Su);
435 StgClosure *handler = fp->handler;
437 Sp += sizeofW(StgCatchFrame); /* Pop */
442 barf("raiseError: uncaught exception: STOP_FRAME");
444 barf("raiseError: weird activation record");
449 static StgClosure* raisePrim(char* msg)
451 /* ToDo: figure out some way to turn the msg into a Haskell Exception
452 * Hack: we don't know how to build an Exception but we do know how
453 * to build a (recursive!) error object.
454 * The result isn't pretty but it's (slightly) better than nothing.
456 nat size = sizeof(StgClosure) + 1;
457 StgClosure* errObj = stgCast(StgClosure*,grabHpNonUpd(size));
458 SET_INFO(errObj,&raise_info);
459 errObj->payload[0] = errObj;
460 fprintf(stderr, "\n\n\nRAISE PRIM %s\n", msg);
464 /* At the moment, I prefer to put it on stdout to make things as
465 * close to Hugs' old behaviour as possible.
467 fprintf(stdout, "Program error: %s", msg);
470 return raiseAnError(stgCast(StgClosure*,errObj));
473 #define raiseIndex(where) raisePrim("Array index out of range in " where)
474 #define raiseDiv0(where) raisePrim("Division by 0 in " where)
476 /* --------------------------------------------------------------------------
478 * ------------------------------------------------------------------------*/
482 unsigned char x = PopTaggedChar(); \
483 unsigned char y = PopTaggedChar(); \
489 unsigned char x = PopTaggedChar(); \
500 StgInt x = PopTaggedInt(); \
501 StgWord y = PopTaggedWord(); \
507 StgInt x = PopTaggedInt(); \
508 StgInt y = PopTaggedInt(); \
514 StgInt x = PopTaggedInt(); \
515 StgInt y = PopTaggedInt(); \
526 StgInt x = PopTaggedInt(); \
532 StgInt x = PopTaggedInt(); \
543 StgInt x = PopTaggedInt(); \
554 StgInt x = PopTaggedInt(); \
560 PushTaggedFloat(e); \
565 StgInt x = PopTaggedInt(); \
566 PushTaggedFloat(e); \
571 PushTaggedDouble(e); \
576 StgInt x = PopTaggedInt(); \
577 PushTaggedDouble(e); \
583 StgWord x = PopTaggedWord(); \
584 StgWord y = PopTaggedWord(); \
590 StgWord x = PopTaggedWord(); \
591 StgWord y = PopTaggedWord(); \
597 StgWord x = PopTaggedWord(); \
603 StgWord x = PopTaggedWord(); \
611 StgAddr x = PopTaggedAddr(); \
612 StgAddr y = PopTaggedAddr(); \
617 StgAddr x = PopTaggedAddr(); \
622 StgAddr x = PopTaggedAddr(); \
623 int y = PopTaggedInt(); \
630 StgAddr x = PopTaggedAddr(); \
631 int y = PopTaggedInt(); \
638 StgAddr x = PopTaggedAddr(); \
639 int y = PopTaggedInt(); \
642 PushTaggedInt64(r); \
646 StgAddr x = PopTaggedAddr(); \
647 int y = PopTaggedInt(); \
654 StgAddr x = PopTaggedAddr(); \
655 int y = PopTaggedInt(); \
658 PushTaggedFloat(r); \
662 StgAddr x = PopTaggedAddr(); \
663 int y = PopTaggedInt(); \
666 PushTaggedDouble(r); \
670 StgAddr x = PopTaggedAddr(); \
671 int y = PopTaggedInt(); \
674 PushTaggedStablePtr(r); \
678 StgAddr x = PopTaggedAddr(); \
679 int y = PopTaggedInt(); \
680 StgChar z = PopTaggedChar(); \
685 StgAddr x = PopTaggedAddr(); \
686 int y = PopTaggedInt(); \
687 StgInt z = PopTaggedInt(); \
692 StgAddr x = PopTaggedAddr(); \
693 int y = PopTaggedInt(); \
694 StgInt64 z = PopTaggedInt64(); \
699 StgAddr x = PopTaggedAddr(); \
700 int y = PopTaggedInt(); \
701 StgAddr z = PopTaggedAddr(); \
706 StgAddr x = PopTaggedAddr(); \
707 int y = PopTaggedInt(); \
708 StgFloat z = PopTaggedFloat(); \
713 StgAddr x = PopTaggedAddr(); \
714 int y = PopTaggedInt(); \
715 StgDouble z = PopTaggedDouble(); \
720 StgAddr x = PopTaggedAddr(); \
721 int y = PopTaggedInt(); \
722 StgStablePtr z = PopTaggedStablePtr(); \
726 #endif /* PROVIDE_ADDR */
730 StgFloat x = PopTaggedFloat(); \
731 StgFloat y = PopTaggedFloat(); \
737 StgFloat x = PopTaggedFloat(); \
738 StgFloat y = PopTaggedFloat(); \
739 PushTaggedFloat(e); \
744 StgFloat x = PopTaggedFloat(); \
745 PushTaggedFloat(e); \
750 StgFloat x = PopTaggedFloat(); \
756 StgFloat x = PopTaggedFloat(); \
762 StgFloat x = PopTaggedFloat(); \
763 PushTaggedDouble(e); \
768 StgDouble x = PopTaggedDouble(); \
769 StgDouble y = PopTaggedDouble(); \
775 StgDouble x = PopTaggedDouble(); \
776 StgDouble y = PopTaggedDouble(); \
777 PushTaggedDouble(e); \
782 StgDouble x = PopTaggedDouble(); \
788 StgDouble x = PopTaggedDouble(); \
789 PushTaggedDouble(e); \
794 StgDouble x = PopTaggedDouble(); \
800 StgDouble x = PopTaggedDouble(); \
801 PushTaggedFloat(e); \
807 StgInt64 x = PopTaggedInt64(); \
808 int y = PopTaggedInt(); \
809 PushTaggedFloat(e); \
813 StgInt64 x = PopTaggedInt64(); \
814 int y = PopTaggedInt(); \
815 PushTaggedDouble(e); \
819 StgInt64 x = PopTaggedInt64(); \
820 StgInt64 y = PopTaggedInt64(); \
825 StgInt64 x = PopTaggedInt64(); \
826 PushTaggedInt64(e); \
830 StgInt64 x = PopTaggedInt64(); \
831 StgInt64 y = PopTaggedInt64(); \
832 PushTaggedInt64(e); \
836 StgInt64 x = PopTaggedInt64(); \
837 StgWord y = PopTaggedWord(); \
838 PushTaggedInt64(e); \
840 #define OP_zz_zZ(e1,e2) \
842 StgInt64 x = PopTaggedInt64(); \
843 StgInt64 y = PopTaggedInt64(); \
844 PushTaggedInt64(e1); \
845 PushTaggedInt64(e2); \
849 StgInt64 x = PopTaggedInt64(); \
850 StgInt64 y = PopTaggedInt64(); \
855 PushTaggedInt64(e); \
859 StgInt64 x = PopTaggedInt64(); \
864 StgInt x = PopTaggedInt(); \
865 PushTaggedInt64(e); \
870 StgInt64 x = PopTaggedInt64(); \
875 StgWord x = PopTaggedWord(); \
876 PushTaggedInt64(e); \
881 StgInt64 x = PopTaggedInt64(); \
882 printf("%lld = %f\n",x,(float)(e)); \
883 PushTaggedFloat(e); \
887 StgFloat x = PopTaggedFloat(); \
888 PushTaggedInt64(e); \
892 StgInt64 x = PopTaggedInt64(); \
893 PushTaggedDouble(e); \
897 StgDouble x = PopTaggedDouble(); \
898 PushTaggedInt64(e); \
902 #ifdef PROVIDE_INTEGER
906 mpz_ptr x = PopTaggedInteger(); \
907 int y = PopTaggedInt(); \
908 PushTaggedFloat(e); \
912 StgFloat x = PopTaggedFloat(); \
913 mpz_ptr r1 = mpz_alloc(); \
917 PushTaggedInteger(r1); \
921 mpz_ptr x = PopTaggedInteger(); \
922 int y = PopTaggedInt(); \
923 PushTaggedDouble(e); \
927 StgDouble x = PopTaggedDouble(); \
928 mpz_ptr r1 = mpz_alloc(); \
932 PushTaggedInteger(r1); \
936 mpz_ptr x = PopTaggedInteger(); \
937 mpz_ptr r = mpz_alloc(); \
939 PushTaggedInteger(r); \
943 mpz_ptr x = PopTaggedInteger(); \
944 mpz_ptr y = PopTaggedInteger(); \
945 mpz_ptr r = mpz_alloc(); \
947 PushTaggedInteger(r); \
951 mpz_ptr x = PopTaggedInteger(); \
952 mpz_ptr y = PopTaggedInteger(); \
957 mpz_ptr x = PopTaggedInteger(); \
962 StgInt x = PopTaggedInt(); \
963 mpz_ptr r = mpz_alloc(); \
965 PushTaggedInteger(r); \
970 mpz_ptr x = PopTaggedInteger(); \
971 PushTaggedInt64(e); \
975 StgInt64 x = PopTaggedInt64(); \
976 mpz_ptr r = mpz_alloc(); \
978 PushTaggedInteger(r); \
984 mpz_ptr x = PopTaggedInteger(); \
989 StgWord x = PopTaggedWord(); \
990 mpz_ptr r = mpz_alloc(); \
992 PushTaggedInteger(r); \
997 mpz_ptr x = PopTaggedInteger(); \
998 PushTaggedFloat(e); \
1002 StgFloat x = PopTaggedFloat(); \
1003 mpz_ptr r = mpz_alloc(); \
1005 PushTaggedInteger(r); \
1009 mpz_ptr x = PopTaggedInteger(); \
1010 PushTaggedDouble(e); \
1014 StgDouble x = PopTaggedDouble(); \
1015 mpz_ptr r = mpz_alloc(); \
1017 PushTaggedInteger(r); \
1020 #endif /* ifdef PROVIDE_INTEGER */
1022 #ifdef PROVIDE_ARRAY
1023 #define HEADER_mI(ty,where) \
1024 StgArrWords* x = stgCast(StgArrWords*,PopPtr()); \
1025 nat i = PopTaggedInt(); \
1026 if (i * sizeof(ty) + (sizeof(ty)) > sizeof(StgWord) * x->words) { \
1027 obj = raiseIndex(where); \
1030 #define OP_mI_ty(ty,where,s) \
1032 HEADER_mI(mycat2(Stg,ty),where) \
1033 { mycat2(Stg,ty) r; \
1035 mycat2(PushTagged,ty)(r); \
1038 #define OP_mIty_(ty,where,s) \
1040 HEADER_mI(mycat2(Stg,ty),where) \
1042 mycat2(Stg,ty) z = mycat2(PopTagged,ty)(); \
1047 #endif /* PROVIDE_ARRAY */
1050 /* This is written as one giant function in the hope that gcc will do
1051 * a better job of register allocation.
1053 StgThreadReturnCode enter( StgClosure* obj )
1055 /* We use a char so that we'll do a context_switch check every 256
1058 char enterCount = 0;
1059 int enterCountI = 0;
1061 /* ASSERT(StorageMgrInfo.hp_start <= Hp && Hp < HpLim && HpLim == StorageMgrInfo.hplim); */
1062 ASSERT(SpLim <= Sp && Sp <= stgCast(StgPtr,Su));
1066 "\n---------------------------------------------------------------\n");
1067 fprintf(stderr,"(%d) Entering: ",enterCountI++); printObj(obj);
1068 fprintf(stderr,"Sp = %p\tSu = %p\n", Sp, Su);
1069 fprintf(stderr, "\n" );
1070 printStack(Sp,CurrentTSO->stack+CurrentTSO->stack_size,Su);
1071 fprintf(stderr, "\n\n");
1077 /*belch("Starting sanity check");
1079 *checkTSO(CurrentTSO, heap_step);
1080 * This check fails if we've done any updates because we
1081 * whack into holes in the heap.
1083 *belch("Ending sanity check");
1090 fprintf(stderr,"Continue?\n");
1094 if (++enterCount == 0 && context_switch) {
1095 PushCPtr(obj); /* code to restart with */
1096 return ThreadYielding;
1098 switch ( get_itbl(obj)->type ) {
1099 case INVALID_OBJECT:
1100 barf("Invalid object %p",obj);
1103 StgBCO* bco = stgCast(StgBCO*,obj);
1105 #if 1 /* We don't use an explicit HP_CHECK anymore */
1106 if (doYouWantToGC()) {
1107 PushCPtr(obj); /* code to restart with */
1108 return HeapOverflow;
1112 ASSERT(pc < bco->n_instrs);
1113 if (0 /*enterCountI > 2*/ ) {
1114 fprintf(stderr, "\n\n-----------------\n" );
1115 printStack(Sp,CurrentTSO->stack+CurrentTSO->stack_size,Su);
1116 fprintf(stderr, "\n");
1119 fprintf(stderr,"Sp = %p\tSu = %p\tpc = %d\t", Sp, Su, pc);
1121 /*fprintf(stderr,"\t"); printStackObj(Sp); */
1122 fprintf(stderr,"\n");
1124 switch (bcoInstr(bco,pc++)) {
1125 case i_INTERNAL_ERROR:
1126 barf("INTERNAL_ERROR at %p:%d",bco,pc-1);
1128 barf("PANIC at %p:%d",bco,pc-1);
1132 int n = bcoInstr(bco,pc++);
1133 /* ToDo: we could allocate the whole thing now and
1134 * slice it up ourselves
1136 if (doYouWantToGC()) {
1137 PushCPtr(obj); /* code to restart with */
1138 return HeapOverflow;
1145 int n = bcoInstr(bco,pc++);
1146 if (Sp - n < SpLim) {
1147 PushCPtr(obj); /* code to restart with */
1148 return StackOverflow;
1154 /* ToDo: make sure that hp check allows for possible PAP */
1155 nat n = bcoInstr(bco,pc++);
1156 if (stgCast(StgPtr,Sp + n) > stgCast(StgPtr,Su)) {
1157 StgWord words = (P_)Su - Sp;
1159 /* first build a PAP */
1160 ASSERT((P_)Su >= Sp); /* was (words >= 0) but that's always true */
1161 if (words == 0) { /* optimisation */
1162 /* Skip building the PAP and update with an indirection. */
1163 } else { /* Build the PAP. */
1164 /* In the evaluator, we avoid the need to do
1165 * a heap check here by including the size of
1166 * the PAP in the heap check we performed
1167 * when we entered the BCO.
1170 StgPAP* pap = stgCast(StgPAP*,grabHpNonUpd(PAP_sizeW(words)));
1171 SET_HDR(pap,&PAP_info,CC_pap);
1172 pap->n_args = words;
1174 for(i = 0; i < (I_)words; ++i) {
1175 payloadWord(pap,i) = Sp[i];
1178 obj = stgCast(StgClosure*,pap);
1181 /* now deal with "update frame" */
1182 /* as an optimisation, we process all on top of stack */
1183 /* instead of just the top one */
1186 switch (get_itbl(Su)->type) {
1189 ASSERT(Sp != (P_)Su);
1190 /* We hit a CATCH frame during an arg satisfaction
1191 * check. So now return to bco_info which is under
1192 * the CATCH frame. The following code is copied
1193 * from a case RET_BCO further down.
1194 * (The reason why we're here is that something of
1195 * functional type has been evaluated as a possibly
1196 * exception-throwing computation, but has not thrown
1197 * any exception, and is now returning to the
1198 * algebraic-case-continuation which forced the
1199 * evaluation in the first place.)
1213 PopUpdateFrame(obj);
1217 return ThreadFinished;
1220 ASSERT(Sp != (P_)Su);
1221 /* We hit a SEQ frame during an arg satisfaction check.
1222 * So now return to bco_info which is under the
1223 * SEQ frame. The following code is copied from a
1224 * case RET_BCO further down. (The reason why we're
1225 * here is that something of functional type has
1226 * been seq-d on, and we're now returning to the
1227 * algebraic-case-continuation which forced the
1228 * evaluation in the first place.)
1240 barf("Invalid update frame during argcheck");
1242 } while (Sp==(P_)Su);
1249 int words = bcoInstr(bco,pc++);
1250 PushPtr(grabHpUpd(AP_sizeW(words)));
1253 case i_ALLOC_CONSTR:
1255 StgInfoTable* info = bcoConstAddr(bco,bcoInstr(bco,pc++));
1256 StgClosure* c = stgCast(StgClosure*,grabHpNonUpd(sizeW_fromITBL(info)));
1258 PushPtr(stgCast(StgPtr,c));
1263 int x = bcoInstr(bco,pc++); /* ToDo: Word not Int! */
1264 int y = bcoInstr(bco,pc++);
1265 StgAP_UPD* o = stgCast(StgAP_UPD*,stackPtr(x));
1266 SET_HDR(o,&AP_UPD_info,??);
1268 o->fun = stgCast(StgClosure*,PopPtr());
1269 for(x=0; x < y; ++x) {
1270 payloadWord(o,x) = PopWord();
1273 fprintf(stderr,"\tBuilt ");
1274 printObj(stgCast(StgClosure*,o));
1280 int x = bcoInstr(bco,pc++);
1281 int y = bcoInstr(bco,pc++);
1282 StgPAP* o = stgCast(StgPAP*,stackPtr(x));
1283 SET_HDR(o,&PAP_info,??);
1285 o->fun = stgCast(StgClosure*,PopPtr());
1286 for(x=0; x < y; ++x) {
1287 payloadWord(o,x) = PopWord();
1290 fprintf(stderr,"\tBuilt ");
1291 printObj(stgCast(StgClosure*,o));
1297 int offset = bcoInstr(bco,pc++);
1298 StgClosure* o = stgCast(StgClosure*,stackPtr(offset));
1299 const StgInfoTable* info = get_itbl(o);
1300 nat p = info->layout.payload.ptrs;
1301 nat np = info->layout.payload.nptrs;
1303 for(i=0; i < p; ++i) {
1304 payloadCPtr(o,i) = PopCPtr();
1306 for(i=0; i < np; ++i) {
1307 payloadWord(o,p+i) = 0xdeadbeef;
1310 fprintf(stderr,"\tBuilt ");
1311 printObj(stgCast(StgClosure*,o));
1317 int x = bcoInstr(bco,pc++);
1318 int y = bcoInstr(bco,pc++);
1319 ASSERT(Sp+x+y <= stgCast(StgPtr,Su));
1320 /* a_1, .. a_x, b_1, .. b_y, s => a_1, .. a_x, s */
1322 setStackWord(x+y,stackWord(x));
1334 PushPtr(bcoConstPtr(bco,bcoInstr(bco,pc++)));
1335 PushPtr(stgCast(StgPtr,&ret_bco_info));
1340 int tag = bcoInstr(bco,pc++);
1341 StgWord offset = bcoInstr(bco,pc++);
1342 if (constrTag(stgCast(StgClosure*,stackPtr(0))) != tag) {
1349 StgClosure* o = stgCast(StgClosure*,stackPtr(0));
1350 const StgInfoTable* itbl = get_itbl(o);
1351 int i = itbl->layout.payload.ptrs;
1352 ASSERT( itbl->type == CONSTR
1353 || itbl->type == CONSTR_STATIC
1354 || itbl->type == CONSTR_NOCAF_STATIC
1357 PushCPtr(payloadCPtr(o,i));
1363 PushPtr(stackPtr(bcoInstr(bco,pc++)));
1368 PushPtr(stgCast(StgPtr,bcoConstPtr(bco,bcoInstr(bco,pc++))));
1373 StgWord o1 = bcoInstr(bco,pc++);
1374 StgWord o2 = bcoInstr(bco,pc++);
1375 StgWord o = o1*256 + o2;
1376 PushPtr(stgCast(StgPtr,bcoConstPtr(bco,o)));
1381 PushTaggedRealWorld();
1386 PushTaggedInt(taggedStackInt(bcoInstr(bco,pc++)));
1391 PushTaggedInt(bcoConstInt(bco,bcoInstr(bco,pc++)));
1401 StgClosure* o = stgCast(StgClosure*,grabHpNonUpd(Izh_sizeW));
1402 SET_HDR(o,&Izh_con_info,??);
1403 payloadWord(o,0) = PopTaggedInt();
1405 fprintf(stderr,"\tBuilt ");
1406 printObj(stgCast(StgClosure*,o));
1408 PushPtr(stgCast(StgPtr,o));
1413 StgClosure* con = stgCast(StgClosure*,stackPtr(0));
1414 /* ASSERT(isIntLike(con)); */
1415 PushTaggedInt(payloadWord(con,0));
1420 StgWord offset = bcoInstr(bco,pc++);
1421 StgInt x = PopTaggedInt();
1422 StgInt y = PopTaggedInt();
1428 #ifdef PROVIDE_INT64
1431 PushTaggedInt64(taggedStackInt64(bcoInstr(bco,pc++)));
1436 PushTaggedInt64(bcoConstInt64(bco,bcoInstr(bco,pc++)));
1439 case i_RETURN_INT64:
1441 ASSERT(0); /* ToDo(); */
1446 StgClosure* o = stgCast(StgClosure*,grabHpNonUpd(I64zh_sizeW));
1447 SET_HDR(o,&I64zh_con_info,??);
1448 ASSIGN_Int64(&payloadWord(o,0),PopTaggedInt64());
1450 fprintf(stderr,"\tBuilt ");
1451 printObj(stgCast(StgClosure*,o));
1453 PushPtr(stgCast(StgPtr,o));
1456 case i_UNPACK_INT64:
1458 StgClosure* con = stgCast(StgClosure*,stackPtr(0));
1459 /*ASSERT(isInt64Like(con)); */
1460 PushTaggedInt64(PK_Int64(&payloadWord(con,0)));
1464 #ifdef PROVIDE_INTEGER
1465 case i_CONST_INTEGER:
1467 char* s = bcoConstAddr(bco,bcoInstr(bco,pc++));
1468 mpz_ptr r = mpz_alloc();
1469 if (s[0] == '0' && s[1] == 'x') {
1470 mpz_set_str(r,s+2,16);
1472 mpz_set_str(r,s,10);
1474 PushTaggedInteger(r);
1482 PushTaggedWord(taggedStackWord(bcoInstr(bco,pc++)));
1487 PushTaggedWord(bcoConstWord(bco,bcoInstr(bco,pc++)));
1497 StgClosure* o = stgCast(StgClosure*,grabHpNonUpd(Wzh_sizeW));
1499 SET_HDR(o,&Wzh_con_info,??);
1500 payloadWord(o,0) = PopTaggedWord();
1502 fprintf(stderr,"\tBuilt ");
1503 printObj(stgCast(StgClosure*,o));
1505 PushPtr(stgCast(StgPtr,o));
1510 StgClosure* con = stgCast(StgClosure*,stackPtr(0));
1511 /* ASSERT(isWordLike(con)); */
1512 PushTaggedWord(payloadWord(con,0));
1519 PushTaggedAddr(taggedStackAddr(bcoInstr(bco,pc++)));
1524 PushTaggedAddr(bcoConstAddr(bco,bcoInstr(bco,pc++)));
1534 StgClosure* o = stgCast(StgClosure*,grabHpNonUpd(Azh_sizeW));
1535 SET_HDR(o,&Azh_con_info,??);
1536 payloadPtr(o,0) = PopTaggedAddr();
1538 fprintf(stderr,"\tBuilt ");
1539 printObj(stgCast(StgClosure*,o));
1541 PushPtr(stgCast(StgPtr,o));
1546 StgClosure* con = stgCast(StgClosure*,stackPtr(0));
1547 /* ASSERT(isAddrLike(con)); */
1548 PushTaggedAddr(payloadPtr(con,0));
1554 PushTaggedChar(taggedStackChar(bcoInstr(bco,pc++)));
1559 PushTaggedChar(bcoConstChar(bco,bcoInstr(bco,pc++)));
1569 StgClosure* o = stgCast(StgClosure*,grabHpNonUpd(Czh_sizeW));
1570 SET_HDR(o,&Czh_con_info,??);
1571 payloadWord(o,0) = PopTaggedChar();
1572 PushPtr(stgCast(StgPtr,o));
1574 fprintf(stderr,"\tBuilt ");
1575 printObj(stgCast(StgClosure*,o));
1581 StgClosure* con = stgCast(StgClosure*,stackPtr(0));
1582 /* ASSERT(isCharLike(con)); */
1583 PushTaggedChar(payloadWord(con,0));
1588 PushTaggedFloat(taggedStackFloat(bcoInstr(bco,pc++)));
1593 PushTaggedFloat(bcoConstFloat(bco,bcoInstr(bco,pc++)));
1596 case i_RETURN_FLOAT:
1603 StgClosure* o = stgCast(StgClosure*,grabHpNonUpd(Fzh_sizeW));
1604 SET_HDR(o,&Fzh_con_info,??);
1605 ASSIGN_FLT(&payloadWord(o,0),PopTaggedFloat());
1607 fprintf(stderr,"\tBuilt ");
1608 printObj(stgCast(StgClosure*,o));
1610 PushPtr(stgCast(StgPtr,o));
1613 case i_UNPACK_FLOAT:
1615 StgClosure* con = stgCast(StgClosure*,stackPtr(0));
1616 /* ASSERT(isFloatLike(con)); */
1617 PushTaggedFloat(PK_FLT(&payloadWord(con,0)));
1622 PushTaggedDouble(taggedStackDouble(bcoInstr(bco,pc++)));
1625 case i_CONST_DOUBLE:
1627 PushTaggedDouble(bcoConstDouble(bco,bcoInstr(bco,pc++)));
1630 case i_RETURN_DOUBLE:
1637 StgClosure* o = stgCast(StgClosure*,grabHpNonUpd(Dzh_sizeW));
1638 SET_HDR(o,&Dzh_con_info,??);
1639 ASSIGN_DBL(&payloadWord(o,0),PopTaggedDouble());
1641 fprintf(stderr,"\tBuilt ");
1642 printObj(stgCast(StgClosure*,o));
1644 PushPtr(stgCast(StgPtr,o));
1647 case i_UNPACK_DOUBLE:
1649 StgClosure* con = stgCast(StgClosure*,stackPtr(0));
1650 /* ASSERT(isDoubleLike(con)); */
1651 PushTaggedDouble(PK_DBL(&payloadWord(con,0)));
1654 #ifdef PROVIDE_STABLE
1657 PushTaggedStablePtr(taggedStackStable(bcoInstr(bco,pc++)));
1660 case i_RETURN_STABLE:
1667 StgClosure* o = stgCast(StgClosure*,grabHpNonUpd(Stablezh_sizeW));
1668 SET_HDR(o,&StablePtr_con_info,??);
1669 payloadWord(o,0) = PopTaggedStablePtr();
1671 fprintf(stderr,"\tBuilt ");
1672 printObj(stgCast(StgClosure*,o));
1674 PushPtr(stgCast(StgPtr,o));
1677 case i_UNPACK_STABLE:
1679 StgClosure* con = stgCast(StgClosure*,stackPtr(0));
1680 /* ASSERT(isStableLike(con)); */
1681 PushTaggedStablePtr(payloadWord(con,0));
1687 switch (bcoInstr(bco,pc++)) {
1688 case i_INTERNAL_ERROR1:
1689 barf("INTERNAL_ERROR1 at %p:%d",bco,pc-1);
1691 case i_pushseqframe:
1693 StgClosure* c = PopCPtr();
1698 case i_pushcatchframe:
1700 StgClosure* e = PopCPtr();
1701 StgClosure* h = PopCPtr();
1707 case i_gtChar: OP_CC_B(x>y); break;
1708 case i_geChar: OP_CC_B(x>=y); break;
1709 case i_eqChar: OP_CC_B(x==y); break;
1710 case i_neChar: OP_CC_B(x!=y); break;
1711 case i_ltChar: OP_CC_B(x<y); break;
1712 case i_leChar: OP_CC_B(x<=y); break;
1713 case i_charToInt: OP_C_I(x); break;
1714 case i_intToChar: OP_I_C(x); break;
1716 case i_gtInt: OP_II_B(x>y); break;
1717 case i_geInt: OP_II_B(x>=y); break;
1718 case i_eqInt: OP_II_B(x==y); break;
1719 case i_neInt: OP_II_B(x!=y); break;
1720 case i_ltInt: OP_II_B(x<y); break;
1721 case i_leInt: OP_II_B(x<=y); break;
1722 case i_minInt: OP__I(INT_MIN); break;
1723 case i_maxInt: OP__I(INT_MAX); break;
1724 case i_plusInt: OP_II_I(x+y); break;
1725 case i_minusInt: OP_II_I(x-y); break;
1726 case i_timesInt: OP_II_I(x*y); break;
1729 int x = PopTaggedInt();
1730 int y = PopTaggedInt();
1732 obj = raiseDiv0("quotInt");
1735 /* ToDo: protect against minInt / -1 errors
1736 * (repeat for all other division primops)
1743 int x = PopTaggedInt();
1744 int y = PopTaggedInt();
1746 obj = raiseDiv0("remInt");
1754 StgInt x = PopTaggedInt();
1755 StgInt y = PopTaggedInt();
1757 obj = raiseDiv0("quotRemInt");
1760 PushTaggedInt(x%y); /* last result */
1761 PushTaggedInt(x/y); /* first result */
1764 case i_negateInt: OP_I_I(-x); break;
1766 case i_andInt: OP_II_I(x&y); break;
1767 case i_orInt: OP_II_I(x|y); break;
1768 case i_xorInt: OP_II_I(x^y); break;
1769 case i_notInt: OP_I_I(~x); break;
1770 case i_shiftLInt: OP_II_I(x<<y); break;
1771 case i_shiftRAInt: OP_II_I(x>>y); break; /* ToDo */
1772 case i_shiftRLInt: OP_II_I(x>>y); break; /* ToDo */
1774 #ifdef PROVIDE_INT64
1775 case i_gtInt64: OP_zz_B(x>y); break;
1776 case i_geInt64: OP_zz_B(x>=y); break;
1777 case i_eqInt64: OP_zz_B(x==y); break;
1778 case i_neInt64: OP_zz_B(x!=y); break;
1779 case i_ltInt64: OP_zz_B(x<y); break;
1780 case i_leInt64: OP_zz_B(x<=y); break;
1781 case i_minInt64: OP__z(0x800000000000LL); break;
1782 case i_maxInt64: OP__z(0x7fffffffffffLL); break;
1783 case i_plusInt64: OP_zz_z(x+y); break;
1784 case i_minusInt64: OP_zz_z(x-y); break;
1785 case i_timesInt64: OP_zz_z(x*y); break;
1788 StgInt64 x = PopTaggedInt64();
1789 StgInt64 y = PopTaggedInt64();
1791 obj = raiseDiv0("quotInt64");
1794 /* ToDo: protect against minInt64 / -1 errors
1795 * (repeat for all other division primops)
1797 PushTaggedInt64(x/y);
1802 StgInt64 x = PopTaggedInt64();
1803 StgInt64 y = PopTaggedInt64();
1805 obj = raiseDiv0("remInt64");
1808 PushTaggedInt64(x%y);
1811 case i_quotRemInt64:
1813 StgInt64 x = PopTaggedInt64();
1814 StgInt64 y = PopTaggedInt64();
1816 obj = raiseDiv0("quotRemInt64");
1819 PushTaggedInt64(x%y); /* last result */
1820 PushTaggedInt64(x/y); /* first result */
1823 case i_negateInt64: OP_z_z(-x); break;
1825 case i_andInt64: OP_zz_z(x&y); break;
1826 case i_orInt64: OP_zz_z(x|y); break;
1827 case i_xorInt64: OP_zz_z(x^y); break;
1828 case i_notInt64: OP_z_z(~x); break;
1829 case i_shiftLInt64: OP_zW_z(x<<y); break;
1830 case i_shiftRAInt64: OP_zW_z(x>>y); break; /* ToDo */
1831 case i_shiftRLInt64: OP_zW_z(x>>y); break; /* ToDo */
1833 case i_int64ToInt: OP_z_I(x); break;
1834 case i_intToInt64: OP_I_z(x); break;
1836 case i_int64ToWord: OP_z_W(x); break;
1837 case i_wordToInt64: OP_W_z(x); break;
1839 case i_int64ToFloat: OP_z_F(x); break;
1840 case i_floatToInt64: OP_F_z(x); break;
1841 case i_int64ToDouble: OP_z_D(x); break;
1842 case i_doubleToInt64: OP_D_z(x); break;
1845 case i_gtWord: OP_WW_B(x>y); break;
1846 case i_geWord: OP_WW_B(x>=y); break;
1847 case i_eqWord: OP_WW_B(x==y); break;
1848 case i_neWord: OP_WW_B(x!=y); break;
1849 case i_ltWord: OP_WW_B(x<y); break;
1850 case i_leWord: OP_WW_B(x<=y); break;
1851 case i_minWord: OP__W(0); break;
1852 case i_maxWord: OP__W(UINT_MAX); break;
1853 case i_plusWord: OP_WW_W(x+y); break;
1854 case i_minusWord: OP_WW_W(x-y); break;
1855 case i_timesWord: OP_WW_W(x*y); break;
1858 StgWord x = PopTaggedWord();
1859 StgWord y = PopTaggedWord();
1861 obj = raiseDiv0("quotWord");
1864 PushTaggedWord(x/y);
1869 StgWord x = PopTaggedWord();
1870 StgWord y = PopTaggedWord();
1872 obj = raiseDiv0("remWord");
1875 PushTaggedWord(x%y);
1880 StgWord x = PopTaggedWord();
1881 StgWord y = PopTaggedWord();
1883 obj = raiseDiv0("quotRemWord");
1886 PushTaggedWord(x%y); /* last result */
1887 PushTaggedWord(x/y); /* first result */
1890 case i_negateWord: OP_W_W(-x); break;
1891 case i_andWord: OP_WW_W(x&y); break;
1892 case i_orWord: OP_WW_W(x|y); break;
1893 case i_xorWord: OP_WW_W(x^y); break;
1894 case i_notWord: OP_W_W(~x); break;
1895 case i_shiftLWord: OP_WW_W(x<<y); break;
1896 case i_shiftRAWord: OP_WW_W(x>>y); break; /* ToDo */
1897 case i_shiftRLWord: OP_WW_W(x>>y); break; /* ToDo */
1898 case i_intToWord: OP_I_W(x); break;
1899 case i_wordToInt: OP_W_I(x); break;
1902 case i_gtAddr: OP_AA_B(x>y); break;
1903 case i_geAddr: OP_AA_B(x>=y); break;
1904 case i_eqAddr: OP_AA_B(x==y); break;
1905 case i_neAddr: OP_AA_B(x!=y); break;
1906 case i_ltAddr: OP_AA_B(x<y); break;
1907 case i_leAddr: OP_AA_B(x<=y); break;
1908 case i_intToAddr: OP_I_A((StgAddr)x); break; /* ToDo */
1909 case i_addrToInt: OP_A_I((StgInt)x); break; /* ToDo */
1911 case i_indexCharOffAddr: OP_AI_C(indexCharOffAddrzh(r,x,y)); break;
1912 case i_readCharOffAddr: OP_AI_C(indexCharOffAddrzh(r,x,y)); break;
1913 case i_writeCharOffAddr: OP_AIC_(writeCharOffAddrzh(x,y,z)); break;
1915 case i_indexIntOffAddr: OP_AI_I(indexIntOffAddrzh(r,x,y)); break;
1916 case i_readIntOffAddr: OP_AI_I(indexIntOffAddrzh(r,x,y)); break;
1917 case i_writeIntOffAddr: OP_AII_(writeIntOffAddrzh(x,y,z)); break;
1918 #ifdef PROVIDE_INT64
1919 case i_indexInt64OffAddr: OP_AI_z(indexInt64OffAddrzh(r,x,y)); break;
1920 case i_readInt64OffAddr: OP_AI_z(indexInt64OffAddrzh(r,x,y)); break;
1921 case i_writeInt64OffAddr: OP_AIz_(writeInt64OffAddrzh(x,y,z)); break;
1924 case i_indexAddrOffAddr: OP_AI_A(indexAddrOffAddrzh(r,x,y)); break;
1925 case i_readAddrOffAddr: OP_AI_A(indexAddrOffAddrzh(r,x,y)); break;
1926 case i_writeAddrOffAddr: OP_AIA_(writeAddrOffAddrzh(x,y,z)); break;
1928 case i_indexFloatOffAddr: OP_AI_F(indexFloatOffAddrzh(r,x,y)); break;
1929 case i_readFloatOffAddr: OP_AI_F(indexFloatOffAddrzh(r,x,y)); break;
1930 case i_writeFloatOffAddr: OP_AIF_(writeFloatOffAddrzh(x,y,z)); break;
1932 case i_indexDoubleOffAddr: OP_AI_D(indexDoubleOffAddrzh(r,x,y)); break;
1933 case i_readDoubleOffAddr: OP_AI_D(indexDoubleOffAddrzh(r,x,y)); break;
1934 case i_writeDoubleOffAddr: OP_AID_(writeDoubleOffAddrzh(x,y,z)); break;
1936 #ifdef PROVIDE_STABLE
1937 case i_indexStableOffAddr: OP_AI_s(indexStablePtrOffAddrzh(r,x,y)); break;
1938 case i_readStableOffAddr: OP_AI_s(indexStablePtrOffAddrzh(r,x,y)); break;
1939 case i_writeStableOffAddr: OP_AIs_(writeStablePtrOffAddrzh(x,y,z)); break;
1942 #endif /* PROVIDE_ADDR */
1944 #ifdef PROVIDE_INTEGER
1945 case i_compareInteger:
1947 mpz_ptr x = PopTaggedInteger();
1948 mpz_ptr y = PopTaggedInteger();
1949 StgInt r = mpz_cmp(x,y);
1950 PushTaggedInt(r<0 ? -1 : (r>0 ? 1 : 0));
1953 case i_negateInteger: OP_Z_Z(mpz_neg(r,x)); break;
1954 case i_plusInteger: OP_ZZ_Z(mpz_add(r,x,y)); break;
1955 case i_minusInteger: OP_ZZ_Z(mpz_sub(r,x,y)); break;
1956 case i_timesInteger: OP_ZZ_Z(mpz_mul(r,x,y)); break;
1957 case i_quotRemInteger:
1959 mpz_ptr x = PopTaggedInteger();
1960 mpz_ptr y = PopTaggedInteger();
1961 mpz_ptr q = mpz_alloc();
1962 mpz_ptr r = mpz_alloc();
1963 if (mpz_sgn(y) == 0) {
1964 obj = raiseDiv0("quotRemInteger");
1967 mpz_tdiv_qr(q,r,x,y);
1968 PushTaggedInteger(r); /* last result */
1969 PushTaggedInteger(q); /* first result */
1972 case i_divModInteger:
1974 mpz_ptr x = PopTaggedInteger();
1975 mpz_ptr y = PopTaggedInteger();
1976 mpz_ptr q = mpz_alloc();
1977 mpz_ptr r = mpz_alloc();
1978 if (mpz_sgn(y) == 0) {
1979 obj = raiseDiv0("divModInteger");
1982 mpz_fdiv_qr(q,r,x,y);
1983 PushTaggedInteger(r); /* last result */
1984 PushTaggedInteger(q); /* first result */
1987 case i_integerToInt: OP_Z_I(mpz_get_si(x)); break;
1988 case i_intToInteger: OP_I_Z(mpz_set_si(r,x)); break;
1989 #ifdef PROVIDE_INT64
1990 case i_integerToInt64: OP_Z_z(mpz_get_si(x)); break;
1991 case i_int64ToInteger: OP_z_Z(mpz_set_si(r,x)); break;
1994 /* NB Use of mpz_get_si is quite deliberate since otherwise
1995 * -255 is converted to 255.
1997 case i_integerToWord: OP_Z_W(mpz_get_si(x)); break;
1998 case i_wordToInteger: OP_W_Z(mpz_set_ui(r,x)); break;
2000 case i_integerToFloat: OP_Z_F(mpz_get_d(x)); break;
2001 case i_floatToInteger: OP_F_Z(mpz_set_d(r,x)); break;
2002 case i_integerToDouble: OP_Z_D(mpz_get_d(x)); break;
2003 case i_doubleToInteger: OP_D_Z(mpz_set_d(r,x)); break;
2004 #endif /* PROVIDE_INTEGER */
2006 case i_gtFloat: OP_FF_B(x>y); break;
2007 case i_geFloat: OP_FF_B(x>=y); break;
2008 case i_eqFloat: OP_FF_B(x==y); break;
2009 case i_neFloat: OP_FF_B(x!=y); break;
2010 case i_ltFloat: OP_FF_B(x<y); break;
2011 case i_leFloat: OP_FF_B(x<=y); break;
2012 case i_minFloat: OP__F(FLT_MIN); break;
2013 case i_maxFloat: OP__F(FLT_MAX); break;
2014 case i_radixFloat: OP__I(FLT_RADIX); break;
2015 case i_digitsFloat: OP__I(FLT_MANT_DIG); break;
2016 case i_minExpFloat: OP__I(FLT_MIN_EXP); break;
2017 case i_maxExpFloat: OP__I(FLT_MAX_EXP); break;
2018 case i_plusFloat: OP_FF_F(x+y); break;
2019 case i_minusFloat: OP_FF_F(x-y); break;
2020 case i_timesFloat: OP_FF_F(x*y); break;
2023 StgFloat x = PopTaggedFloat();
2024 StgFloat y = PopTaggedFloat();
2027 obj = raiseDiv0("divideFloat");
2031 PushTaggedFloat(x/y);
2034 case i_negateFloat: OP_F_F(-x); break;
2035 case i_floatToInt: OP_F_I(x); break;
2036 case i_intToFloat: OP_I_F(x); break;
2037 case i_expFloat: OP_F_F(exp(x)); break;
2038 case i_logFloat: OP_F_F(log(x)); break;
2039 case i_sqrtFloat: OP_F_F(sqrt(x)); break;
2040 case i_sinFloat: OP_F_F(sin(x)); break;
2041 case i_cosFloat: OP_F_F(cos(x)); break;
2042 case i_tanFloat: OP_F_F(tan(x)); break;
2043 case i_asinFloat: OP_F_F(asin(x)); break;
2044 case i_acosFloat: OP_F_F(acos(x)); break;
2045 case i_atanFloat: OP_F_F(atan(x)); break;
2046 case i_sinhFloat: OP_F_F(sinh(x)); break;
2047 case i_coshFloat: OP_F_F(cosh(x)); break;
2048 case i_tanhFloat: OP_F_F(tanh(x)); break;
2049 case i_powerFloat: OP_FF_F(pow(x,y)); break;
2051 #ifdef PROVIDE_INT64
2052 /* Based on old Hugs code */
2053 /* ToDo: use ~/fptools/ghc/runtime/prims/PrimArith.lc */
2054 case i_encodeFloatz: OP_zI_F(ldexp(x,y)); break;
2055 case i_decodeFloatz:
2057 /* ToDo: this code is known to give very approximate results
2058 * (even when StgInt64 overflow doesn't occur)
2060 double f0 = PopTaggedFloat();
2062 double f1 = frexp((double)(f0),&n); /* 0.5 <= f1 < 1 */
2063 double f2 = ldexp(f1,FLT_MANT_DIG); /* 2^m-1 <= f2 < 2^m, m=FLT_MANT_DIG */
2064 PushTaggedInt(n-FLT_MANT_DIG);
2065 PushTaggedInt64((StgInt64)f2);
2066 #if 1 /* paranoia */
2067 if (ldexp((StgInt64)f2,n-FLT_MANT_DIG) != f0) {
2068 fprintf(stderr,"*** primDecodeFloat mismatch: %.10f != %.10f\n",
2069 ldexp((StgInt64)f2,n-FLT_MANT_DIG),f0);
2074 #endif /* PROVIDE_INT64 */
2075 #ifdef PROVIDE_INTEGER
2076 case i_encodeFloatZ: OP_ZI_F(__encodeFloat(x,y)); break;
2077 case i_decodeFloatZ: OP_F_ZI(__decodeFloat(r1,&r2,x)); break;
2079 case i_isNaNFloat: OP_F_B(isFloatNaN(x)); break;
2080 case i_isInfiniteFloat: OP_F_B(isFloatInfinite(x)); break;
2081 case i_isNegativeZeroFloat: OP_F_B(isFloatNegativeZero(x)); break;
2082 case i_isDenormalizedFloat: OP_F_B(isFloatDenormalized(x)); break;
2083 case i_gtDouble: OP_DD_B(x>y); break;
2084 case i_geDouble: OP_DD_B(x>=y); break;
2085 case i_eqDouble: OP_DD_B(x==y); break;
2086 case i_neDouble: OP_DD_B(x!=y); break;
2087 case i_ltDouble: OP_DD_B(x<y); break;
2088 case i_leDouble: OP_DD_B(x<=y) break;
2089 case i_minDouble: OP__D(DBL_MIN); break;
2090 case i_maxDouble: OP__D(DBL_MAX); break;
2091 case i_radixDouble: OP__I(FLT_RADIX); break;
2092 case i_digitsDouble: OP__I(DBL_MANT_DIG); break;
2093 case i_minExpDouble: OP__I(DBL_MIN_EXP); break;
2094 case i_maxExpDouble: OP__I(DBL_MAX_EXP); break;
2095 case i_plusDouble: OP_DD_D(x+y); break;
2096 case i_minusDouble: OP_DD_D(x-y); break;
2097 case i_timesDouble: OP_DD_D(x*y); break;
2098 case i_divideDouble:
2100 StgDouble x = PopTaggedDouble();
2101 StgDouble y = PopTaggedDouble();
2104 obj = raiseDiv0("divideDouble");
2108 PushTaggedDouble(x/y);
2111 case i_negateDouble: OP_D_D(-x); break;
2112 case i_doubleToInt: OP_D_I(x); break;
2113 case i_intToDouble: OP_I_D(x); break;
2114 case i_doubleToFloat: OP_D_F(x); break;
2115 case i_floatToDouble: OP_F_F(x); break;
2116 case i_expDouble: OP_D_D(exp(x)); break;
2117 case i_logDouble: OP_D_D(log(x)); break;
2118 case i_sqrtDouble: OP_D_D(sqrt(x)); break;
2119 case i_sinDouble: OP_D_D(sin(x)); break;
2120 case i_cosDouble: OP_D_D(cos(x)); break;
2121 case i_tanDouble: OP_D_D(tan(x)); break;
2122 case i_asinDouble: OP_D_D(asin(x)); break;
2123 case i_acosDouble: OP_D_D(acos(x)); break;
2124 case i_atanDouble: OP_D_D(atan(x)); break;
2125 case i_sinhDouble: OP_D_D(sinh(x)); break;
2126 case i_coshDouble: OP_D_D(cosh(x)); break;
2127 case i_tanhDouble: OP_D_D(tanh(x)); break;
2128 case i_powerDouble: OP_DD_D(pow(x,y)); break;
2129 #ifdef PROVIDE_INT64
2130 case i_encodeDoublez: OP_zI_D(ldexp(x,y)); break;
2131 case i_decodeDoublez:
2133 /* ToDo: this code is known to give very approximate results
2134 * (even when StgInt64 overflow doesn't occur)
2136 double f0 = PopTaggedDouble();
2138 double f1 = frexp((double)(f0),&n); /* 0.5 <= f1 < 1 */
2139 double f2 = ldexp(f1,FLT_MANT_DIG); /* 2^m-1 <= f2 < 2^m, m=FLT_MANT_DIG */
2140 PushTaggedInt(n-FLT_MANT_DIG);
2141 PushTaggedInt64((StgInt64)f2);
2142 #if 1 /* paranoia */
2143 if (ldexp((StgInt64)f2,n-FLT_MANT_DIG) != f0) {
2144 fprintf(stderr,"*** primDecodeDouble mismatch: %.10f != %.10f\n",
2145 ldexp((StgInt64)f2,n-FLT_MANT_DIG),f0);
2150 #endif /* PROVIDE_INT64 */
2151 #ifdef PROVIDE_INTEGER
2152 case i_encodeDoubleZ: OP_ZI_D(__encodeDouble(x,y)); break;
2153 case i_decodeDoubleZ: OP_D_ZI(__decodeDouble(r1,&r2,x)); break;
2154 #endif /* PROVIDE_INTEGER */
2155 case i_isNaNDouble: OP_D_B(isDoubleNaN(x)); break;
2156 case i_isInfiniteDouble: OP_D_B(isDoubleInfinite(x)); break;
2157 case i_isNegativeZeroDouble: OP_D_B(isDoubleNegativeZero(x)); break;
2158 case i_isDenormalizedDouble: OP_D_B(isDoubleDenormalized(x)); break;
2159 case i_isIEEEDouble:
2161 PushTaggedBool(rtsTrue);
2165 barf("Unrecognised primop1");
2171 switch (bcoInstr(bco,pc++)) {
2172 case i_INTERNAL_ERROR2:
2173 barf("INTERNAL_ERROR2 at %p:%d",bco,pc-1);
2175 case i_raise: /* raise#{err} */
2177 StgClosure* err = PopCPtr();
2178 obj = raiseAnError(err);
2181 #ifdef PROVIDE_ARRAY
2184 StgClosure* init = PopCPtr();
2186 = stgCast(StgMutVar*,allocate(sizeofW(StgMutVar)));
2187 SET_HDR(mv,&MUT_VAR_info,CCCS);
2189 PushPtr(stgCast(StgPtr,mv));
2194 StgMutVar* mv = stgCast(StgMutVar*,PopPtr());
2200 StgMutVar* mv = stgCast(StgMutVar*,PopPtr());
2201 StgClosure* value = PopCPtr();
2207 nat n = PopTaggedInt(); /* or Word?? */
2208 StgClosure* init = PopCPtr();
2209 StgWord size = sizeofW(StgMutArrPtrs) + n;
2212 = stgCast(StgMutArrPtrs*,allocate(size));
2213 SET_HDR(arr,&MUT_ARR_PTRS_info,CCCS);
2215 for (i = 0; i < n; ++i) {
2216 arr->payload[i] = init;
2218 PushPtr(stgCast(StgPtr,arr));
2224 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
2225 nat i = PopTaggedInt(); /* or Word?? */
2226 StgWord n = arr->ptrs;
2228 obj = raiseIndex("{index,read}Array");
2231 PushCPtr(arr->payload[i]);
2236 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
2237 nat i = PopTaggedInt(); /* or Word? */
2238 StgClosure* v = PopCPtr();
2239 StgWord n = arr->ptrs;
2241 obj = raiseIndex("{index,read}Array");
2244 arr->payload[i] = v;
2248 case i_sizeMutableArray:
2250 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
2251 PushTaggedInt(arr->ptrs);
2254 case i_unsafeFreezeArray:
2256 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
2257 SET_INFO(arr,&MUT_ARR_PTRS_FROZEN_info);
2258 PushPtr(stgCast(StgPtr,arr));
2261 case i_unsafeFreezeByteArray:
2263 /* Delightfully simple :-) */
2267 case i_sameMutableArray:
2268 case i_sameMutableByteArray:
2270 StgPtr x = PopPtr();
2271 StgPtr y = PopPtr();
2272 PushTaggedBool(x==y);
2276 case i_newByteArray:
2278 nat n = PopTaggedInt(); /* or Word?? */
2279 StgInt words = (n+sizeof(W_)-1)/sizeof(W_);
2280 StgWord size = sizeofW(StgArrWords) + words;
2282 StgArrWords* arr = stgCast(StgArrWords*,allocate(size));
2283 SET_HDR(arr,&ARR_WORDS_info,CCCS);
2286 for (i = 0; i < n; ++i) {
2287 arr->payload[i] = 0xdeadbeef;
2290 PushPtr(stgCast(StgPtr,arr));
2294 /* Most of these generate alignment warnings on Sparcs and similar architectures.
2295 * These are harmless and are caused by the cast to C* in BYTE_ARR_CTS.
2297 case i_indexCharArray: OP_mI_ty(Char,"indexCharArray", indexCharArrayzh(r,x,i)); break;
2298 case i_readCharArray: OP_mI_ty(Char,"readCharArray", readCharArrayzh(r,x,i)); break;
2299 case i_writeCharArray: OP_mIty_(Char,"writeCharArray", writeCharArrayzh(x,i,z)); break;
2301 case i_indexIntArray: OP_mI_ty(Int,"indexIntArray", indexIntArrayzh(r,x,i)); break;
2302 case i_readIntArray: OP_mI_ty(Int,"readIntArray", readIntArrayzh(r,x,i)); break;
2303 case i_writeIntArray: OP_mIty_(Int,"writeIntArray", writeIntArrayzh(x,i,z)); break;
2304 #ifdef PROVIDE_INT64
2305 case i_indexInt64Array: OP_mI_ty(Int64,"indexInt64Array", indexInt64Arrayzh(r,x,i)); break;
2306 case i_readInt64Array: OP_mI_ty(Int64,"readInt64Array", readInt64Arrayzh(r,x,i)); break;
2307 case i_writeInt64Array: OP_mIty_(Int64,"writeInt64Array", writeInt64Arrayzh(x,i,z)); break;
2310 case i_indexAddrArray: OP_mI_ty(Addr,"indexAddrArray", indexAddrArrayzh(r,x,i)); break;
2311 case i_readAddrArray: OP_mI_ty(Addr,"readAddrArray", readAddrArrayzh(r,x,i)); break;
2312 case i_writeAddrArray: OP_mIty_(Addr,"writeAddrArray", writeAddrArrayzh(x,i,z)); break;
2314 case i_indexFloatArray: OP_mI_ty(Float,"indexFloatArray", indexFloatArrayzh(r,x,i)); break;
2315 case i_readFloatArray: OP_mI_ty(Float,"readFloatArray", readFloatArrayzh(r,x,i)); break;
2316 case i_writeFloatArray: OP_mIty_(Float,"writeFloatArray", writeFloatArrayzh(x,i,z)); break;
2318 case i_indexDoubleArray: OP_mI_ty(Double,"indexDoubleArray", indexDoubleArrayzh(r,x,i)); break;
2319 case i_readDoubleArray: OP_mI_ty(Double,"readDoubleArray", readDoubleArrayzh(r,x,i)); break;
2320 case i_writeDoubleArray: OP_mIty_(Double,"writeDoubleArray", writeDoubleArrayzh(x,i,z)); break;
2322 #ifdef PROVIDE_STABLE
2323 case i_indexStableArray: OP_mI_ty(StablePtr,"indexStableArray", indexStablePtrArrayzh(r,x,i)); break;
2324 case i_readStableArray: OP_mI_ty(StablePtr,"readStableArray", readStablePtrArrayzh(r,x,i)); break;
2325 case i_writeStableArray: OP_mIty_(StablePtr,"writeStableArray", writeStablePtrArrayzh(x,i,z)); break;
2328 #endif /* PROVIDE_ARRAY */
2329 #ifdef PROVIDE_COERCE
2330 case i_unsafeCoerce:
2332 /* Another nullop */
2336 #ifdef PROVIDE_PTREQUALITY
2337 case i_reallyUnsafePtrEquality:
2338 { /* identical to i_sameRef */
2339 StgPtr x = PopPtr();
2340 StgPtr y = PopPtr();
2341 PushTaggedBool(x==y);
2345 #ifdef PROVIDE_FOREIGN
2346 /* ForeignObj# operations */
2347 case i_makeForeignObj:
2349 StgForeignObj *result
2350 = stgCast(StgForeignObj*,allocate(sizeofW(StgForeignObj)));
2351 SET_HDR(result,&FOREIGN_info,CCCS);
2352 result -> data = PopTaggedAddr();
2353 PushPtr(stgCast(StgPtr,result));
2356 #endif /* PROVIDE_FOREIGN */
2361 = stgCast(StgWeak*,allocate(sizeofW(StgWeak)));
2362 SET_HDR(w, &WEAK_info, CCCS);
2364 w->value = PopCPtr();
2365 w->finaliser = PopCPtr();
2366 w->link = weak_ptr_list;
2368 IF_DEBUG(weak, fprintf(stderr,"New weak pointer at %p\n",w));
2369 PushPtr(stgCast(StgPtr,w));
2374 StgWeak *w = stgCast(StgWeak*,PopPtr());
2375 if (w->header.info == &WEAK_info) {
2376 PushCPtr(w->value); /* last result */
2377 PushTaggedInt(1); /* first result */
2379 PushPtr(stgCast(StgPtr,w)); /* ToDo: error thunk would be better */
2384 #endif /* PROVIDE_WEAK */
2385 #ifdef PROVIDE_STABLE
2386 /* StablePtr# operations */
2387 case i_makeStablePtr:
2388 case i_deRefStablePtr:
2389 case i_freeStablePtr:
2390 { fprintf(stderr,"Evaluator.c:stablePtrOp unimp\n" );
2395 case i_makeStablePtr:
2397 StgStablePtr stable_ptr;
2398 if (stable_ptr_free == NULL) {
2399 enlargeStablePtrTable();
2402 stable_ptr = stable_ptr_free - stable_ptr_table;
2403 stable_ptr_free = (P_*)*stable_ptr_free;
2404 stable_ptr_table[stable_ptr] = PopPtr();
2406 PushTaggedStablePtr(stable_ptr);
2409 case i_deRefStablePtr:
2411 StgStablePtr stable_ptr = PopTaggedStablePtr();
2412 PushPtr(stable_ptr_table[stable_ptr]);
2416 case i_freeStablePtr:
2418 StgStablePtr stable_ptr = PopTaggedStablePtr();
2419 stable_ptr_table[stable_ptr] = (P_)stable_ptr_free;
2420 stable_ptr_free = stable_ptr_table + stable_ptr;
2426 #endif /* PROVIDE_STABLE */
2427 #ifdef PROVIDE_CONCURRENT
2430 StgClosure* c = PopCPtr();
2431 StgTSO* t = createGenThread(RtsFlags.GcFlags.initialStkSize,c);
2432 PushPtr(stgCast(StgPtr,t));
2434 /* switch at the earliest opportunity */
2436 /* but don't automatically switch to GHC - or you'll waste your
2437 * time slice switching back.
2439 * Actually, there's more to it than that: the default
2440 * (ThreadEnterGHC) causes the thread to crash - don't
2441 * understand why. - ADR
2443 t->whatNext = ThreadEnterHugs;
2448 StgTSO* tso = stgCast(StgTSO*,PopPtr());
2450 if (tso == CurrentTSO) { /* suicide */
2451 return ThreadFinished;
2456 { /* identical to i_sameRef */
2457 StgPtr x = PopPtr();
2458 StgPtr y = PopPtr();
2459 PushTaggedBool(x==y);
2464 StgMVar *mvar = stgCast(StgMVar*,allocate(sizeofW(StgMVar)));
2465 SET_INFO(mvar,&EMPTY_MVAR_info);
2466 mvar->head = mvar->tail = EndTSOQueue;
2467 /* ToDo: this is a little strange */
2468 mvar->value = stgCast(StgClosure*,&END_TSO_QUEUE_closure);
2469 PushPtr(stgCast(StgPtr,mvar));
2474 ToDo: another way out of the problem might be to add an explicit
2475 continuation to primTakeMVar: takeMVar v = primTakeMVar v takeMVar.
2476 The problem with this plan is that now I dont know how much to chop
2481 StgMVar *mvar = stgCast(StgMVar*,PopPtr());
2482 /* If the MVar is empty, put ourselves
2483 * on its blocking queue, and wait
2484 * until we're woken up.
2486 if (GET_INFO(mvar) != &FULL_MVAR_info) {
2487 if (mvar->head == EndTSOQueue) {
2488 mvar->head = CurrentTSO;
2490 mvar->tail->link = CurrentTSO;
2492 CurrentTSO->link = EndTSOQueue;
2493 mvar->tail = CurrentTSO;
2495 /* Hack, hack, hack.
2496 * When we block, we push a restart closure
2497 * on the stack - but which closure?
2498 * We happen to know that the BCO we're
2499 * executing looks like this:
2508 * 14: ALLOC_CONSTR 0x8213a80
2518 * so we rearrange the stack to look the
2519 * way it did when we entered this BCO
2521 * What a disgusting hack!
2527 return ThreadBlocked;
2530 PushCPtr(mvar->value);
2531 SET_INFO(mvar,&EMPTY_MVAR_info);
2532 /* ToDo: this is a little strange */
2533 mvar->value = (StgClosure*)&END_TSO_QUEUE_closure;
2540 StgMVar* mvar = stgCast(StgMVar*,PopPtr());
2541 StgClosure* value = PopCPtr();
2542 if (GET_INFO(mvar) == &FULL_MVAR_info) {
2543 obj = raisePrim("putMVar {full MVar}");
2546 /* wake up the first thread on the
2547 * queue, it will continue with the
2548 * takeMVar operation and mark the
2551 StgTSO* tso = mvar->head;
2552 SET_INFO(mvar,&FULL_MVAR_info);
2553 mvar->value = value;
2554 if (tso != EndTSOQueue) {
2555 PUSH_ON_RUN_QUEUE(tso);
2556 mvar->head = tso->link;
2557 tso->link = EndTSOQueue;
2558 if (mvar->head == EndTSOQueue) {
2559 mvar->tail = EndTSOQueue;
2563 /* yield for better communication performance */
2570 /* As PrimOps.h says: Hmm, I'll think about these later. */
2573 #endif /* PROVIDE_CONCURRENT */
2577 CFunDescriptor* descriptor = PopTaggedAddr();
2578 StgAddr funPtr = PopTaggedAddr();
2579 ccall(descriptor,funPtr);
2583 barf("Unrecognised primop2");
2588 barf("Unrecognised instruction");
2591 barf("Ran off the end of bco - yoiks");
2596 StgCAF* caf = stgCast(StgCAF*,obj);
2597 if (Sp - sizeofW(StgUpdateFrame) < SpLim) {
2598 PushCPtr(obj); /* code to restart with */
2599 return StackOverflow;
2601 /* ToDo: look for Sp==Su && stackInt(0) == UPD_FRAME and insert an indirection immediately */
2603 /*was StgBlackHole* */
2604 StgBlockingQueue* bh
2605 = stgCast(StgBlockingQueue*,grabHpUpd(BLACKHOLE_sizeW()));
2606 SET_INFO(bh,&CAF_BLACKHOLE_info);
2607 bh->blocking_queue = EndTSOQueue;
2608 IF_DEBUG(gccafs,fprintf(stderr,"Created CAF_BLACKHOLE %p for CAF %p in evaluator\n",bh,caf));
2609 SET_INFO(caf,&CAF_ENTERED_info);
2610 caf->value = stgCast(StgClosure*,bh);
2611 PUSH_UPD_FRAME(bh,0);
2612 Sp -= sizeofW(StgUpdateFrame);
2614 caf->link = enteredCAFs;
2621 StgCAF* caf = stgCast(StgCAF*,obj);
2622 obj = caf->value; /* it's just a fancy indirection */
2628 /*was StgBlackHole* */
2629 StgBlockingQueue* bh = stgCast(StgBlockingQueue*,obj);
2630 /* Put ourselves on the blocking queue for this black hole and block */
2631 CurrentTSO->link = bh->blocking_queue;
2632 bh->blocking_queue = CurrentTSO;
2633 PushCPtr(obj); /* code to restart with */
2634 return ThreadBlocked;
2638 StgAP_UPD* ap = stgCast(StgAP_UPD*,obj);
2640 if (Sp - (i + sizeofW(StgUpdateFrame)) < SpLim) {
2641 PushCPtr(obj); /* code to restart with */
2642 return StackOverflow;
2644 /* ToDo: look for Sp==Su && stackInt(0) == UPD_FRAME and insert an indirection immediately */
2645 PUSH_UPD_FRAME(ap,0);
2646 Sp -= sizeofW(StgUpdateFrame);
2648 PushWord(payloadWord(ap,i));
2651 #ifndef LAZY_BLACKHOLING
2653 /* superfluous - but makes debugging easier */
2654 StgBlackHole* bh = stgCast(StgBlackHole*,ap);
2655 SET_INFO(bh,&BLACKHOLE_info);
2656 bh->blocking_queue = EndTSOQueue;
2657 IF_DEBUG(gccafs,fprintf(stderr,"Eagerly blackholed AP_UPD %p in evaluator\n",bh));
2660 #endif /* LAZY_BLACKHOLING */
2665 StgPAP* pap = stgCast(StgPAP*,obj);
2666 int i = pap->n_args; /* ToDo: stack check */
2667 /* ToDo: if PAP is in whnf, we can update any update frames
2671 PushWord(payloadWord(pap,i));
2678 obj = stgCast(StgInd*,obj)->indirectee;
2682 case CONSTR_INTLIKE:
2683 case CONSTR_CHARLIKE:
2685 case CONSTR_NOCAF_STATIC:
2688 switch (get_itbl(stgCast(StgClosure*,Sp))->type) {
2693 PopUpdateFrame(obj);
2703 /*fprintf(stderr,"Sp = %p\tSu = %p\n", Sp, Su);*/
2704 /*printStack(Sp,CurrentTSO->stack+CurrentTSO->stack_size,Su);*/
2707 return ThreadFinished;
2718 case RET_SMALL: /* return to GHC */
2722 barf("todo: RET_[VEC_]{BIG,SMALL}");
2724 belch("entered CONSTR with invalid continuation on stack");
2726 printObj(stgCast(StgClosure*,Sp))
2728 barf("bailing out");
2734 CurrentTSO->whatNext = ThreadEnterGHC;
2735 PushCPtr(obj); /* code to restart with */
2736 return ThreadYielding;
2739 barf("Ran off the end of enter - yoiks");
2742 /* -----------------------------------------------------------------------------
2743 * ccall support code:
2744 * marshall moves args from C stack to Haskell stack
2745 * unmarshall moves args from Haskell stack to C stack
2746 * argSize calculates how much space you need on the C stack
2747 * ---------------------------------------------------------------------------*/
2749 /* Pop arguments off the C stack and Push them onto the Hugs stack.
2750 * Used when preparing for C calling Haskell or in response to
2751 * Haskell calling C.
2753 nat marshall(char arg_ty, void* arg)
2757 PushTaggedInt(*((int*)arg));
2758 return ARG_SIZE(INT_TAG);
2759 #ifdef PROVIDE_INT64
2761 PushTaggedInt64(*((StgInt64*)arg));
2762 return ARG_SIZE(INT64_TAG);
2764 #ifdef TODO_PROVIDE_INTEGER
2766 PushTaggedInteger(*((mpz_ptr*)arg));
2767 return ARG_SIZE(INTEGER_TAG);
2771 PushTaggedWord(*((unsigned int*)arg));
2772 return ARG_SIZE(WORD_TAG);
2775 PushTaggedChar(*((char*)arg));
2776 return ARG_SIZE(CHAR_TAG);
2778 PushTaggedFloat(*((float*)arg));
2779 return ARG_SIZE(FLOAT_TAG);
2781 PushTaggedDouble(*((double*)arg));
2782 return ARG_SIZE(DOUBLE_TAG);
2785 PushTaggedAddr(*((void**)arg));
2786 return ARG_SIZE(ADDR_TAG);
2788 #ifdef PROVIDE_STABLE
2790 PushTaggedStablePtr(*((StgStablePtr*)arg));
2791 return ARG_SIZE(STABLE_TAG);
2794 /* Not allowed in this direction - you have to
2795 * call makeForeignPtr explicitly
2797 barf("marshall: ForeignPtr#\n");
2799 #ifdef PROVIDE_ARRAY
2803 /* Not allowed in this direction */
2804 barf("marshall: [Mutable]ByteArray#\n");
2807 barf("marshall: unrecognised arg type %d\n",arg_ty);
2812 /* Pop arguments off the Hugs stack and Push them onto the C stack.
2813 * Used when preparing for Haskell calling C or in response to
2814 * C calling Haskell.
2816 nat unmarshall(char res_ty, void* res)
2820 *((int*)res) = PopTaggedInt();
2821 return ARG_SIZE(INT_TAG);
2822 #ifdef PROVIDE_INT64
2824 *((StgInt64*)res) = PopTaggedInt64();
2825 return ARG_SIZE(INT64_TAG);
2827 #ifdef TODO_PROVIDE_INTEGER
2829 *((mpz_ptr*)res) = PopTaggedInteger();
2830 return ARG_SIZE(INTEGER_TAG);
2834 *((unsigned int*)res) = PopTaggedWord();
2835 return ARG_SIZE(WORD_TAG);
2838 *((int*)res) = PopTaggedChar();
2839 return ARG_SIZE(CHAR_TAG);
2841 *((float*)res) = PopTaggedFloat();
2842 return ARG_SIZE(FLOAT_TAG);
2844 *((double*)res) = PopTaggedDouble();
2845 return ARG_SIZE(DOUBLE_TAG);
2848 *((void**)res) = PopTaggedAddr();
2849 return ARG_SIZE(ADDR_TAG);
2851 #ifdef PROVIDE_STABLE
2853 *((StgStablePtr*)res) = PopTaggedStablePtr();
2854 return ARG_SIZE(STABLE_TAG);
2858 StgForeignObj *result = stgCast(StgForeignObj*,PopPtr());
2859 *((void**)res) = result->data;
2860 return sizeofW(StgPtr);
2862 #ifdef PROVIDE_ARRAY
2867 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
2868 *((void**)res) = stgCast(void*,&(arr->payload));
2869 return sizeofW(StgPtr);
2872 barf("unmarshall: unrecognised result type %d\n",res_ty);
2876 nat argSize( const char* ks )
2879 for( ; *ks != '\0'; ++ks) {
2882 sz += sizeof(StgWord) * ARG_SIZE(INT_TAG);
2884 #ifdef PROVIDE_INT64
2886 sz += sizeof(StgWord) * ARG_SIZE(INT64_TAG);
2889 #ifdef TODO_PROVIDE_INTEGER
2891 sz += sizeof(StgWord) * ARG_SIZE(INTEGER_TAG);
2896 sz += sizeof(StgWord) * ARG_SIZE(WORD_TAG);
2900 sz += sizeof(StgWord) * ARG_SIZE(CHAR_TAG);
2903 sz += sizeof(StgWord) * ARG_SIZE(FLOAT_TAG);
2906 sz += sizeof(StgWord) * ARG_SIZE(DOUBLE_TAG);
2910 sz += sizeof(StgWord) * ARG_SIZE(ADDR_TAG);
2913 #ifdef PROVIDE_STABLE
2915 sz += sizeof(StgWord) * ARG_SIZE(STABLE_TAG);
2918 #ifdef PROVIDE_FOREIGN
2921 #ifdef PROVIDE_ARRAY
2925 sz += sizeof(StgPtr);
2928 barf("argSize: unrecognised result type %d\n",*ks);
2935 #endif /* INTERPRETER */