1 /* -*- mode: hugs-c; -*- */
2 /* -----------------------------------------------------------------------------
5 * Copyright (c) 1994-1998.
7 * $RCSfile: Evaluator.c,v $
9 * $Date: 1999/01/27 14:51:18 $
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 static inline void mpz_free ( mpz_ptr a )
124 /* --------------------------------------------------------------------------
126 * ------------------------------------------------------------------------*/
128 static inline void PushTag ( StackTag t );
129 static inline void PushPtr ( StgPtr x );
130 static inline void PushCPtr ( StgClosure* x );
131 static inline void PushInt ( StgInt x );
132 static inline void PushWord ( StgWord x );
134 static inline void PushTag ( StackTag t ) { *(--Sp) = t; }
135 static inline void PushPtr ( StgPtr x ) { *(--stgCast(StgPtr*,Sp)) = x; }
136 static inline void PushCPtr ( StgClosure* x ) { *(--stgCast(StgClosure**,Sp)) = x; }
137 static inline void PushInt ( StgInt x ) { *(--stgCast(StgInt*,Sp)) = x; }
138 static inline void PushWord ( StgWord x ) { *(--stgCast(StgWord*,Sp)) = x; }
140 static inline void checkTag ( StackTag t1, StackTag t2 );
141 static inline void PopTag ( StackTag t );
142 static inline StgPtr PopPtr ( void );
143 static inline StgClosure* PopCPtr ( void );
144 static inline StgInt PopInt ( void );
145 static inline StgWord PopWord ( void );
147 static inline void checkTag ( StackTag t1, StackTag t2 ) { ASSERT(t1 == t2);}
148 static inline void PopTag ( StackTag t ) { checkTag(t,*(Sp++)); }
149 static inline StgPtr PopPtr ( void ) { return *stgCast(StgPtr*,Sp)++; }
150 static inline StgClosure* PopCPtr ( void ) { return *stgCast(StgClosure**,Sp)++; }
151 static inline StgInt PopInt ( void ) { return *stgCast(StgInt*,Sp)++; }
152 static inline StgWord PopWord ( void ) { return *stgCast(StgWord*,Sp)++; }
154 static inline StgPtr stackPtr ( StgStackOffset i );
155 static inline StgInt stackInt ( StgStackOffset i );
156 static inline StgWord stackWord ( StgStackOffset i );
158 static inline StgPtr stackPtr ( StgStackOffset i ) { return *stgCast(StgPtr*, Sp+i); }
159 static inline StgInt stackInt ( StgStackOffset i ) { return *stgCast(StgInt*, Sp+i); }
160 static inline StgWord stackWord ( StgStackOffset i ) { return *stgCast(StgWord*,Sp+i); }
162 static inline void setStackWord ( StgStackOffset i, StgWord w );
164 static inline void setStackWord ( StgStackOffset i, StgWord w ) { Sp[i] = w; }
166 static inline void PushTaggedRealWorld( void );
167 static inline void PushTaggedInt ( StgInt x );
169 static inline void PushTaggedInt64 ( StgInt64 x );
171 #ifdef PROVIDE_INTEGER
172 static inline void PushTaggedInteger ( mpz_ptr x );
175 static inline void PushTaggedWord ( StgWord x );
178 static inline void PushTaggedAddr ( StgAddr x );
180 static inline void PushTaggedChar ( StgChar x );
181 static inline void PushTaggedFloat ( StgFloat x );
182 static inline void PushTaggedDouble ( StgDouble x );
183 static inline void PushTaggedStablePtr ( StgStablePtr x );
184 static inline void PushTaggedBool ( int x );
186 static inline void PushTaggedRealWorld( void ) { PushTag(REALWORLD_TAG); }
187 static inline void PushTaggedInt ( StgInt x ) { Sp -= sizeofW(StgInt); *Sp = x; PushTag(INT_TAG); }
189 static inline void PushTaggedInt64 ( StgInt64 x ) { Sp -= sizeofW(StgInt64); ASSIGN_Int64(Sp,x); PushTag(INT64_TAG); }
191 #ifdef PROVIDE_INTEGER
192 static inline void PushTaggedInteger ( mpz_ptr x )
194 StgForeignObj *result;
197 result = stgCast(StgForeignObj*,allocate(sizeofW(StgForeignObj)));
198 SET_HDR(result,&FOREIGN_info,CCCS);
201 #if 0 /* For now we don't deallocate Integer's at all */
202 w = stgCast(StgWeak*,allocate(sizeofW(StgWeak)));
203 SET_HDR(w, &WEAK_info, CCCS);
204 w->key = stgCast(StgClosure*,result);
205 w->value = stgCast(StgClosure*,result); /* or any other closure you have handy */
206 w->finaliser = funPtrToIO(mpz_free);
207 w->link = weak_ptr_list;
209 IF_DEBUG(weak, fprintf(stderr,"New weak pointer watching Foreign MPZ at %p\n",w));
212 PushPtr(stgCast(StgPtr,result));
216 static inline void PushTaggedWord ( StgWord x ) { Sp -= sizeofW(StgWord); *Sp = x; PushTag(WORD_TAG); }
219 static inline void PushTaggedAddr ( StgAddr x ) { Sp -= sizeofW(StgAddr); *Sp = (W_)x; PushTag(ADDR_TAG); }
221 static inline void PushTaggedChar ( StgChar x ) { Sp -= sizeofW(StgChar); *Sp = x; PushTag(CHAR_TAG); }
222 static inline void PushTaggedFloat ( StgFloat x ) { Sp -= sizeofW(StgFloat); ASSIGN_FLT(Sp,x); PushTag(FLOAT_TAG); }
223 static inline void PushTaggedDouble ( StgDouble x ) { Sp -= sizeofW(StgDouble); ASSIGN_DBL(Sp,x); PushTag(DOUBLE_TAG); }
224 static inline void PushTaggedStablePtr ( StgStablePtr x ) { Sp -= sizeofW(StgStablePtr); *Sp = x; PushTag(STABLE_TAG); }
225 static inline void PushTaggedBool ( int x ) { PushTaggedInt(x); }
227 static inline void PopTaggedRealWorld ( void );
228 static inline StgInt PopTaggedInt ( void );
230 static inline StgInt64 PopTaggedInt64 ( void );
232 #ifdef PROVIDE_INTEGER
233 static inline mpz_ptr PopTaggedInteger ( void );
236 static inline StgWord PopTaggedWord ( void );
239 static inline StgAddr PopTaggedAddr ( void );
241 static inline StgChar PopTaggedChar ( void );
242 static inline StgFloat PopTaggedFloat ( void );
243 static inline StgDouble PopTaggedDouble ( void );
244 static inline StgStablePtr PopTaggedStablePtr ( void );
246 static inline void PopTaggedRealWorld ( void ) { PopTag(REALWORLD_TAG); }
247 static inline StgInt PopTaggedInt ( void ) { StgInt r; PopTag(INT_TAG); r = *stgCast(StgInt*, Sp); Sp += sizeofW(StgInt); return r;}
249 static inline StgInt64 PopTaggedInt64 ( void ) { StgInt64 r; PopTag(INT64_TAG); r = PK_Int64(Sp); Sp += sizeofW(StgInt64); return r;}
251 #ifdef PROVIDE_INTEGER
252 static inline mpz_ptr PopTaggedInteger ( void ) { StgForeignObj *r = *stgCast(StgForeignObj**,Sp); Sp += sizeofW(StgPtr); return stgCast(mpz_ptr,r->data);}
255 static inline StgWord PopTaggedWord ( void ) { StgWord r; PopTag(WORD_TAG); r = *stgCast(StgWord*, Sp); Sp += sizeofW(StgWord); return r;}
258 static inline StgAddr PopTaggedAddr ( void ) { StgAddr r; PopTag(ADDR_TAG); r = *stgCast(StgAddr*, Sp); Sp += sizeofW(StgAddr); return r;}
260 static inline StgChar PopTaggedChar ( void ) { StgChar r; PopTag(CHAR_TAG); r = *stgCast(StgChar*, Sp); Sp += sizeofW(StgChar); return r;}
261 static inline StgFloat PopTaggedFloat ( void ) { StgFloat r; PopTag(FLOAT_TAG); r = PK_FLT(Sp); Sp += sizeofW(StgFloat); return r;}
262 static inline StgDouble PopTaggedDouble ( void ) { StgDouble r; PopTag(DOUBLE_TAG); r = PK_DBL(Sp); Sp += sizeofW(StgDouble); return r;}
263 static inline StgStablePtr PopTaggedStablePtr ( void ) { StgInt r; PopTag(STABLE_TAG); r = *stgCast(StgStablePtr*, Sp); Sp += sizeofW(StgStablePtr); return r;}
265 static inline StgInt taggedStackInt ( StgStackOffset i );
267 static inline StgInt64 taggedStackInt64 ( StgStackOffset i );
270 static inline StgWord taggedStackWord ( StgStackOffset i );
273 static inline StgAddr taggedStackAddr ( StgStackOffset i );
275 static inline StgChar taggedStackChar ( StgStackOffset i );
276 static inline StgFloat taggedStackFloat ( StgStackOffset i );
277 static inline StgDouble taggedStackDouble ( StgStackOffset i );
278 static inline StgStablePtr taggedStackStable ( StgStackOffset i );
280 static inline StgInt taggedStackInt ( StgStackOffset i ) { checkTag(INT_TAG,Sp[i]); return *stgCast(StgInt*, Sp+1+i); }
282 static inline StgInt64 taggedStackInt64 ( StgStackOffset i ) { checkTag(INT64_TAG,Sp[i]); return PK_Int64(Sp+1+i); }
285 static inline StgWord taggedStackWord ( StgStackOffset i ) { checkTag(WORD_TAG,Sp[i]); return *stgCast(StgWord*, Sp+1+i); }
288 static inline StgAddr taggedStackAddr ( StgStackOffset i ) { checkTag(ADDR_TAG,Sp[i]); return *stgCast(StgAddr*, Sp+1+i); }
290 static inline StgChar taggedStackChar ( StgStackOffset i ) { checkTag(CHAR_TAG,Sp[i]); return *stgCast(StgChar*, Sp+1+i); }
291 static inline StgFloat taggedStackFloat ( StgStackOffset i ) { checkTag(FLOAT_TAG,Sp[i]); return PK_FLT(Sp+1+i); }
292 static inline StgDouble taggedStackDouble ( StgStackOffset i ) { checkTag(DOUBLE_TAG,Sp[i]); return PK_DBL(Sp+1+i); }
293 static inline StgStablePtr taggedStackStable ( StgStackOffset i ) { checkTag(STABLE_TAG,Sp[i]); return *stgCast(StgStablePtr*, Sp+1+i); }
296 /* --------------------------------------------------------------------------
299 * Should we allocate from a nursery or use the
300 * doYouWantToGC/allocate interface? We'd already implemented a
301 * nursery-style scheme when the doYouWantToGC/allocate interface
303 * One reason to prefer the doYouWantToGC/allocate interface is to
304 * support operations which allocate an unknown amount in the heap
305 * (array ops, gmp ops, etc)
306 * ------------------------------------------------------------------------*/
308 static inline StgPtr grabHpUpd( nat size )
310 ASSERT( size >= MIN_UPD_SIZE + sizeofW(StgHeader) );
311 return allocate(size);
314 static inline StgPtr grabHpNonUpd( nat size )
316 ASSERT( size >= MIN_NONUPD_SIZE + sizeofW(StgHeader) );
317 return allocate(size);
320 /* --------------------------------------------------------------------------
321 * Manipulate "update frame" list:
322 * o Update frames (based on stg_do_update and friends in Updates.hc)
323 * o Error handling/catching (based on catchzh_fast and friends in Prims.hc)
324 * o Seq frames (based on seq_frame_entry in Prims.hc)
326 * ------------------------------------------------------------------------*/
328 static inline void PopUpdateFrame ( StgClosure* obj );
329 static inline void PushCatchFrame ( StgClosure* catcher );
330 static inline void PopCatchFrame ( void );
331 static inline void PushSeqFrame ( void );
332 static inline void PopSeqFrame ( void );
334 static inline StgClosure* raiseAnError ( StgClosure* errObj );
336 static inline void PopUpdateFrame( StgClosure* obj )
338 /* NB: doesn't assume that Sp == Su */
340 fprintf(stderr, "Updating ");
341 printPtr(stgCast(StgPtr,Su->updatee));
342 fprintf(stderr, " with ");
344 fprintf(stderr,"\nSp = %p\tSu = %p\n", Sp, Su);
346 #ifndef LAZY_BLACKHOLING
347 ASSERT(get_itbl(Su->updatee)->type == BLACKHOLE
348 || get_itbl(Su->updatee)->type == CAF_BLACKHOLE
350 #endif /* LAZY_BLACKHOLING */
351 UPD_IND(Su->updatee,obj);
352 Sp = stgCast(StgStackPtr,Su) + sizeofW(StgUpdateFrame);
356 static inline void PopStopFrame( StgClosure* obj )
358 /* Move Su just off the end of the stack, we're about to spam the
359 * STOP_FRAME with the return value.
361 Su = stgCast(StgUpdateFrame*,Sp+1);
362 *stgCast(StgClosure**,Sp) = obj;
365 static inline void PushCatchFrame( StgClosure* handler )
368 /* ToDo: stack check! */
369 Sp -= sizeofW(StgCatchFrame*); /* ToDo: this can't be right */
370 fp = stgCast(StgCatchFrame*,Sp);
371 SET_HDR(fp,&catch_frame_info,CCCS);
372 fp->handler = handler;
374 Su = stgCast(StgUpdateFrame*,fp);
377 static inline void PopCatchFrame( void )
379 /* NB: doesn't assume that Sp == Su */
380 /* fprintf(stderr,"Popping catch frame\n"); */
381 Sp = stgCast(StgStackPtr,Su) + sizeofW(StgCatchFrame);
382 Su = stgCast(StgCatchFrame*,Su)->link;
385 static inline void PushSeqFrame( void )
388 /* ToDo: stack check! */
389 Sp -= sizeofW(StgSeqFrame*); /* ToDo: this can't be right */
390 fp = stgCast(StgSeqFrame*,Sp);
391 SET_HDR(fp,&seq_frame_info,CCCS);
393 Su = stgCast(StgUpdateFrame*,fp);
396 static inline void PopSeqFrame( void )
398 /* NB: doesn't assume that Sp == Su */
399 Sp = stgCast(StgStackPtr,Su) + sizeofW(StgSeqFrame);
400 Su = stgCast(StgSeqFrame*,Su)->link;
403 static inline StgClosure* raiseAnError( StgClosure* errObj )
405 StgClosure *raise_closure;
407 /* This closure represents the expression 'raise# E' where E
408 * is the exception raise. It is used to overwrite all the
409 * thunks which are currently under evaluataion.
411 raise_closure = (StgClosure *)allocate(sizeofW(StgClosure)+1);
412 raise_closure->header.info = &raise_info;
413 raise_closure->payload[0] = R1.cl;
416 switch (get_itbl(Su)->type) {
418 UPD_IND(Su->updatee,raise_closure);
419 Sp = stgCast(StgStackPtr,Su) + sizeofW(StgUpdateFrame);
425 case CATCH_FRAME: /* found it! */
427 StgCatchFrame* fp = stgCast(StgCatchFrame*,Su);
428 StgClosure *handler = fp->handler;
430 Sp += sizeofW(StgCatchFrame); /* Pop */
435 barf("raiseError: STOP_FRAME");
437 barf("raiseError: weird activation record");
442 static StgClosure* raisePrim(char* msg)
444 /* ToDo: figure out some way to turn the msg into a Haskell Exception
445 * Hack: we don't know how to build an Exception but we do know how
446 * to build a (recursive!) error object.
447 * The result isn't pretty but it's (slightly) better than nothing.
449 nat size = sizeof(StgClosure) + 1;
450 StgClosure* errObj = stgCast(StgClosure*,grabHpNonUpd(size));
451 SET_INFO(errObj,&raise_info);
452 errObj->payload[0] = errObj;
457 /* At the moment, I prefer to put it on stdout to make things as
458 * close to Hugs' old behaviour as possible.
460 fprintf(stdout, "Program error: %s", msg);
463 return raiseAnError(stgCast(StgClosure*,errObj));
466 #define raiseIndex(where) raisePrim("Array index out of range in " where)
467 #define raiseDiv0(where) raisePrim("Division by 0 in " where)
469 /* --------------------------------------------------------------------------
471 * ------------------------------------------------------------------------*/
475 unsigned char x = PopTaggedChar(); \
476 unsigned char y = PopTaggedChar(); \
482 unsigned char x = PopTaggedChar(); \
493 StgInt x = PopTaggedInt(); \
494 StgWord y = PopTaggedWord(); \
500 StgInt x = PopTaggedInt(); \
501 StgInt y = PopTaggedInt(); \
507 StgInt x = PopTaggedInt(); \
508 StgInt y = PopTaggedInt(); \
519 StgInt x = PopTaggedInt(); \
525 StgInt x = PopTaggedInt(); \
536 StgInt x = PopTaggedInt(); \
547 StgInt x = PopTaggedInt(); \
553 PushTaggedFloat(e); \
558 StgInt x = PopTaggedInt(); \
559 PushTaggedFloat(e); \
564 PushTaggedDouble(e); \
569 StgInt x = PopTaggedInt(); \
570 PushTaggedDouble(e); \
576 StgWord x = PopTaggedWord(); \
577 StgWord y = PopTaggedWord(); \
583 StgWord x = PopTaggedWord(); \
584 StgWord y = PopTaggedWord(); \
590 StgWord x = PopTaggedWord(); \
596 StgWord x = PopTaggedWord(); \
604 StgAddr x = PopTaggedAddr(); \
605 StgAddr y = PopTaggedAddr(); \
610 StgAddr x = PopTaggedAddr(); \
615 StgAddr x = PopTaggedAddr(); \
616 int y = PopTaggedInt(); \
623 StgAddr x = PopTaggedAddr(); \
624 int y = PopTaggedInt(); \
631 StgAddr x = PopTaggedAddr(); \
632 int y = PopTaggedInt(); \
635 PushTaggedInt64(r); \
639 StgAddr x = PopTaggedAddr(); \
640 int y = PopTaggedInt(); \
647 StgAddr x = PopTaggedAddr(); \
648 int y = PopTaggedInt(); \
651 PushTaggedFloat(r); \
655 StgAddr x = PopTaggedAddr(); \
656 int y = PopTaggedInt(); \
659 PushTaggedDouble(r); \
663 StgAddr x = PopTaggedAddr(); \
664 int y = PopTaggedInt(); \
667 PushTaggedStablePtr(r); \
671 StgAddr x = PopTaggedAddr(); \
672 int y = PopTaggedInt(); \
673 StgChar z = PopTaggedChar(); \
678 StgAddr x = PopTaggedAddr(); \
679 int y = PopTaggedInt(); \
680 StgInt z = PopTaggedInt(); \
685 StgAddr x = PopTaggedAddr(); \
686 int y = PopTaggedInt(); \
687 StgInt64 z = PopTaggedInt64(); \
692 StgAddr x = PopTaggedAddr(); \
693 int y = PopTaggedInt(); \
694 StgAddr z = PopTaggedAddr(); \
699 StgAddr x = PopTaggedAddr(); \
700 int y = PopTaggedInt(); \
701 StgFloat z = PopTaggedFloat(); \
706 StgAddr x = PopTaggedAddr(); \
707 int y = PopTaggedInt(); \
708 StgDouble z = PopTaggedDouble(); \
713 StgAddr x = PopTaggedAddr(); \
714 int y = PopTaggedInt(); \
715 StgStablePtr z = PopTaggedStablePtr(); \
719 #endif /* PROVIDE_ADDR */
723 StgFloat x = PopTaggedFloat(); \
724 StgFloat y = PopTaggedFloat(); \
730 StgFloat x = PopTaggedFloat(); \
731 StgFloat y = PopTaggedFloat(); \
732 PushTaggedFloat(e); \
737 StgFloat x = PopTaggedFloat(); \
738 PushTaggedFloat(e); \
743 StgFloat x = PopTaggedFloat(); \
749 StgFloat x = PopTaggedFloat(); \
755 StgFloat x = PopTaggedFloat(); \
756 PushTaggedDouble(e); \
761 StgDouble x = PopTaggedDouble(); \
762 StgDouble y = PopTaggedDouble(); \
768 StgDouble x = PopTaggedDouble(); \
769 StgDouble y = PopTaggedDouble(); \
770 PushTaggedDouble(e); \
775 StgDouble x = PopTaggedDouble(); \
781 StgDouble x = PopTaggedDouble(); \
782 PushTaggedDouble(e); \
787 StgDouble x = PopTaggedDouble(); \
793 StgDouble x = PopTaggedDouble(); \
794 PushTaggedFloat(e); \
800 StgInt64 x = PopTaggedInt64(); \
801 int y = PopTaggedInt(); \
802 PushTaggedFloat(e); \
806 StgInt64 x = PopTaggedInt64(); \
807 int y = PopTaggedInt(); \
808 PushTaggedDouble(e); \
812 StgInt64 x = PopTaggedInt64(); \
813 StgInt64 y = PopTaggedInt64(); \
818 StgInt64 x = PopTaggedInt64(); \
819 PushTaggedInt64(e); \
823 StgInt64 x = PopTaggedInt64(); \
824 StgInt64 y = PopTaggedInt64(); \
825 PushTaggedInt64(e); \
829 StgInt64 x = PopTaggedInt64(); \
830 StgWord y = PopTaggedWord(); \
831 PushTaggedInt64(e); \
833 #define OP_zz_zZ(e1,e2) \
835 StgInt64 x = PopTaggedInt64(); \
836 StgInt64 y = PopTaggedInt64(); \
837 PushTaggedInt64(e1); \
838 PushTaggedInt64(e2); \
842 StgInt64 x = PopTaggedInt64(); \
843 StgInt64 y = PopTaggedInt64(); \
848 PushTaggedInt64(e); \
852 StgInt64 x = PopTaggedInt64(); \
857 StgInt x = PopTaggedInt(); \
858 PushTaggedInt64(e); \
863 StgInt64 x = PopTaggedInt64(); \
868 StgWord x = PopTaggedWord(); \
869 PushTaggedInt64(e); \
874 StgInt64 x = PopTaggedInt64(); \
875 printf("%lld = %f\n",x,(float)(e)); \
876 PushTaggedFloat(e); \
880 StgFloat x = PopTaggedFloat(); \
881 PushTaggedInt64(e); \
885 StgInt64 x = PopTaggedInt64(); \
886 PushTaggedDouble(e); \
890 StgDouble x = PopTaggedDouble(); \
891 PushTaggedInt64(e); \
895 #ifdef PROVIDE_INTEGER
899 mpz_ptr x = PopTaggedInteger(); \
900 int y = PopTaggedInt(); \
901 PushTaggedFloat(e); \
905 StgFloat x = PopTaggedFloat(); \
906 mpz_ptr r1 = mpz_alloc(); \
910 PushTaggedInteger(r1); \
914 mpz_ptr x = PopTaggedInteger(); \
915 int y = PopTaggedInt(); \
916 PushTaggedDouble(e); \
920 StgDouble x = PopTaggedDouble(); \
921 mpz_ptr r1 = mpz_alloc(); \
925 PushTaggedInteger(r1); \
929 mpz_ptr x = PopTaggedInteger(); \
930 mpz_ptr r = mpz_alloc(); \
932 PushTaggedInteger(r); \
936 mpz_ptr x = PopTaggedInteger(); \
937 mpz_ptr y = PopTaggedInteger(); \
938 mpz_ptr r = mpz_alloc(); \
940 PushTaggedInteger(r); \
944 mpz_ptr x = PopTaggedInteger(); \
945 mpz_ptr y = PopTaggedInteger(); \
950 mpz_ptr x = PopTaggedInteger(); \
955 StgInt x = PopTaggedInt(); \
956 mpz_ptr r = mpz_alloc(); \
958 PushTaggedInteger(r); \
963 mpz_ptr x = PopTaggedInteger(); \
964 PushTaggedInt64(e); \
968 StgInt64 x = PopTaggedInt64(); \
969 mpz_ptr r = mpz_alloc(); \
971 PushTaggedInteger(r); \
977 mpz_ptr x = PopTaggedInteger(); \
982 StgWord x = PopTaggedWord(); \
983 mpz_ptr r = mpz_alloc(); \
985 PushTaggedInteger(r); \
990 mpz_ptr x = PopTaggedInteger(); \
991 PushTaggedFloat(e); \
995 StgFloat x = PopTaggedFloat(); \
996 mpz_ptr r = mpz_alloc(); \
998 PushTaggedInteger(r); \
1002 mpz_ptr x = PopTaggedInteger(); \
1003 PushTaggedDouble(e); \
1007 StgDouble x = PopTaggedDouble(); \
1008 mpz_ptr r = mpz_alloc(); \
1010 PushTaggedInteger(r); \
1013 #endif /* ifdef PROVIDE_INTEGER */
1015 #ifdef PROVIDE_ARRAY
1016 #define HEADER_mI(ty,where) \
1017 StgArrWords* x = stgCast(StgArrWords*,PopPtr()); \
1018 nat i = PopTaggedInt(); \
1019 if (i * sizeof(ty) + (sizeof(ty)) > sizeof(StgWord) * x->words) { \
1020 obj = raiseIndex(where); \
1023 #define OP_mI_ty(ty,where,s) \
1025 HEADER_mI(mycat2(Stg,ty),where) \
1026 { mycat2(Stg,ty) r; \
1028 mycat2(PushTagged,ty)(r); \
1031 #define OP_mIty_(ty,where,s) \
1033 HEADER_mI(mycat2(Stg,ty),where) \
1035 mycat2(Stg,ty) z = mycat2(PopTagged,ty)(); \
1040 #endif /* PROVIDE_ARRAY */
1043 /* This is written as one giant function in the hope that gcc will do
1044 * a better job of register allocation.
1046 StgThreadReturnCode enter( StgClosure* obj )
1048 /* We use a char so that we'll do a context_switch check every 256
1051 char enterCount = 0;
1053 /* ASSERT(StorageMgrInfo.hp_start <= Hp && Hp < HpLim && HpLim == StorageMgrInfo.hplim); */
1054 ASSERT(SpLim <= Sp && Sp <= stgCast(StgPtr,Su));
1057 fprintf(stderr,"Sp = %p\tSu = %p\n", Sp, Su);
1058 printStack(Sp,CurrentTSO->stack+CurrentTSO->stack_size,Su);
1059 fprintf(stderr,"Entering: "); printObj(obj);
1065 /*belch("Starting sanity check");
1067 *checkTSO(CurrentTSO, heap_step);
1068 * This check fails if we've done any updates because we
1069 * whack into holes in the heap.
1071 *belch("Ending sanity check");
1078 fprintf(stderr,"Continue?\n");
1082 if (++enterCount == 0 && context_switch) {
1083 PushCPtr(obj); /* code to restart with */
1084 return ThreadYielding;
1086 switch ( get_itbl(obj)->type ) {
1087 case INVALID_OBJECT:
1088 barf("Invalid object %p",obj);
1091 StgBCO* bco = stgCast(StgBCO*,obj);
1093 #if 1 /* We don't use an explicit HP_CHECK anymore */
1094 if (doYouWantToGC()) {
1095 PushCPtr(obj); /* code to restart with */
1096 return HeapOverflow;
1100 ASSERT(pc < bco->n_instrs);
1102 fprintf(stderr,"Sp = %p\tSu = %p\tpc = %d\t", Sp, Su, pc);
1104 /*fprintf(stderr,"\t"); printStackObj(Sp); */
1105 fprintf(stderr,"\n");
1107 switch (bcoInstr(bco,pc++)) {
1108 case i_INTERNAL_ERROR:
1109 barf("INTERNAL_ERROR at %p:%d",bco,pc-1);
1111 barf("PANIC at %p:%d",bco,pc-1);
1115 int n = bcoInstr(bco,pc++);
1116 /* ToDo: we could allocate the whole thing now and
1117 * slice it up ourselves
1119 if (doYouWantToGC()) {
1120 PushCPtr(obj); /* code to restart with */
1121 return HeapOverflow;
1128 int n = bcoInstr(bco,pc++);
1129 if (Sp - n < SpLim) {
1130 PushCPtr(obj); /* code to restart with */
1131 return StackOverflow;
1137 /* ToDo: make sure that hp check allows for possible PAP */
1138 nat n = bcoInstr(bco,pc++);
1139 if (stgCast(StgPtr,Sp + n) > stgCast(StgPtr,Su)) {
1140 StgWord words = (P_)Su - Sp;
1142 /* first build a PAP */
1143 ASSERT((P_)Su >= Sp); /* was (words >= 0) but that's always true */
1144 if (words == 0) { /* optimisation */
1145 /* Skip building the PAP and update with an indirection. */
1146 } else { /* Build the PAP. */
1147 /* In the evaluator, we avoid the need to do
1148 * a heap check here by including the size of
1149 * the PAP in the heap check we performed
1150 * when we entered the BCO.
1153 StgPAP* pap = stgCast(StgPAP*,grabHpNonUpd(PAP_sizeW(words)));
1154 SET_HDR(pap,&PAP_info,CC_pap);
1155 pap->n_args = words;
1157 for(i = 0; i < (I_)words; ++i) {
1158 payloadWord(pap,i) = Sp[i];
1161 obj = stgCast(StgClosure*,pap);
1164 /* now deal with "update frame" */
1165 /* as an optimisation, we process all on top of stack instead of just the top one */
1168 switch (get_itbl(Su)->type) {
1173 PopUpdateFrame(obj);
1177 return ThreadFinished;
1182 barf("Invalid update frame during argcheck");
1184 } while (Sp==(P_)Su);
1191 int words = bcoInstr(bco,pc++);
1192 PushPtr(grabHpUpd(AP_sizeW(words)));
1195 case i_ALLOC_CONSTR:
1197 StgInfoTable* info = bcoConstAddr(bco,bcoInstr(bco,pc++));
1198 StgClosure* c = stgCast(StgClosure*,grabHpNonUpd(sizeW_fromITBL(info)));
1200 PushPtr(stgCast(StgPtr,c));
1205 int x = bcoInstr(bco,pc++); /* ToDo: Word not Int! */
1206 int y = bcoInstr(bco,pc++);
1207 StgAP_UPD* o = stgCast(StgAP_UPD*,stackPtr(x));
1208 SET_HDR(o,&AP_UPD_info,??);
1210 o->fun = stgCast(StgClosure*,PopPtr());
1211 for(x=0; x < y; ++x) {
1212 payloadWord(o,x) = PopWord();
1215 fprintf(stderr,"\tBuilt ");
1216 printObj(stgCast(StgClosure*,o));
1222 int x = bcoInstr(bco,pc++);
1223 int y = bcoInstr(bco,pc++);
1224 StgPAP* o = stgCast(StgPAP*,stackPtr(x));
1225 SET_HDR(o,&PAP_info,??);
1227 o->fun = stgCast(StgClosure*,PopPtr());
1228 for(x=0; x < y; ++x) {
1229 payloadWord(o,x) = PopWord();
1232 fprintf(stderr,"\tBuilt ");
1233 printObj(stgCast(StgClosure*,o));
1239 int offset = bcoInstr(bco,pc++);
1240 StgClosure* o = stgCast(StgClosure*,stackPtr(offset));
1241 const StgInfoTable* info = get_itbl(o);
1242 nat p = info->layout.payload.ptrs;
1243 nat np = info->layout.payload.nptrs;
1245 for(i=0; i < p; ++i) {
1246 payloadCPtr(o,i) = PopCPtr();
1248 for(i=0; i < np; ++i) {
1249 payloadWord(o,p+i) = 0xdeadbeef;
1252 fprintf(stderr,"\tBuilt ");
1253 printObj(stgCast(StgClosure*,o));
1259 int x = bcoInstr(bco,pc++);
1260 int y = bcoInstr(bco,pc++);
1261 ASSERT(Sp+x+y <= stgCast(StgPtr,Su));
1262 /* a_1, .. a_x, b_1, .. b_y, s => a_1, .. a_x, s */
1264 setStackWord(x+y,stackWord(x));
1276 PushPtr(bcoConstPtr(bco,bcoInstr(bco,pc++)));
1277 PushPtr(stgCast(StgPtr,&ret_bco_info));
1282 int tag = bcoInstr(bco,pc++);
1283 StgWord offset = bcoInstr(bco,pc++);
1284 if (constrTag(stgCast(StgClosure*,stackPtr(0))) != tag) {
1291 StgClosure* o = stgCast(StgClosure*,stackPtr(0));
1292 const StgInfoTable* itbl = get_itbl(o);
1293 int i = itbl->layout.payload.ptrs;
1294 ASSERT( itbl->type == CONSTR
1295 || itbl->type == CONSTR_STATIC
1296 || itbl->type == CONSTR_NOCAF_STATIC
1299 PushCPtr(payloadCPtr(o,i));
1305 PushPtr(stackPtr(bcoInstr(bco,pc++)));
1310 PushPtr(stgCast(StgPtr,bcoConstPtr(bco,bcoInstr(bco,pc++))));
1315 StgWord o1 = bcoInstr(bco,pc++);
1316 StgWord o2 = bcoInstr(bco,pc++);
1317 StgWord o = o1*256 + o2;
1318 PushPtr(stgCast(StgPtr,bcoConstPtr(bco,o)));
1323 PushTaggedRealWorld();
1328 PushTaggedInt(taggedStackInt(bcoInstr(bco,pc++)));
1333 PushTaggedInt(bcoConstInt(bco,bcoInstr(bco,pc++)));
1343 StgClosure* o = stgCast(StgClosure*,grabHpNonUpd(Izh_sizeW));
1344 SET_HDR(o,&Izh_con_info,??);
1345 payloadWord(o,0) = PopTaggedInt();
1347 fprintf(stderr,"\tBuilt ");
1348 printObj(stgCast(StgClosure*,o));
1350 PushPtr(stgCast(StgPtr,o));
1355 StgClosure* con = stgCast(StgClosure*,stackPtr(0));
1356 /* ASSERT(isIntLike(con)); */
1357 PushTaggedInt(payloadWord(con,0));
1362 StgWord offset = bcoInstr(bco,pc++);
1363 StgInt x = PopTaggedInt();
1364 StgInt y = PopTaggedInt();
1370 #ifdef PROVIDE_INT64
1373 PushTaggedInt64(taggedStackInt64(bcoInstr(bco,pc++)));
1378 PushTaggedInt64(bcoConstInt64(bco,bcoInstr(bco,pc++)));
1381 case i_RETURN_INT64:
1383 ASSERT(0); /* ToDo(); */
1388 StgClosure* o = stgCast(StgClosure*,grabHpNonUpd(I64zh_sizeW));
1389 SET_HDR(o,&I64zh_con_info,??);
1390 ASSIGN_Int64(&payloadWord(o,0),PopTaggedInt64());
1392 fprintf(stderr,"\tBuilt ");
1393 printObj(stgCast(StgClosure*,o));
1395 PushPtr(stgCast(StgPtr,o));
1398 case i_UNPACK_INT64:
1400 StgClosure* con = stgCast(StgClosure*,stackPtr(0));
1401 /*ASSERT(isInt64Like(con)); */
1402 PushTaggedInt64(PK_Int64(&payloadWord(con,0)));
1406 #ifdef PROVIDE_INTEGER
1407 case i_CONST_INTEGER:
1409 char* s = bcoConstAddr(bco,bcoInstr(bco,pc++));
1410 mpz_ptr r = mpz_alloc();
1411 if (s[0] == '0' && s[1] == 'x') {
1412 mpz_set_str(r,s+2,16);
1414 mpz_set_str(r,s,10);
1416 PushTaggedInteger(r);
1424 PushTaggedWord(taggedStackWord(bcoInstr(bco,pc++)));
1429 PushTaggedWord(bcoConstWord(bco,bcoInstr(bco,pc++)));
1439 StgClosure* o = stgCast(StgClosure*,grabHpNonUpd(Wzh_sizeW));
1441 SET_HDR(o,&Wzh_con_info,??);
1442 payloadWord(o,0) = PopTaggedWord();
1444 fprintf(stderr,"\tBuilt ");
1445 printObj(stgCast(StgClosure*,o));
1447 PushPtr(stgCast(StgPtr,o));
1452 StgClosure* con = stgCast(StgClosure*,stackPtr(0));
1453 /* ASSERT(isWordLike(con)); */
1454 PushTaggedWord(payloadWord(con,0));
1461 PushTaggedAddr(taggedStackAddr(bcoInstr(bco,pc++)));
1466 PushTaggedAddr(bcoConstAddr(bco,bcoInstr(bco,pc++)));
1476 StgClosure* o = stgCast(StgClosure*,grabHpNonUpd(Azh_sizeW));
1477 SET_HDR(o,&Azh_con_info,??);
1478 payloadPtr(o,0) = PopTaggedAddr();
1480 fprintf(stderr,"\tBuilt ");
1481 printObj(stgCast(StgClosure*,o));
1483 PushPtr(stgCast(StgPtr,o));
1488 StgClosure* con = stgCast(StgClosure*,stackPtr(0));
1489 /* ASSERT(isAddrLike(con)); */
1490 PushTaggedAddr(payloadPtr(con,0));
1496 PushTaggedChar(taggedStackChar(bcoInstr(bco,pc++)));
1501 PushTaggedChar(bcoConstChar(bco,bcoInstr(bco,pc++)));
1511 StgClosure* o = stgCast(StgClosure*,grabHpNonUpd(Czh_sizeW));
1512 SET_HDR(o,&Czh_con_info,??);
1513 payloadWord(o,0) = PopTaggedChar();
1514 PushPtr(stgCast(StgPtr,o));
1516 fprintf(stderr,"\tBuilt ");
1517 printObj(stgCast(StgClosure*,o));
1523 StgClosure* con = stgCast(StgClosure*,stackPtr(0));
1524 /* ASSERT(isCharLike(con)); */
1525 PushTaggedChar(payloadWord(con,0));
1530 PushTaggedFloat(taggedStackFloat(bcoInstr(bco,pc++)));
1535 PushTaggedFloat(bcoConstFloat(bco,bcoInstr(bco,pc++)));
1538 case i_RETURN_FLOAT:
1545 StgClosure* o = stgCast(StgClosure*,grabHpNonUpd(Fzh_sizeW));
1546 SET_HDR(o,&Fzh_con_info,??);
1547 ASSIGN_FLT(&payloadWord(o,0),PopTaggedFloat());
1549 fprintf(stderr,"\tBuilt ");
1550 printObj(stgCast(StgClosure*,o));
1552 PushPtr(stgCast(StgPtr,o));
1555 case i_UNPACK_FLOAT:
1557 StgClosure* con = stgCast(StgClosure*,stackPtr(0));
1558 /* ASSERT(isFloatLike(con)); */
1559 PushTaggedFloat(PK_FLT(&payloadWord(con,0)));
1564 PushTaggedDouble(taggedStackDouble(bcoInstr(bco,pc++)));
1567 case i_CONST_DOUBLE:
1569 PushTaggedDouble(bcoConstDouble(bco,bcoInstr(bco,pc++)));
1572 case i_RETURN_DOUBLE:
1579 StgClosure* o = stgCast(StgClosure*,grabHpNonUpd(Dzh_sizeW));
1580 SET_HDR(o,&Dzh_con_info,??);
1581 ASSIGN_DBL(&payloadWord(o,0),PopTaggedDouble());
1583 fprintf(stderr,"\tBuilt ");
1584 printObj(stgCast(StgClosure*,o));
1586 PushPtr(stgCast(StgPtr,o));
1589 case i_UNPACK_DOUBLE:
1591 StgClosure* con = stgCast(StgClosure*,stackPtr(0));
1592 /* ASSERT(isDoubleLike(con)); */
1593 PushTaggedDouble(PK_DBL(&payloadWord(con,0)));
1596 #ifdef PROVIDE_STABLE
1599 PushTaggedStablePtr(taggedStackStable(bcoInstr(bco,pc++)));
1602 case i_RETURN_STABLE:
1609 StgClosure* o = stgCast(StgClosure*,grabHpNonUpd(Stablezh_sizeW));
1610 SET_HDR(o,&StablePtr_con_info,??);
1611 payloadWord(o,0) = PopTaggedStablePtr();
1613 fprintf(stderr,"\tBuilt ");
1614 printObj(stgCast(StgClosure*,o));
1616 PushPtr(stgCast(StgPtr,o));
1619 case i_UNPACK_STABLE:
1621 StgClosure* con = stgCast(StgClosure*,stackPtr(0));
1622 /* ASSERT(isStableLike(con)); */
1623 PushTaggedStablePtr(payloadWord(con,0));
1629 switch (bcoInstr(bco,pc++)) {
1630 case i_INTERNAL_ERROR1:
1631 barf("INTERNAL_ERROR1 at %p:%d",bco,pc-1);
1633 case i_gtChar: OP_CC_B(x>y); break;
1634 case i_geChar: OP_CC_B(x>=y); break;
1635 case i_eqChar: OP_CC_B(x==y); break;
1636 case i_neChar: OP_CC_B(x!=y); break;
1637 case i_ltChar: OP_CC_B(x<y); break;
1638 case i_leChar: OP_CC_B(x<=y); break;
1639 case i_charToInt: OP_C_I(x); break;
1640 case i_intToChar: OP_I_C(x); break;
1642 case i_gtInt: OP_II_B(x>y); break;
1643 case i_geInt: OP_II_B(x>=y); break;
1644 case i_eqInt: OP_II_B(x==y); break;
1645 case i_neInt: OP_II_B(x!=y); break;
1646 case i_ltInt: OP_II_B(x<y); break;
1647 case i_leInt: OP_II_B(x<=y); break;
1648 case i_minInt: OP__I(INT_MIN); break;
1649 case i_maxInt: OP__I(INT_MAX); break;
1650 case i_plusInt: OP_II_I(x+y); break;
1651 case i_minusInt: OP_II_I(x-y); break;
1652 case i_timesInt: OP_II_I(x*y); break;
1655 int x = PopTaggedInt();
1656 int y = PopTaggedInt();
1658 obj = raiseDiv0("quotInt");
1661 /* ToDo: protect against minInt / -1 errors
1662 * (repeat for all other division primops)
1669 int x = PopTaggedInt();
1670 int y = PopTaggedInt();
1672 obj = raiseDiv0("remInt");
1680 StgInt x = PopTaggedInt();
1681 StgInt y = PopTaggedInt();
1683 obj = raiseDiv0("quotRemInt");
1686 PushTaggedInt(x%y); /* last result */
1687 PushTaggedInt(x/y); /* first result */
1690 case i_negateInt: OP_I_I(-x); break;
1692 case i_andInt: OP_II_I(x&y); break;
1693 case i_orInt: OP_II_I(x|y); break;
1694 case i_xorInt: OP_II_I(x^y); break;
1695 case i_notInt: OP_I_I(~x); break;
1696 case i_shiftLInt: OP_IW_I(x<<y); break;
1697 case i_shiftRAInt: OP_IW_I(x>>y); break; /* ToDo */
1698 case i_shiftRLInt: OP_IW_I(x>>y); break; /* ToDo */
1700 #ifdef PROVIDE_INT64
1701 case i_gtInt64: OP_zz_B(x>y); break;
1702 case i_geInt64: OP_zz_B(x>=y); break;
1703 case i_eqInt64: OP_zz_B(x==y); break;
1704 case i_neInt64: OP_zz_B(x!=y); break;
1705 case i_ltInt64: OP_zz_B(x<y); break;
1706 case i_leInt64: OP_zz_B(x<=y); break;
1707 case i_minInt64: OP__z(0x800000000000LL); break;
1708 case i_maxInt64: OP__z(0x7fffffffffffLL); break;
1709 case i_plusInt64: OP_zz_z(x+y); break;
1710 case i_minusInt64: OP_zz_z(x-y); break;
1711 case i_timesInt64: OP_zz_z(x*y); break;
1714 StgInt64 x = PopTaggedInt64();
1715 StgInt64 y = PopTaggedInt64();
1717 obj = raiseDiv0("quotInt64");
1720 /* ToDo: protect against minInt64 / -1 errors
1721 * (repeat for all other division primops)
1723 PushTaggedInt64(x/y);
1728 StgInt64 x = PopTaggedInt64();
1729 StgInt64 y = PopTaggedInt64();
1731 obj = raiseDiv0("remInt64");
1734 PushTaggedInt64(x%y);
1737 case i_quotRemInt64:
1739 StgInt64 x = PopTaggedInt64();
1740 StgInt64 y = PopTaggedInt64();
1742 obj = raiseDiv0("quotRemInt64");
1745 PushTaggedInt64(x%y); /* last result */
1746 PushTaggedInt64(x/y); /* first result */
1749 case i_negateInt64: OP_z_z(-x); break;
1751 case i_andInt64: OP_zz_z(x&y); break;
1752 case i_orInt64: OP_zz_z(x|y); break;
1753 case i_xorInt64: OP_zz_z(x^y); break;
1754 case i_notInt64: OP_z_z(~x); break;
1755 case i_shiftLInt64: OP_zW_z(x<<y); break;
1756 case i_shiftRAInt64: OP_zW_z(x>>y); break; /* ToDo */
1757 case i_shiftRLInt64: OP_zW_z(x>>y); break; /* ToDo */
1759 case i_int64ToInt: OP_z_I(x); break;
1760 case i_intToInt64: OP_I_z(x); break;
1762 case i_int64ToWord: OP_z_W(x); break;
1763 case i_wordToInt64: OP_W_z(x); break;
1765 case i_int64ToFloat: OP_z_F(x); break;
1766 case i_floatToInt64: OP_F_z(x); break;
1767 case i_int64ToDouble: OP_z_D(x); break;
1768 case i_doubleToInt64: OP_D_z(x); break;
1771 case i_gtWord: OP_WW_B(x>y); break;
1772 case i_geWord: OP_WW_B(x>=y); break;
1773 case i_eqWord: OP_WW_B(x==y); break;
1774 case i_neWord: OP_WW_B(x!=y); break;
1775 case i_ltWord: OP_WW_B(x<y); break;
1776 case i_leWord: OP_WW_B(x<=y); break;
1777 case i_minWord: OP__W(0); break;
1778 case i_maxWord: OP__W(UINT_MAX); break;
1779 case i_plusWord: OP_WW_W(x+y); break;
1780 case i_minusWord: OP_WW_W(x-y); break;
1781 case i_timesWord: OP_WW_W(x*y); break;
1784 StgWord x = PopTaggedWord();
1785 StgWord y = PopTaggedWord();
1787 obj = raiseDiv0("quotWord");
1790 PushTaggedWord(x/y);
1795 StgWord x = PopTaggedWord();
1796 StgWord y = PopTaggedWord();
1798 obj = raiseDiv0("remWord");
1801 PushTaggedWord(x%y);
1806 StgWord x = PopTaggedWord();
1807 StgWord y = PopTaggedWord();
1809 obj = raiseDiv0("quotRemWord");
1812 PushTaggedWord(x%y); /* last result */
1813 PushTaggedWord(x/y); /* first result */
1816 case i_negateWord: OP_W_W(-x); break;
1817 case i_andWord: OP_WW_W(x&y); break;
1818 case i_orWord: OP_WW_W(x|y); break;
1819 case i_xorWord: OP_WW_W(x^y); break;
1820 case i_notWord: OP_W_W(~x); break;
1821 case i_shiftLWord: OP_WW_W(x<<y); break;
1822 case i_shiftRAWord: OP_WW_W(x>>y); break; /* ToDo */
1823 case i_shiftRLWord: OP_WW_W(x>>y); break; /* ToDo */
1824 case i_intToWord: OP_I_W(x); break;
1825 case i_wordToInt: OP_W_I(x); break;
1828 case i_gtAddr: OP_AA_B(x>y); break;
1829 case i_geAddr: OP_AA_B(x>=y); break;
1830 case i_eqAddr: OP_AA_B(x==y); break;
1831 case i_neAddr: OP_AA_B(x!=y); break;
1832 case i_ltAddr: OP_AA_B(x<y); break;
1833 case i_leAddr: OP_AA_B(x<=y); break;
1834 case i_intToAddr: OP_I_A((StgAddr)x); break; /* ToDo */
1835 case i_addrToInt: OP_A_I((StgInt)x); break; /* ToDo */
1837 case i_indexCharOffAddr: OP_AI_C(indexCharOffAddrzh(r,x,y)); break;
1838 case i_readCharOffAddr: OP_AI_C(indexCharOffAddrzh(r,x,y)); break;
1839 case i_writeCharOffAddr: OP_AIC_(writeCharOffAddrzh(x,y,z)); break;
1841 case i_indexIntOffAddr: OP_AI_I(indexIntOffAddrzh(r,x,y)); break;
1842 case i_readIntOffAddr: OP_AI_I(indexIntOffAddrzh(r,x,y)); break;
1843 case i_writeIntOffAddr: OP_AII_(writeIntOffAddrzh(x,y,z)); break;
1844 #ifdef PROVIDE_INT64
1845 case i_indexInt64OffAddr: OP_AI_z(indexInt64OffAddrzh(r,x,y)); break;
1846 case i_readInt64OffAddr: OP_AI_z(indexInt64OffAddrzh(r,x,y)); break;
1847 case i_writeInt64OffAddr: OP_AIz_(writeInt64OffAddrzh(x,y,z)); break;
1850 case i_indexAddrOffAddr: OP_AI_A(indexAddrOffAddrzh(r,x,y)); break;
1851 case i_readAddrOffAddr: OP_AI_A(indexAddrOffAddrzh(r,x,y)); break;
1852 case i_writeAddrOffAddr: OP_AIA_(writeAddrOffAddrzh(x,y,z)); break;
1854 case i_indexFloatOffAddr: OP_AI_F(indexFloatOffAddrzh(r,x,y)); break;
1855 case i_readFloatOffAddr: OP_AI_F(indexFloatOffAddrzh(r,x,y)); break;
1856 case i_writeFloatOffAddr: OP_AIF_(writeFloatOffAddrzh(x,y,z)); break;
1858 case i_indexDoubleOffAddr: OP_AI_D(indexDoubleOffAddrzh(r,x,y)); break;
1859 case i_readDoubleOffAddr: OP_AI_D(indexDoubleOffAddrzh(r,x,y)); break;
1860 case i_writeDoubleOffAddr: OP_AID_(writeDoubleOffAddrzh(x,y,z)); break;
1862 #ifdef PROVIDE_STABLE
1863 case i_indexStableOffAddr: OP_AI_s(indexStablePtrOffAddrzh(r,x,y)); break;
1864 case i_readStableOffAddr: OP_AI_s(indexStablePtrOffAddrzh(r,x,y)); break;
1865 case i_writeStableOffAddr: OP_AIs_(writeStablePtrOffAddrzh(x,y,z)); break;
1868 #endif /* PROVIDE_ADDR */
1870 #ifdef PROVIDE_INTEGER
1871 case i_compareInteger:
1873 mpz_ptr x = PopTaggedInteger();
1874 mpz_ptr y = PopTaggedInteger();
1875 StgInt r = mpz_cmp(x,y);
1876 PushTaggedInt(r<0 ? -1 : (r>0 ? 1 : 0));
1879 case i_negateInteger: OP_Z_Z(mpz_neg(r,x)); break;
1880 case i_plusInteger: OP_ZZ_Z(mpz_add(r,x,y)); break;
1881 case i_minusInteger: OP_ZZ_Z(mpz_sub(r,x,y)); break;
1882 case i_timesInteger: OP_ZZ_Z(mpz_mul(r,x,y)); break;
1883 case i_quotRemInteger:
1885 mpz_ptr x = PopTaggedInteger();
1886 mpz_ptr y = PopTaggedInteger();
1887 mpz_ptr q = mpz_alloc();
1888 mpz_ptr r = mpz_alloc();
1889 if (mpz_sgn(y) == 0) {
1890 obj = raiseDiv0("quotRemInteger");
1893 mpz_tdiv_qr(q,r,x,y);
1894 PushTaggedInteger(r); /* last result */
1895 PushTaggedInteger(q); /* first result */
1898 case i_divModInteger:
1900 mpz_ptr x = PopTaggedInteger();
1901 mpz_ptr y = PopTaggedInteger();
1902 mpz_ptr q = mpz_alloc();
1903 mpz_ptr r = mpz_alloc();
1904 if (mpz_sgn(y) == 0) {
1905 obj = raiseDiv0("divModInteger");
1908 mpz_fdiv_qr(q,r,x,y);
1909 PushTaggedInteger(r); /* last result */
1910 PushTaggedInteger(q); /* first result */
1913 case i_integerToInt: OP_Z_I(mpz_get_si(x)); break;
1914 case i_intToInteger: OP_I_Z(mpz_set_si(r,x)); break;
1915 #ifdef PROVIDE_INT64
1916 case i_integerToInt64: OP_Z_z(mpz_get_si(x)); break;
1917 case i_int64ToInteger: OP_z_Z(mpz_set_si(r,x)); break;
1920 /* NB Use of mpz_get_si is quite deliberate since otherwise
1921 * -255 is converted to 255.
1923 case i_integerToWord: OP_Z_W(mpz_get_si(x)); break;
1924 case i_wordToInteger: OP_W_Z(mpz_set_ui(r,x)); break;
1926 case i_integerToFloat: OP_Z_F(mpz_get_d(x)); break;
1927 case i_floatToInteger: OP_F_Z(mpz_set_d(r,x)); break;
1928 case i_integerToDouble: OP_Z_D(mpz_get_d(x)); break;
1929 case i_doubleToInteger: OP_D_Z(mpz_set_d(r,x)); break;
1930 #endif /* PROVIDE_INTEGER */
1932 case i_gtFloat: OP_FF_B(x>y); break;
1933 case i_geFloat: OP_FF_B(x>=y); break;
1934 case i_eqFloat: OP_FF_B(x==y); break;
1935 case i_neFloat: OP_FF_B(x!=y); break;
1936 case i_ltFloat: OP_FF_B(x<y); break;
1937 case i_leFloat: OP_FF_B(x<=y); break;
1938 case i_minFloat: OP__F(FLT_MIN); break;
1939 case i_maxFloat: OP__F(FLT_MAX); break;
1940 case i_radixFloat: OP__I(FLT_RADIX); break;
1941 case i_digitsFloat: OP__I(FLT_MANT_DIG); break;
1942 case i_minExpFloat: OP__I(FLT_MIN_EXP); break;
1943 case i_maxExpFloat: OP__I(FLT_MAX_EXP); break;
1944 case i_plusFloat: OP_FF_F(x+y); break;
1945 case i_minusFloat: OP_FF_F(x-y); break;
1946 case i_timesFloat: OP_FF_F(x*y); break;
1949 StgFloat x = PopTaggedFloat();
1950 StgFloat y = PopTaggedFloat();
1953 obj = raiseDiv0("divideFloat");
1957 PushTaggedFloat(x/y);
1960 case i_negateFloat: OP_F_F(-x); break;
1961 case i_floatToInt: OP_F_I(x); break;
1962 case i_intToFloat: OP_I_F(x); break;
1963 case i_expFloat: OP_F_F(exp(x)); break;
1964 case i_logFloat: OP_F_F(log(x)); break;
1965 case i_sqrtFloat: OP_F_F(sqrt(x)); break;
1966 case i_sinFloat: OP_F_F(sin(x)); break;
1967 case i_cosFloat: OP_F_F(cos(x)); break;
1968 case i_tanFloat: OP_F_F(tan(x)); break;
1969 case i_asinFloat: OP_F_F(asin(x)); break;
1970 case i_acosFloat: OP_F_F(acos(x)); break;
1971 case i_atanFloat: OP_F_F(atan(x)); break;
1972 case i_sinhFloat: OP_F_F(sinh(x)); break;
1973 case i_coshFloat: OP_F_F(cosh(x)); break;
1974 case i_tanhFloat: OP_F_F(tanh(x)); break;
1975 case i_powerFloat: OP_FF_F(pow(x,y)); break;
1977 #ifdef PROVIDE_INT64
1978 /* Based on old Hugs code */
1979 /* ToDo: use ~/fptools/ghc/runtime/prims/PrimArith.lc */
1980 case i_encodeFloatz: OP_zI_F(ldexp(x,y)); break;
1981 case i_decodeFloatz:
1983 /* ToDo: this code is known to give very approximate results
1984 * (even when StgInt64 overflow doesn't occur)
1986 double f0 = PopTaggedFloat();
1988 double f1 = frexp((double)(f0),&n); /* 0.5 <= f1 < 1 */
1989 double f2 = ldexp(f1,FLT_MANT_DIG); /* 2^m-1 <= f2 < 2^m, m=FLT_MANT_DIG */
1990 PushTaggedInt(n-FLT_MANT_DIG);
1991 PushTaggedInt64((StgInt64)f2);
1992 #if 1 /* paranoia */
1993 if (ldexp((StgInt64)f2,n-FLT_MANT_DIG) != f0) {
1994 fprintf(stderr,"*** primDecodeFloat mismatch: %.10f != %.10f\n",
1995 ldexp((StgInt64)f2,n-FLT_MANT_DIG),f0);
2000 #endif /* PROVIDE_INT64 */
2001 #ifdef PROVIDE_INTEGER
2002 case i_encodeFloatZ: OP_ZI_F(__encodeFloat(x,y)); break;
2003 case i_decodeFloatZ: OP_F_ZI(__decodeFloat(r1,&r2,x)); break;
2005 case i_isNaNFloat: OP_F_B(isFloatNaN(x)); break;
2006 case i_isInfiniteFloat: OP_F_B(isFloatInfinite(x)); break;
2007 case i_isNegativeZeroFloat: OP_F_B(isFloatNegativeZero(x)); break;
2008 case i_isDenormalizedFloat: OP_F_B(isFloatDenormalized(x)); break;
2009 case i_gtDouble: OP_DD_B(x>y); break;
2010 case i_geDouble: OP_DD_B(x>=y); break;
2011 case i_eqDouble: OP_DD_B(x==y); break;
2012 case i_neDouble: OP_DD_B(x!=y); break;
2013 case i_ltDouble: OP_DD_B(x<y); break;
2014 case i_leDouble: OP_DD_B(x<=y) break;
2015 case i_minDouble: OP__D(DBL_MIN); break;
2016 case i_maxDouble: OP__D(DBL_MAX); break;
2017 case i_radixDouble: OP__I(FLT_RADIX); break;
2018 case i_digitsDouble: OP__I(DBL_MANT_DIG); break;
2019 case i_minExpDouble: OP__I(DBL_MIN_EXP); break;
2020 case i_maxExpDouble: OP__I(DBL_MAX_EXP); break;
2021 case i_plusDouble: OP_DD_D(x+y); break;
2022 case i_minusDouble: OP_DD_D(x-y); break;
2023 case i_timesDouble: OP_DD_D(x*y); break;
2024 case i_divideDouble:
2026 StgDouble x = PopTaggedDouble();
2027 StgDouble y = PopTaggedDouble();
2030 obj = raiseDiv0("divideDouble");
2034 PushTaggedDouble(x/y);
2037 case i_negateDouble: OP_D_D(-x); break;
2038 case i_doubleToInt: OP_D_I(x); break;
2039 case i_intToDouble: OP_I_D(x); break;
2040 case i_doubleToFloat: OP_D_F(x); break;
2041 case i_floatToDouble: OP_F_F(x); break;
2042 case i_expDouble: OP_D_D(exp(x)); break;
2043 case i_logDouble: OP_D_D(log(x)); break;
2044 case i_sqrtDouble: OP_D_D(sqrt(x)); break;
2045 case i_sinDouble: OP_D_D(sin(x)); break;
2046 case i_cosDouble: OP_D_D(cos(x)); break;
2047 case i_tanDouble: OP_D_D(tan(x)); break;
2048 case i_asinDouble: OP_D_D(asin(x)); break;
2049 case i_acosDouble: OP_D_D(acos(x)); break;
2050 case i_atanDouble: OP_D_D(atan(x)); break;
2051 case i_sinhDouble: OP_D_D(sinh(x)); break;
2052 case i_coshDouble: OP_D_D(cosh(x)); break;
2053 case i_tanhDouble: OP_D_D(tanh(x)); break;
2054 case i_powerDouble: OP_DD_D(pow(x,y)); break;
2055 #ifdef PROVIDE_INT64
2056 case i_encodeDoublez: OP_zI_D(ldexp(x,y)); break;
2057 case i_decodeDoublez:
2059 /* ToDo: this code is known to give very approximate results
2060 * (even when StgInt64 overflow doesn't occur)
2062 double f0 = PopTaggedDouble();
2064 double f1 = frexp((double)(f0),&n); /* 0.5 <= f1 < 1 */
2065 double f2 = ldexp(f1,FLT_MANT_DIG); /* 2^m-1 <= f2 < 2^m, m=FLT_MANT_DIG */
2066 PushTaggedInt(n-FLT_MANT_DIG);
2067 PushTaggedInt64((StgInt64)f2);
2068 #if 1 /* paranoia */
2069 if (ldexp((StgInt64)f2,n-FLT_MANT_DIG) != f0) {
2070 fprintf(stderr,"*** primDecodeDouble mismatch: %.10f != %.10f\n",
2071 ldexp((StgInt64)f2,n-FLT_MANT_DIG),f0);
2076 #endif /* PROVIDE_INT64 */
2077 #ifdef PROVIDE_INTEGER
2078 case i_encodeDoubleZ: OP_ZI_D(__encodeDouble(x,y)); break;
2079 case i_decodeDoubleZ: OP_D_ZI(__decodeDouble(r1,&r2,x)); break;
2080 #endif /* PROVIDE_INTEGER */
2081 case i_isNaNDouble: OP_D_B(isDoubleNaN(x)); break;
2082 case i_isInfiniteDouble: OP_D_B(isDoubleInfinite(x)); break;
2083 case i_isNegativeZeroDouble: OP_D_B(isDoubleNegativeZero(x)); break;
2084 case i_isDenormalizedDouble: OP_D_B(isDoubleDenormalized(x)); break;
2085 case i_isIEEEDouble:
2087 PushTaggedBool(rtsTrue);
2091 barf("Unrecognised primop1");
2097 switch (bcoInstr(bco,pc++)) {
2098 case i_INTERNAL_ERROR2:
2099 barf("INTERNAL_ERROR2 at %p:%d",bco,pc-1);
2100 case i_catch: /* catch#{e,h} */
2106 /* catch suffers the same problem as takeMVar:
2107 * it tries to do control flow even if it isn't
2108 * the last instruction in the BCO.
2109 * This can leave a mess on the stack if the
2110 * last instructions are anything important
2111 * like SLIDE. Our vile hack depends on the
2112 * fact that with the current code generator,
2113 * we know exactly that i_catch is followed
2114 * by code that drops 2 variables off the
2123 case i_raise: /* raise#{err} */
2125 StgClosure* err = PopCPtr();
2126 obj = raiseAnError(err);
2129 case i_force: /* force#{x} (evaluate x, primreturn nothing) */
2134 /* force suffers the same problem as takeMVar:
2135 * it tries to do control flow even if it isn't
2136 * the last instruction in the BCO.
2137 * This can leave a mess on the stack if the
2138 * last instructions are anything important
2139 * like SLIDE. Our vile hack depends on the
2140 * fact that with the current code generator,
2141 * we know exactly that i_force is followed
2142 * by code that drops 1 variable off the stack.
2150 #ifdef PROVIDE_ARRAY
2153 StgClosure* init = PopCPtr();
2155 = stgCast(StgMutVar*,allocate(sizeofW(StgMutVar)));
2156 SET_HDR(mv,&MUT_VAR_info,CCCS);
2158 PushPtr(stgCast(StgPtr,mv));
2163 StgMutVar* mv = stgCast(StgMutVar*,PopPtr());
2169 StgMutVar* mv = stgCast(StgMutVar*,PopPtr());
2170 StgClosure* value = PopCPtr();
2176 nat n = PopTaggedInt(); /* or Word?? */
2177 StgClosure* init = PopCPtr();
2178 StgWord size = sizeofW(StgArrPtrs) + n;
2181 = stgCast(StgArrPtrs*,allocate(size));
2182 SET_HDR(arr,&MUT_ARR_PTRS_info,CCCS);
2184 for (i = 0; i < n; ++i) {
2185 arr->payload[i] = init;
2187 PushPtr(stgCast(StgPtr,arr));
2193 StgArrPtrs* arr = stgCast(StgArrPtrs*,PopPtr());
2194 nat i = PopTaggedInt(); /* or Word?? */
2195 StgWord n = arr->ptrs;
2197 obj = raiseIndex("{index,read}Array");
2200 PushCPtr(arr->payload[i]);
2205 StgArrPtrs* arr = stgCast(StgArrPtrs*,PopPtr());
2206 nat i = PopTaggedInt(); /* or Word? */
2207 StgClosure* v = PopCPtr();
2208 StgWord n = arr->ptrs;
2210 obj = raiseIndex("{index,read}Array");
2213 arr->payload[i] = v;
2217 case i_sizeMutableArray:
2219 StgArrPtrs* arr = stgCast(StgArrPtrs*,PopPtr());
2220 PushTaggedInt(arr->ptrs);
2223 case i_unsafeFreezeArray:
2225 StgArrPtrs* arr = stgCast(StgArrPtrs*,PopPtr());
2226 SET_INFO(arr,&MUT_ARR_PTRS_FROZEN_info);
2227 PushPtr(stgCast(StgPtr,arr));
2230 case i_unsafeFreezeByteArray:
2232 /* Delightfully simple :-) */
2236 case i_sameMutableArray:
2237 case i_sameMutableByteArray:
2239 StgPtr x = PopPtr();
2240 StgPtr y = PopPtr();
2241 PushTaggedBool(x==y);
2245 case i_newByteArray:
2247 nat n = PopTaggedInt(); /* or Word?? */
2248 StgInt words = (n+sizeof(W_)-1)/sizeof(W_);
2249 StgWord size = sizeofW(StgArrWords) + words;
2251 StgArrWords* arr = stgCast(StgArrWords*,allocate(size));
2252 SET_HDR(arr,&MUT_ARR_WORDS_info,CCCS);
2255 for (i = 0; i < n; ++i) {
2256 arr->payload[i] = 0xdeadbeef;
2259 PushPtr(stgCast(StgPtr,arr));
2263 /* Most of these generate alignment warnings on Sparcs and similar architectures.
2264 * These are harmless and are caused by the cast to C* in BYTE_ARR_CTS.
2266 case i_indexCharArray: OP_mI_ty(Char,"indexCharArray", indexCharArrayzh(r,x,i)); break;
2267 case i_readCharArray: OP_mI_ty(Char,"readCharArray", readCharArrayzh(r,x,i)); break;
2268 case i_writeCharArray: OP_mIty_(Char,"writeCharArray", writeCharArrayzh(x,i,z)); break;
2270 case i_indexIntArray: OP_mI_ty(Int,"indexIntArray", indexIntArrayzh(r,x,i)); break;
2271 case i_readIntArray: OP_mI_ty(Int,"readIntArray", readIntArrayzh(r,x,i)); break;
2272 case i_writeIntArray: OP_mIty_(Int,"writeIntArray", writeIntArrayzh(x,i,z)); break;
2273 #ifdef PROVIDE_INT64
2274 case i_indexInt64Array: OP_mI_ty(Int64,"indexInt64Array", indexInt64Arrayzh(r,x,i)); break;
2275 case i_readInt64Array: OP_mI_ty(Int64,"readInt64Array", readInt64Arrayzh(r,x,i)); break;
2276 case i_writeInt64Array: OP_mIty_(Int64,"writeInt64Array", writeInt64Arrayzh(x,i,z)); break;
2279 case i_indexAddrArray: OP_mI_ty(Addr,"indexAddrArray", indexAddrArrayzh(r,x,i)); break;
2280 case i_readAddrArray: OP_mI_ty(Addr,"readAddrArray", readAddrArrayzh(r,x,i)); break;
2281 case i_writeAddrArray: OP_mIty_(Addr,"writeAddrArray", writeAddrArrayzh(x,i,z)); break;
2283 case i_indexFloatArray: OP_mI_ty(Float,"indexFloatArray", indexFloatArrayzh(r,x,i)); break;
2284 case i_readFloatArray: OP_mI_ty(Float,"readFloatArray", readFloatArrayzh(r,x,i)); break;
2285 case i_writeFloatArray: OP_mIty_(Float,"writeFloatArray", writeFloatArrayzh(x,i,z)); break;
2287 case i_indexDoubleArray: OP_mI_ty(Double,"indexDoubleArray", indexDoubleArrayzh(r,x,i)); break;
2288 case i_readDoubleArray: OP_mI_ty(Double,"readDoubleArray", readDoubleArrayzh(r,x,i)); break;
2289 case i_writeDoubleArray: OP_mIty_(Double,"writeDoubleArray", writeDoubleArrayzh(x,i,z)); break;
2291 #ifdef PROVIDE_STABLE
2292 case i_indexStableArray: OP_mI_ty(StablePtr,"indexStableArray", indexStablePtrArrayzh(r,x,i)); break;
2293 case i_readStableArray: OP_mI_ty(StablePtr,"readStableArray", readStablePtrArrayzh(r,x,i)); break;
2294 case i_writeStableArray: OP_mIty_(StablePtr,"writeStableArray", writeStablePtrArrayzh(x,i,z)); break;
2297 #endif /* PROVIDE_ARRAY */
2298 #ifdef PROVIDE_COERCE
2299 case i_unsafeCoerce:
2301 /* Another nullop */
2305 #ifdef PROVIDE_PTREQUALITY
2306 case i_reallyUnsafePtrEquality:
2307 { /* identical to i_sameRef */
2308 StgPtr x = PopPtr();
2309 StgPtr y = PopPtr();
2310 PushTaggedBool(x==y);
2314 #ifdef PROVIDE_FOREIGN
2315 /* ForeignObj# operations */
2316 case i_makeForeignObj:
2318 StgForeignObj *result
2319 = stgCast(StgForeignObj*,allocate(sizeofW(StgForeignObj)));
2320 SET_HDR(result,&FOREIGN_info,CCCS);
2321 result -> data = PopTaggedAddr();
2322 PushPtr(stgCast(StgPtr,result));
2325 #endif /* PROVIDE_FOREIGN */
2330 = stgCast(StgWeak*,allocate(sizeofW(StgWeak)));
2331 SET_HDR(w, &WEAK_info, CCCS);
2333 w->value = PopCPtr();
2334 w->finaliser = PopCPtr();
2335 w->link = weak_ptr_list;
2337 IF_DEBUG(weak, fprintf(stderr,"New weak pointer at %p\n",w));
2338 PushPtr(stgCast(StgPtr,w));
2343 StgWeak *w = stgCast(StgWeak*,PopPtr());
2344 if (w->header.info == &WEAK_info) {
2345 PushCPtr(w->value); /* last result */
2346 PushTaggedInt(1); /* first result */
2348 PushPtr(stgCast(StgPtr,w)); /* ToDo: error thunk would be better */
2353 #endif /* PROVIDE_WEAK */
2354 #ifdef PROVIDE_STABLE
2355 /* StablePtr# operations */
2356 case i_makeStablePtr:
2358 StgStablePtr stable_ptr;
2359 if (stable_ptr_free == NULL) {
2360 enlargeStablePtrTable();
2363 stable_ptr = stable_ptr_free - stable_ptr_table;
2364 stable_ptr_free = (P_*)*stable_ptr_free;
2365 stable_ptr_table[stable_ptr] = PopPtr();
2367 PushTaggedStablePtr(stable_ptr);
2370 case i_deRefStablePtr:
2372 StgStablePtr stable_ptr = PopTaggedStablePtr();
2373 PushPtr(stable_ptr_table[stable_ptr]);
2377 case i_freeStablePtr:
2379 StgStablePtr stable_ptr = PopTaggedStablePtr();
2380 stable_ptr_table[stable_ptr] = (P_)stable_ptr_free;
2381 stable_ptr_free = stable_ptr_table + stable_ptr;
2384 #endif /* PROVIDE_STABLE */
2385 #ifdef PROVIDE_CONCURRENT
2388 StgClosure* c = PopCPtr();
2389 StgTSO* t = createGenThread(RtsFlags.GcFlags.initialStkSize,c);
2390 PushPtr(stgCast(StgPtr,t));
2392 /* switch at the earliest opportunity */
2394 /* but don't automatically switch to GHC - or you'll waste your
2395 * time slice switching back.
2397 * Actually, there's more to it than that: the default
2398 * (ThreadEnterGHC) causes the thread to crash - don't
2399 * understand why. - ADR
2401 t->whatNext = ThreadEnterHugs;
2406 StgTSO* tso = stgCast(StgTSO*,PopPtr());
2408 if (tso == CurrentTSO) { /* suicide */
2409 return ThreadFinished;
2414 { /* identical to i_sameRef */
2415 StgPtr x = PopPtr();
2416 StgPtr y = PopPtr();
2417 PushTaggedBool(x==y);
2422 StgMVar *mvar = stgCast(StgMVar*,allocate(sizeofW(StgMVar)));
2423 SET_INFO(mvar,&EMPTY_MVAR_info);
2424 mvar->head = mvar->tail = EndTSOQueue;
2425 /* ToDo: this is a little strange */
2426 mvar->value = stgCast(StgClosure*,&END_TSO_QUEUE_closure);
2427 PushPtr(stgCast(StgPtr,mvar));
2432 ToDo: another way out of the problem might be to add an explicit
2433 continuation to primTakeMVar: takeMVar v = primTakeMVar v takeMVar.
2434 The problem with this plan is that now I dont know how much to chop
2439 StgMVar *mvar = stgCast(StgMVar*,PopPtr());
2440 /* If the MVar is empty, put ourselves
2441 * on its blocking queue, and wait
2442 * until we're woken up.
2444 if (GET_INFO(mvar) != &FULL_MVAR_info) {
2445 if (mvar->head == EndTSOQueue) {
2446 mvar->head = CurrentTSO;
2448 mvar->tail->link = CurrentTSO;
2450 CurrentTSO->link = EndTSOQueue;
2451 mvar->tail = CurrentTSO;
2453 /* Hack, hack, hack.
2454 * When we block, we push a restart closure
2455 * on the stack - but which closure?
2456 * We happen to know that the BCO we're
2457 * executing looks like this:
2466 * 14: ALLOC_CONSTR 0x8213a80
2476 * so we rearrange the stack to look the
2477 * way it did when we entered this BCO
2479 * What a disgusting hack!
2485 return ThreadBlocked;
2488 PushCPtr(mvar->value);
2489 SET_INFO(mvar,&EMPTY_MVAR_info);
2490 /* ToDo: this is a little strange */
2491 mvar->value = (StgClosure*)&END_TSO_QUEUE_closure;
2498 StgMVar* mvar = stgCast(StgMVar*,PopPtr());
2499 StgClosure* value = PopCPtr();
2500 if (GET_INFO(mvar) == &FULL_MVAR_info) {
2501 obj = raisePrim("putMVar {full MVar}");
2504 /* wake up the first thread on the
2505 * queue, it will continue with the
2506 * takeMVar operation and mark the
2509 StgTSO* tso = mvar->head;
2510 SET_INFO(mvar,&FULL_MVAR_info);
2511 mvar->value = value;
2512 if (tso != EndTSOQueue) {
2513 PUSH_ON_RUN_QUEUE(tso);
2514 mvar->head = tso->link;
2515 tso->link = EndTSOQueue;
2516 if (mvar->head == EndTSOQueue) {
2517 mvar->tail = EndTSOQueue;
2521 /* yield for better communication performance */
2528 /* As PrimOps.h says: Hmm, I'll think about these later. */
2531 #endif /* PROVIDE_CONCURRENT */
2535 CFunDescriptor* descriptor = PopTaggedAddr();
2536 StgAddr funPtr = PopTaggedAddr();
2537 ccall(descriptor,funPtr);
2541 barf("Unrecognised primop2");
2546 barf("Unrecognised instruction");
2549 barf("Ran off the end of bco - yoiks");
2554 StgCAF* caf = stgCast(StgCAF*,obj);
2555 if (Sp - sizeofW(StgUpdateFrame) < SpLim) {
2556 PushCPtr(obj); /* code to restart with */
2557 return StackOverflow;
2559 /* ToDo: look for Sp==Su && stackInt(0) == UPD_FRAME and insert an indirection immediately */
2561 StgBlackHole* bh = stgCast(StgBlackHole*,grabHpUpd(BLACKHOLE_sizeW()));
2562 SET_INFO(bh,&CAF_BLACKHOLE_info);
2563 bh->blocking_queue = EndTSOQueue;
2564 IF_DEBUG(gccafs,fprintf(stderr,"Created CAF_BLACKHOLE %p for CAF %p in evaluator\n",bh,caf));
2565 SET_INFO(caf,&CAF_ENTERED_info);
2566 caf->value = stgCast(StgClosure*,bh);
2567 PUSH_UPD_FRAME(bh,0);
2568 Sp -= sizeofW(StgUpdateFrame);
2570 caf->link = enteredCAFs;
2577 StgCAF* caf = stgCast(StgCAF*,obj);
2578 obj = caf->value; /* it's just a fancy indirection */
2584 StgBlackHole* bh = stgCast(StgBlackHole*,obj);
2585 /* Put ourselves on the blocking queue for this black hole and block */
2586 CurrentTSO->link = bh->blocking_queue;
2587 bh->blocking_queue = CurrentTSO;
2588 PushCPtr(obj); /* code to restart with */
2589 return ThreadBlocked;
2593 StgAP_UPD* ap = stgCast(StgAP_UPD*,obj);
2595 if (Sp - (i + sizeofW(StgUpdateFrame)) < SpLim) {
2596 PushCPtr(obj); /* code to restart with */
2597 return StackOverflow;
2599 /* ToDo: look for Sp==Su && stackInt(0) == UPD_FRAME and insert an indirection immediately */
2600 PUSH_UPD_FRAME(ap,0);
2601 Sp -= sizeofW(StgUpdateFrame);
2603 PushWord(payloadWord(ap,i));
2606 #ifndef LAZY_BLACKHOLING
2608 /* superfluous - but makes debugging easier */
2609 StgBlackHole* bh = stgCast(StgBlackHole*,ap);
2610 SET_INFO(bh,&BLACKHOLE_info);
2611 bh->blocking_queue = EndTSOQueue;
2612 IF_DEBUG(gccafs,fprintf(stderr,"Eagerly blackholed AP_UPD %p in evaluator\n",bh));
2615 #endif /* LAZY_BLACKHOLING */
2620 StgPAP* pap = stgCast(StgPAP*,obj);
2621 int i = pap->n_args; /* ToDo: stack check */
2622 /* ToDo: if PAP is in whnf, we can update any update frames
2626 PushWord(payloadWord(pap,i));
2633 obj = stgCast(StgInd*,obj)->indirectee;
2637 case CONSTR_INTLIKE:
2638 case CONSTR_CHARLIKE:
2640 case CONSTR_NOCAF_STATIC:
2643 switch (get_itbl(stgCast(StgClosure*,Sp))->type) {
2648 PopUpdateFrame(obj);
2658 /*fprintf(stderr,"Sp = %p\tSu = %p\n", Sp, Su);*/
2659 /*printStack(Sp,CurrentTSO->stack+CurrentTSO->stack_size,Su);*/
2662 return ThreadFinished;
2673 case RET_SMALL: /* return to GHC */
2677 barf("todo: RET_[VEC_]{BIG,SMALL}");
2679 belch("entered CONSTR with invalid continuation on stack");
2681 printObj(stgCast(StgClosure*,Sp))
2683 barf("bailing out");
2689 CurrentTSO->whatNext = ThreadEnterGHC;
2690 PushCPtr(obj); /* code to restart with */
2691 return ThreadYielding;
2694 barf("Ran off the end of enter - yoiks");
2697 /* -----------------------------------------------------------------------------
2698 * ccall support code:
2699 * marshall moves args from C stack to Haskell stack
2700 * unmarshall moves args from Haskell stack to C stack
2701 * argSize calculates how much space you need on the C stack
2702 * ---------------------------------------------------------------------------*/
2704 /* Pop arguments off the C stack and Push them onto the Hugs stack.
2705 * Used when preparing for C calling Haskell or in response to
2706 * Haskell calling C.
2708 nat marshall(char arg_ty, void* arg)
2712 PushTaggedInt(*((int*)arg));
2713 return ARG_SIZE(INT_TAG);
2714 #ifdef PROVIDE_INT64
2716 PushTaggedInt64(*((StgInt64*)arg));
2717 return ARG_SIZE(INT64_TAG);
2719 #ifdef TODO_PROVIDE_INTEGER
2721 PushTaggedInteger(*((mpz_ptr*)arg));
2722 return ARG_SIZE(INTEGER_TAG);
2726 PushTaggedWord(*((unsigned int*)arg));
2727 return ARG_SIZE(WORD_TAG);
2730 PushTaggedChar(*((char*)arg));
2731 return ARG_SIZE(CHAR_TAG);
2733 PushTaggedFloat(*((float*)arg));
2734 return ARG_SIZE(FLOAT_TAG);
2736 PushTaggedDouble(*((double*)arg));
2737 return ARG_SIZE(DOUBLE_TAG);
2740 PushTaggedAddr(*((void**)arg));
2741 return ARG_SIZE(ADDR_TAG);
2744 PushTaggedStablePtr(*((StgStablePtr*)arg));
2745 return ARG_SIZE(STABLE_TAG);
2747 /* Not allowed in this direction - you have to
2748 * call makeForeignPtr explicitly
2750 barf("marshall: ForeignPtr#\n");
2752 #ifdef PROVIDE_ARRAY
2756 /* Not allowed in this direction */
2757 barf("marshall: [Mutable]ByteArray#\n");
2760 barf("marshall: unrecognised arg type %d\n",arg_ty);
2765 /* Pop arguments off the Hugs stack and Push them onto the C stack.
2766 * Used when preparing for Haskell calling C or in response to
2767 * C calling Haskell.
2769 nat unmarshall(char res_ty, void* res)
2773 *((int*)res) = PopTaggedInt();
2774 return ARG_SIZE(INT_TAG);
2775 #ifdef PROVIDE_INT64
2777 *((StgInt64*)res) = PopTaggedInt64();
2778 return ARG_SIZE(INT64_TAG);
2780 #ifdef TODO_PROVIDE_INTEGER
2782 *((mpz_ptr*)res) = PopTaggedInteger();
2783 return ARG_SIZE(INTEGER_TAG);
2787 *((unsigned int*)res) = PopTaggedWord();
2788 return ARG_SIZE(WORD_TAG);
2791 *((int*)res) = PopTaggedChar();
2792 return ARG_SIZE(CHAR_TAG);
2794 *((float*)res) = PopTaggedFloat();
2795 return ARG_SIZE(FLOAT_TAG);
2797 *((double*)res) = PopTaggedDouble();
2798 return ARG_SIZE(DOUBLE_TAG);
2801 *((void**)res) = PopTaggedAddr();
2802 return ARG_SIZE(ADDR_TAG);
2805 *((StgStablePtr*)res) = PopTaggedStablePtr();
2806 return ARG_SIZE(STABLE_TAG);
2809 StgForeignObj *result = stgCast(StgForeignObj*,PopPtr());
2810 *((void**)res) = result->data;
2811 return sizeofW(StgPtr);
2813 #ifdef PROVIDE_ARRAY
2818 StgArrPtrs* arr = stgCast(StgArrPtrs*,PopPtr());
2819 *((void**)res) = stgCast(void*,&(arr->payload));
2820 return sizeofW(StgPtr);
2823 barf("unmarshall: unrecognised result type %d\n",res_ty);
2827 nat argSize( const char* ks )
2830 for( ; *ks != '\0'; ++ks) {
2833 sz += sizeof(StgWord) * ARG_SIZE(INT_TAG);
2835 #ifdef PROVIDE_INT64
2837 sz += sizeof(StgWord) * ARG_SIZE(INT64_TAG);
2840 #ifdef TODO_PROVIDE_INTEGER
2842 sz += sizeof(StgWord) * ARG_SIZE(INTEGER_TAG);
2847 sz += sizeof(StgWord) * ARG_SIZE(WORD_TAG);
2851 sz += sizeof(StgWord) * ARG_SIZE(CHAR_TAG);
2854 sz += sizeof(StgWord) * ARG_SIZE(FLOAT_TAG);
2857 sz += sizeof(StgWord) * ARG_SIZE(DOUBLE_TAG);
2861 sz += sizeof(StgWord) * ARG_SIZE(ADDR_TAG);
2864 #ifdef PROVIDE_STABLE
2866 sz += sizeof(StgWord) * ARG_SIZE(STABLE_TAG);
2869 #ifdef PROVIDE_FOREIGN
2872 #ifdef PROVIDE_ARRAY
2876 sz += sizeof(StgPtr);
2879 barf("argSize: unrecognised result type %d\n",*ks);
2886 #endif /* INTERPRETER */