2 /* -----------------------------------------------------------------------------
3 * $Id: Evaluator.c,v 1.9 1999/02/11 17:40:24 simonm Exp $
5 * Copyright (c) The GHC Team 1994-1999.
9 * ---------------------------------------------------------------------------*/
19 #include "SchedAPI.h" /* for createGenThread */
20 #include "Schedule.h" /* for context_switch */
22 #include "Bytecodes.h"
23 #include "Assembler.h" /* for CFun stuff */
24 #include "ForeignCall.h"
25 #include "StablePriv.h"
26 #include "PrimOps.h" /* for __{encode,decode}{Float,Double} */
27 #include "Evaluator.h"
31 #include "Disassembler.h"
37 #include <math.h> /* These are for primops */
38 #include <limits.h> /* These are for primops */
39 #include <float.h> /* These are for primops */
41 #include <ieee754.h> /* These are for primops */
43 #ifdef PROVIDE_INTEGER
44 #include "gmp.h" /* These are for primops */
47 /* An incredibly useful abbreviation.
48 * Interestingly, there are some uses of END_TSO_QUEUE_closure that
49 * can't use it because they use the closure at type StgClosure* or
50 * even StgPtr*. I suspect they should be changed. -- ADR
52 #define EndTSOQueue stgCast(StgTSO*,(void*)&END_TSO_QUEUE_closure)
54 /* These macros are rather delicate - read a good ANSI C book carefully
58 #define mycat(x,y) x##y
59 #define mycat2(x,y) mycat(x,y)
60 #define mycat3(x,y,z) mycat2(x,mycat2(y,z))
62 /* --------------------------------------------------------------------------
63 * Hugs Hooks - a bit of a hack
64 * ------------------------------------------------------------------------*/
66 void setRtsFlags( int x );
67 void setRtsFlags( int x )
69 *(int*)(&(RtsFlags.DebugFlags)) = x;
72 /* --------------------------------------------------------------------------
75 * ToDo: figure out why these are being used and crush them!
76 * ------------------------------------------------------------------------*/
78 void OnExitHook (void)
81 void StackOverflowHook (unsigned long stack_size)
83 fprintf(stderr,"Stack Overflow\n");
86 void OutOfHeapHook (unsigned long request_size, unsigned long heap_size)
88 fprintf(stderr,"Out Of Heap\n");
91 void MallocFailHook (unsigned long request_size /* in bytes */, char *msg)
93 fprintf(stderr,"Malloc Fail\n");
96 void defaultsHook (void)
101 /* --------------------------------------------------------------------------
103 * ------------------------------------------------------------------------*/
105 #ifdef PROVIDE_INTEGER
106 static /*inline*/ mpz_ptr mpz_alloc ( void );
107 static /*inline*/ void mpz_free ( mpz_ptr );
109 static /*inline*/ mpz_ptr mpz_alloc ( void )
111 mpz_ptr r = stgCast(mpz_ptr,stgMallocBytes( sizeof(mpz_t),"mpz_alloc"));
116 static /*inline*/ void mpz_free ( mpz_ptr a )
123 /* --------------------------------------------------------------------------
125 * ------------------------------------------------------------------------*/
127 static /*inline*/ void PushTag ( StackTag t );
128 static /*inline*/ void PushPtr ( StgPtr x );
129 static /*inline*/ void PushCPtr ( StgClosure* x );
130 static /*inline*/ void PushInt ( StgInt x );
131 static /*inline*/ void PushWord ( StgWord x );
133 static /*inline*/ void PushTag ( StackTag t ) { *(--Sp) = t; }
134 static /*inline*/ void PushPtr ( StgPtr x ) { *(--stgCast(StgPtr*,Sp)) = x; }
135 static /*inline*/ void PushCPtr ( StgClosure* x ) { *(--stgCast(StgClosure**,Sp)) = x; }
136 static /*inline*/ void PushInt ( StgInt x ) { *(--stgCast(StgInt*,Sp)) = x; }
137 static /*inline*/ void PushWord ( StgWord x ) { *(--stgCast(StgWord*,Sp)) = x; }
139 static /*inline*/ void checkTag ( StackTag t1, StackTag t2 );
140 static /*inline*/ void PopTag ( StackTag t );
141 static /*inline*/ StgPtr PopPtr ( void );
142 static /*inline*/ StgClosure* PopCPtr ( void );
143 static /*inline*/ StgInt PopInt ( void );
144 static /*inline*/ StgWord PopWord ( void );
146 static /*inline*/ void checkTag ( StackTag t1, StackTag t2 ) { ASSERT(t1 == t2);}
147 static /*inline*/ void PopTag ( StackTag t ) { checkTag(t,*(Sp++)); }
148 static /*inline*/ StgPtr PopPtr ( void ) { return *stgCast(StgPtr*,Sp)++; }
149 static /*inline*/ StgClosure* PopCPtr ( void ) { return *stgCast(StgClosure**,Sp)++; }
150 static /*inline*/ StgInt PopInt ( void ) { return *stgCast(StgInt*,Sp)++; }
151 static /*inline*/ StgWord PopWord ( void ) { return *stgCast(StgWord*,Sp)++; }
153 static /*inline*/ StgPtr stackPtr ( StgStackOffset i );
154 static /*inline*/ StgInt stackInt ( StgStackOffset i );
155 static /*inline*/ StgWord stackWord ( StgStackOffset i );
157 static /*inline*/ StgPtr stackPtr ( StgStackOffset i ) { return *stgCast(StgPtr*, Sp+i); }
158 static /*inline*/ StgInt stackInt ( StgStackOffset i ) { return *stgCast(StgInt*, Sp+i); }
159 static /*inline*/ StgWord stackWord ( StgStackOffset i ) { return *stgCast(StgWord*,Sp+i); }
161 static /*inline*/ void setStackWord ( StgStackOffset i, StgWord w );
163 static /*inline*/ void setStackWord ( StgStackOffset i, StgWord w ) { Sp[i] = w; }
165 static /*inline*/ void PushTaggedRealWorld( void );
166 static /*inline*/ void PushTaggedInt ( StgInt x );
168 static /*inline*/ void PushTaggedInt64 ( StgInt64 x );
170 #ifdef PROVIDE_INTEGER
171 static /*inline*/ void PushTaggedInteger ( mpz_ptr x );
174 static /*inline*/ void PushTaggedWord ( StgWord x );
177 static /*inline*/ void PushTaggedAddr ( StgAddr x );
179 static /*inline*/ void PushTaggedChar ( StgChar x );
180 static /*inline*/ void PushTaggedFloat ( StgFloat x );
181 static /*inline*/ void PushTaggedDouble ( StgDouble x );
182 static /*inline*/ void PushTaggedStablePtr ( StgStablePtr x );
183 static /*inline*/ void PushTaggedBool ( int x );
185 static /*inline*/ void PushTaggedRealWorld( void ) { PushTag(REALWORLD_TAG); }
186 static /*inline*/ void PushTaggedInt ( StgInt x ) { Sp -= sizeofW(StgInt); *Sp = x; PushTag(INT_TAG); }
188 static /*inline*/ void PushTaggedInt64 ( StgInt64 x ) { Sp -= sizeofW(StgInt64); ASSIGN_Int64(Sp,x); PushTag(INT64_TAG); }
190 #ifdef PROVIDE_INTEGER
191 static /*inline*/ void PushTaggedInteger ( mpz_ptr x )
193 StgForeignObj *result;
196 result = stgCast(StgForeignObj*,allocate(sizeofW(StgForeignObj)));
197 SET_HDR(result,&FOREIGN_info,CCCS);
200 #if 0 /* For now we don't deallocate Integer's at all */
201 w = stgCast(StgWeak*,allocate(sizeofW(StgWeak)));
202 SET_HDR(w, &WEAK_info, CCCS);
203 w->key = stgCast(StgClosure*,result);
204 w->value = stgCast(StgClosure*,result); /* or any other closure you have handy */
205 w->finalizer = funPtrToIO(mpz_free);
206 w->link = weak_ptr_list;
208 IF_DEBUG(weak, fprintf(stderr,"New weak pointer watching Foreign MPZ at %p\n",w));
211 PushPtr(stgCast(StgPtr,result));
215 static /*inline*/ void PushTaggedWord ( StgWord x ) { Sp -= sizeofW(StgWord); *Sp = x; PushTag(WORD_TAG); }
218 static /*inline*/ void PushTaggedAddr ( StgAddr x ) { Sp -= sizeofW(StgAddr); *Sp = (W_)x; PushTag(ADDR_TAG); }
220 static /*inline*/ void PushTaggedChar ( StgChar x ) { Sp -= sizeofW(StgChar); *Sp = x; PushTag(CHAR_TAG); }
221 static /*inline*/ void PushTaggedFloat ( StgFloat x ) { Sp -= sizeofW(StgFloat); ASSIGN_FLT(Sp,x); PushTag(FLOAT_TAG); }
222 static /*inline*/ void PushTaggedDouble ( StgDouble x ) { Sp -= sizeofW(StgDouble); ASSIGN_DBL(Sp,x); PushTag(DOUBLE_TAG); }
223 static /*inline*/ void PushTaggedStablePtr ( StgStablePtr x ) { Sp -= sizeofW(StgStablePtr); *Sp = x; PushTag(STABLE_TAG); }
224 static /*inline*/ void PushTaggedBool ( int x ) { PushTaggedInt(x); }
226 static /*inline*/ void PopTaggedRealWorld ( void );
227 static /*inline*/ StgInt PopTaggedInt ( void );
229 static /*inline*/ StgInt64 PopTaggedInt64 ( void );
231 #ifdef PROVIDE_INTEGER
232 static /*inline*/ mpz_ptr PopTaggedInteger ( void );
235 static /*inline*/ StgWord PopTaggedWord ( void );
238 static /*inline*/ StgAddr PopTaggedAddr ( void );
240 static /*inline*/ StgChar PopTaggedChar ( void );
241 static /*inline*/ StgFloat PopTaggedFloat ( void );
242 static /*inline*/ StgDouble PopTaggedDouble ( void );
243 static /*inline*/ StgStablePtr PopTaggedStablePtr ( void );
245 static /*inline*/ void PopTaggedRealWorld ( void ) { PopTag(REALWORLD_TAG); }
246 static /*inline*/ StgInt PopTaggedInt ( void ) { StgInt r; PopTag(INT_TAG); r = *stgCast(StgInt*, Sp); Sp += sizeofW(StgInt); return r;}
248 static /*inline*/ StgInt64 PopTaggedInt64 ( void ) { StgInt64 r; PopTag(INT64_TAG); r = PK_Int64(Sp); Sp += sizeofW(StgInt64); return r;}
250 #ifdef PROVIDE_INTEGER
251 static /*inline*/ mpz_ptr PopTaggedInteger ( void ) { StgForeignObj *r = *stgCast(StgForeignObj**,Sp); Sp += sizeofW(StgPtr); return stgCast(mpz_ptr,r->data);}
254 static /*inline*/ StgWord PopTaggedWord ( void ) { StgWord r; PopTag(WORD_TAG); r = *stgCast(StgWord*, Sp); Sp += sizeofW(StgWord); return r;}
257 static /*inline*/ StgAddr PopTaggedAddr ( void ) { StgAddr r; PopTag(ADDR_TAG); r = *stgCast(StgAddr*, Sp); Sp += sizeofW(StgAddr); return r;}
259 static /*inline*/ StgChar PopTaggedChar ( void ) { StgChar r; PopTag(CHAR_TAG); r = *stgCast(StgChar*, Sp); Sp += sizeofW(StgChar); return r;}
260 static /*inline*/ StgFloat PopTaggedFloat ( void ) { StgFloat r; PopTag(FLOAT_TAG); r = PK_FLT(Sp); Sp += sizeofW(StgFloat); return r;}
261 static /*inline*/ StgDouble PopTaggedDouble ( void ) { StgDouble r; PopTag(DOUBLE_TAG); r = PK_DBL(Sp); Sp += sizeofW(StgDouble); return r;}
262 static /*inline*/ StgStablePtr PopTaggedStablePtr ( void ) { StgInt r; PopTag(STABLE_TAG); r = *stgCast(StgStablePtr*, Sp); Sp += sizeofW(StgStablePtr); return r;}
264 static /*inline*/ StgInt taggedStackInt ( StgStackOffset i );
266 static /*inline*/ StgInt64 taggedStackInt64 ( StgStackOffset i );
269 static /*inline*/ StgWord taggedStackWord ( StgStackOffset i );
272 static /*inline*/ StgAddr taggedStackAddr ( StgStackOffset i );
274 static /*inline*/ StgChar taggedStackChar ( StgStackOffset i );
275 static /*inline*/ StgFloat taggedStackFloat ( StgStackOffset i );
276 static /*inline*/ StgDouble taggedStackDouble ( StgStackOffset i );
277 static /*inline*/ StgStablePtr taggedStackStable ( StgStackOffset i );
279 static /*inline*/ StgInt taggedStackInt ( StgStackOffset i ) { checkTag(INT_TAG,Sp[i]); return *stgCast(StgInt*, Sp+1+i); }
281 static /*inline*/ StgInt64 taggedStackInt64 ( StgStackOffset i ) { checkTag(INT64_TAG,Sp[i]); return PK_Int64(Sp+1+i); }
284 static /*inline*/ StgWord taggedStackWord ( StgStackOffset i ) { checkTag(WORD_TAG,Sp[i]); return *stgCast(StgWord*, Sp+1+i); }
287 static /*inline*/ StgAddr taggedStackAddr ( StgStackOffset i ) { checkTag(ADDR_TAG,Sp[i]); return *stgCast(StgAddr*, Sp+1+i); }
289 static /*inline*/ StgChar taggedStackChar ( StgStackOffset i ) { checkTag(CHAR_TAG,Sp[i]); return *stgCast(StgChar*, Sp+1+i); }
290 static /*inline*/ StgFloat taggedStackFloat ( StgStackOffset i ) { checkTag(FLOAT_TAG,Sp[i]); return PK_FLT(Sp+1+i); }
291 static /*inline*/ StgDouble taggedStackDouble ( StgStackOffset i ) { checkTag(DOUBLE_TAG,Sp[i]); return PK_DBL(Sp+1+i); }
292 static /*inline*/ StgStablePtr taggedStackStable ( StgStackOffset i ) { checkTag(STABLE_TAG,Sp[i]); return *stgCast(StgStablePtr*, Sp+1+i); }
295 /* --------------------------------------------------------------------------
298 * Should we allocate from a nursery or use the
299 * doYouWantToGC/allocate interface? We'd already implemented a
300 * nursery-style scheme when the doYouWantToGC/allocate interface
302 * One reason to prefer the doYouWantToGC/allocate interface is to
303 * support operations which allocate an unknown amount in the heap
304 * (array ops, gmp ops, etc)
305 * ------------------------------------------------------------------------*/
307 static /*inline*/ StgPtr grabHpUpd( nat size )
309 ASSERT( size >= MIN_UPD_SIZE + sizeofW(StgHeader) );
310 return allocate(size);
313 static /*inline*/ StgPtr grabHpNonUpd( nat size )
315 ASSERT( size >= MIN_NONUPD_SIZE + sizeofW(StgHeader) );
316 return allocate(size);
319 /* --------------------------------------------------------------------------
320 * Manipulate "update frame" list:
321 * o Update frames (based on stg_do_update and friends in Updates.hc)
322 * o Error handling/catching (based on catchzh_fast and friends in Prims.hc)
323 * o Seq frames (based on seq_frame_entry in Prims.hc)
325 * ------------------------------------------------------------------------*/
327 static /*inline*/ void PopUpdateFrame ( StgClosure* obj );
328 static /*inline*/ void PushCatchFrame ( StgClosure* catcher );
329 static /*inline*/ void PopCatchFrame ( void );
330 static /*inline*/ void PushSeqFrame ( void );
331 static /*inline*/ void PopSeqFrame ( void );
333 static /*inline*/ StgClosure* raiseAnError ( StgClosure* errObj );
335 static /*inline*/ void PopUpdateFrame( StgClosure* obj )
337 /* NB: doesn't assume that Sp == Su */
339 fprintf(stderr, "Updating ");
340 printPtr(stgCast(StgPtr,Su->updatee));
341 fprintf(stderr, " with ");
343 fprintf(stderr,"\nSp = %p\tSu = %p\n", Sp, Su);
345 #ifndef LAZY_BLACKHOLING
346 ASSERT(get_itbl(Su->updatee)->type == BLACKHOLE
347 || get_itbl(Su->updatee)->type == CAF_BLACKHOLE
349 #endif /* LAZY_BLACKHOLING */
350 UPD_IND(Su->updatee,obj);
351 Sp = stgCast(StgStackPtr,Su) + sizeofW(StgUpdateFrame);
355 static /*inline*/ void PopStopFrame( StgClosure* obj )
357 /* Move Su just off the end of the stack, we're about to spam the
358 * STOP_FRAME with the return value.
360 Su = stgCast(StgUpdateFrame*,Sp+1);
361 *stgCast(StgClosure**,Sp) = obj;
364 static /*inline*/ void PushCatchFrame( StgClosure* handler )
367 /* ToDo: stack check! */
368 Sp -= sizeofW(StgCatchFrame*); /* ToDo: this can't be right */
369 fp = stgCast(StgCatchFrame*,Sp);
370 SET_HDR(fp,&catch_frame_info,CCCS);
371 fp->handler = handler;
373 Su = stgCast(StgUpdateFrame*,fp);
376 static /*inline*/ void PopCatchFrame( void )
378 /* NB: doesn't assume that Sp == Su */
379 /* fprintf(stderr,"Popping catch frame\n"); */
380 Sp = stgCast(StgStackPtr,Su) + sizeofW(StgCatchFrame);
381 Su = stgCast(StgCatchFrame*,Su)->link;
384 static /*inline*/ void PushSeqFrame( void )
387 /* ToDo: stack check! */
388 Sp -= sizeofW(StgSeqFrame*); /* ToDo: this can't be right */
389 fp = stgCast(StgSeqFrame*,Sp);
390 SET_HDR(fp,&seq_frame_info,CCCS);
392 Su = stgCast(StgUpdateFrame*,fp);
395 static /*inline*/ void PopSeqFrame( void )
397 /* NB: doesn't assume that Sp == Su */
398 Sp = stgCast(StgStackPtr,Su) + sizeofW(StgSeqFrame);
399 Su = stgCast(StgSeqFrame*,Su)->link;
402 static /*inline*/ StgClosure* raiseAnError( StgClosure* errObj )
404 StgClosure *raise_closure;
406 /* This closure represents the expression 'raise# E' where E
407 * is the exception raise. It is used to overwrite all the
408 * thunks which are currently under evaluataion.
410 raise_closure = (StgClosure *)allocate(sizeofW(StgClosure)+1);
411 raise_closure->header.info = &raise_info;
412 raise_closure->payload[0] = R1.cl;
415 switch (get_itbl(Su)->type) {
417 UPD_IND(Su->updatee,raise_closure);
418 Sp = stgCast(StgStackPtr,Su) + sizeofW(StgUpdateFrame);
424 case CATCH_FRAME: /* found it! */
426 StgCatchFrame* fp = stgCast(StgCatchFrame*,Su);
427 StgClosure *handler = fp->handler;
429 Sp += sizeofW(StgCatchFrame); /* Pop */
434 barf("raiseError: STOP_FRAME");
436 barf("raiseError: weird activation record");
441 static StgClosure* raisePrim(char* msg)
443 /* ToDo: figure out some way to turn the msg into a Haskell Exception
444 * Hack: we don't know how to build an Exception but we do know how
445 * to build a (recursive!) error object.
446 * The result isn't pretty but it's (slightly) better than nothing.
448 nat size = sizeof(StgClosure) + 1;
449 StgClosure* errObj = stgCast(StgClosure*,grabHpNonUpd(size));
450 SET_INFO(errObj,&raise_info);
451 errObj->payload[0] = errObj;
456 /* At the moment, I prefer to put it on stdout to make things as
457 * close to Hugs' old behaviour as possible.
459 fprintf(stdout, "Program error: %s", msg);
462 return raiseAnError(stgCast(StgClosure*,errObj));
465 #define raiseIndex(where) raisePrim("Array index out of range in " where)
466 #define raiseDiv0(where) raisePrim("Division by 0 in " where)
468 /* --------------------------------------------------------------------------
470 * ------------------------------------------------------------------------*/
474 unsigned char x = PopTaggedChar(); \
475 unsigned char y = PopTaggedChar(); \
481 unsigned char x = PopTaggedChar(); \
492 StgInt x = PopTaggedInt(); \
493 StgWord y = PopTaggedWord(); \
499 StgInt x = PopTaggedInt(); \
500 StgInt y = PopTaggedInt(); \
506 StgInt x = PopTaggedInt(); \
507 StgInt y = PopTaggedInt(); \
518 StgInt x = PopTaggedInt(); \
524 StgInt x = PopTaggedInt(); \
535 StgInt x = PopTaggedInt(); \
546 StgInt x = PopTaggedInt(); \
552 PushTaggedFloat(e); \
557 StgInt x = PopTaggedInt(); \
558 PushTaggedFloat(e); \
563 PushTaggedDouble(e); \
568 StgInt x = PopTaggedInt(); \
569 PushTaggedDouble(e); \
575 StgWord x = PopTaggedWord(); \
576 StgWord y = PopTaggedWord(); \
582 StgWord x = PopTaggedWord(); \
583 StgWord y = PopTaggedWord(); \
589 StgWord x = PopTaggedWord(); \
595 StgWord x = PopTaggedWord(); \
603 StgAddr x = PopTaggedAddr(); \
604 StgAddr y = PopTaggedAddr(); \
609 StgAddr x = PopTaggedAddr(); \
614 StgAddr x = PopTaggedAddr(); \
615 int y = PopTaggedInt(); \
622 StgAddr x = PopTaggedAddr(); \
623 int y = PopTaggedInt(); \
630 StgAddr x = PopTaggedAddr(); \
631 int y = PopTaggedInt(); \
634 PushTaggedInt64(r); \
638 StgAddr x = PopTaggedAddr(); \
639 int y = PopTaggedInt(); \
646 StgAddr x = PopTaggedAddr(); \
647 int y = PopTaggedInt(); \
650 PushTaggedFloat(r); \
654 StgAddr x = PopTaggedAddr(); \
655 int y = PopTaggedInt(); \
658 PushTaggedDouble(r); \
662 StgAddr x = PopTaggedAddr(); \
663 int y = PopTaggedInt(); \
666 PushTaggedStablePtr(r); \
670 StgAddr x = PopTaggedAddr(); \
671 int y = PopTaggedInt(); \
672 StgChar z = PopTaggedChar(); \
677 StgAddr x = PopTaggedAddr(); \
678 int y = PopTaggedInt(); \
679 StgInt z = PopTaggedInt(); \
684 StgAddr x = PopTaggedAddr(); \
685 int y = PopTaggedInt(); \
686 StgInt64 z = PopTaggedInt64(); \
691 StgAddr x = PopTaggedAddr(); \
692 int y = PopTaggedInt(); \
693 StgAddr z = PopTaggedAddr(); \
698 StgAddr x = PopTaggedAddr(); \
699 int y = PopTaggedInt(); \
700 StgFloat z = PopTaggedFloat(); \
705 StgAddr x = PopTaggedAddr(); \
706 int y = PopTaggedInt(); \
707 StgDouble z = PopTaggedDouble(); \
712 StgAddr x = PopTaggedAddr(); \
713 int y = PopTaggedInt(); \
714 StgStablePtr z = PopTaggedStablePtr(); \
718 #endif /* PROVIDE_ADDR */
722 StgFloat x = PopTaggedFloat(); \
723 StgFloat y = PopTaggedFloat(); \
729 StgFloat x = PopTaggedFloat(); \
730 StgFloat y = PopTaggedFloat(); \
731 PushTaggedFloat(e); \
736 StgFloat x = PopTaggedFloat(); \
737 PushTaggedFloat(e); \
742 StgFloat x = PopTaggedFloat(); \
748 StgFloat x = PopTaggedFloat(); \
754 StgFloat x = PopTaggedFloat(); \
755 PushTaggedDouble(e); \
760 StgDouble x = PopTaggedDouble(); \
761 StgDouble y = PopTaggedDouble(); \
767 StgDouble x = PopTaggedDouble(); \
768 StgDouble y = PopTaggedDouble(); \
769 PushTaggedDouble(e); \
774 StgDouble x = PopTaggedDouble(); \
780 StgDouble x = PopTaggedDouble(); \
781 PushTaggedDouble(e); \
786 StgDouble x = PopTaggedDouble(); \
792 StgDouble x = PopTaggedDouble(); \
793 PushTaggedFloat(e); \
799 StgInt64 x = PopTaggedInt64(); \
800 int y = PopTaggedInt(); \
801 PushTaggedFloat(e); \
805 StgInt64 x = PopTaggedInt64(); \
806 int y = PopTaggedInt(); \
807 PushTaggedDouble(e); \
811 StgInt64 x = PopTaggedInt64(); \
812 StgInt64 y = PopTaggedInt64(); \
817 StgInt64 x = PopTaggedInt64(); \
818 PushTaggedInt64(e); \
822 StgInt64 x = PopTaggedInt64(); \
823 StgInt64 y = PopTaggedInt64(); \
824 PushTaggedInt64(e); \
828 StgInt64 x = PopTaggedInt64(); \
829 StgWord y = PopTaggedWord(); \
830 PushTaggedInt64(e); \
832 #define OP_zz_zZ(e1,e2) \
834 StgInt64 x = PopTaggedInt64(); \
835 StgInt64 y = PopTaggedInt64(); \
836 PushTaggedInt64(e1); \
837 PushTaggedInt64(e2); \
841 StgInt64 x = PopTaggedInt64(); \
842 StgInt64 y = PopTaggedInt64(); \
847 PushTaggedInt64(e); \
851 StgInt64 x = PopTaggedInt64(); \
856 StgInt x = PopTaggedInt(); \
857 PushTaggedInt64(e); \
862 StgInt64 x = PopTaggedInt64(); \
867 StgWord x = PopTaggedWord(); \
868 PushTaggedInt64(e); \
873 StgInt64 x = PopTaggedInt64(); \
874 printf("%lld = %f\n",x,(float)(e)); \
875 PushTaggedFloat(e); \
879 StgFloat x = PopTaggedFloat(); \
880 PushTaggedInt64(e); \
884 StgInt64 x = PopTaggedInt64(); \
885 PushTaggedDouble(e); \
889 StgDouble x = PopTaggedDouble(); \
890 PushTaggedInt64(e); \
894 #ifdef PROVIDE_INTEGER
898 mpz_ptr x = PopTaggedInteger(); \
899 int y = PopTaggedInt(); \
900 PushTaggedFloat(e); \
904 StgFloat x = PopTaggedFloat(); \
905 mpz_ptr r1 = mpz_alloc(); \
909 PushTaggedInteger(r1); \
913 mpz_ptr x = PopTaggedInteger(); \
914 int y = PopTaggedInt(); \
915 PushTaggedDouble(e); \
919 StgDouble x = PopTaggedDouble(); \
920 mpz_ptr r1 = mpz_alloc(); \
924 PushTaggedInteger(r1); \
928 mpz_ptr x = PopTaggedInteger(); \
929 mpz_ptr r = mpz_alloc(); \
931 PushTaggedInteger(r); \
935 mpz_ptr x = PopTaggedInteger(); \
936 mpz_ptr y = PopTaggedInteger(); \
937 mpz_ptr r = mpz_alloc(); \
939 PushTaggedInteger(r); \
943 mpz_ptr x = PopTaggedInteger(); \
944 mpz_ptr y = PopTaggedInteger(); \
949 mpz_ptr x = PopTaggedInteger(); \
954 StgInt x = PopTaggedInt(); \
955 mpz_ptr r = mpz_alloc(); \
957 PushTaggedInteger(r); \
962 mpz_ptr x = PopTaggedInteger(); \
963 PushTaggedInt64(e); \
967 StgInt64 x = PopTaggedInt64(); \
968 mpz_ptr r = mpz_alloc(); \
970 PushTaggedInteger(r); \
976 mpz_ptr x = PopTaggedInteger(); \
981 StgWord x = PopTaggedWord(); \
982 mpz_ptr r = mpz_alloc(); \
984 PushTaggedInteger(r); \
989 mpz_ptr x = PopTaggedInteger(); \
990 PushTaggedFloat(e); \
994 StgFloat x = PopTaggedFloat(); \
995 mpz_ptr r = mpz_alloc(); \
997 PushTaggedInteger(r); \
1001 mpz_ptr x = PopTaggedInteger(); \
1002 PushTaggedDouble(e); \
1006 StgDouble x = PopTaggedDouble(); \
1007 mpz_ptr r = mpz_alloc(); \
1009 PushTaggedInteger(r); \
1012 #endif /* ifdef PROVIDE_INTEGER */
1014 #ifdef PROVIDE_ARRAY
1015 #define HEADER_mI(ty,where) \
1016 StgArrWords* x = stgCast(StgArrWords*,PopPtr()); \
1017 nat i = PopTaggedInt(); \
1018 if (i * sizeof(ty) + (sizeof(ty)) > sizeof(StgWord) * x->words) { \
1019 obj = raiseIndex(where); \
1022 #define OP_mI_ty(ty,where,s) \
1024 HEADER_mI(mycat2(Stg,ty),where) \
1025 { mycat2(Stg,ty) r; \
1027 mycat2(PushTagged,ty)(r); \
1030 #define OP_mIty_(ty,where,s) \
1032 HEADER_mI(mycat2(Stg,ty),where) \
1034 mycat2(Stg,ty) z = mycat2(PopTagged,ty)(); \
1039 #endif /* PROVIDE_ARRAY */
1042 /* This is written as one giant function in the hope that gcc will do
1043 * a better job of register allocation.
1045 StgThreadReturnCode enter( StgClosure* obj )
1047 /* We use a char so that we'll do a context_switch check every 256
1050 char enterCount = 0;
1052 /* ASSERT(StorageMgrInfo.hp_start <= Hp && Hp < HpLim && HpLim == StorageMgrInfo.hplim); */
1053 ASSERT(SpLim <= Sp && Sp <= stgCast(StgPtr,Su));
1056 fprintf(stderr,"Sp = %p\tSu = %p\n", Sp, Su);
1057 printStack(Sp,CurrentTSO->stack+CurrentTSO->stack_size,Su);
1058 fprintf(stderr,"Entering: "); printObj(obj);
1064 /*belch("Starting sanity check");
1066 *checkTSO(CurrentTSO, heap_step);
1067 * This check fails if we've done any updates because we
1068 * whack into holes in the heap.
1070 *belch("Ending sanity check");
1077 fprintf(stderr,"Continue?\n");
1081 if (++enterCount == 0 && context_switch) {
1082 PushCPtr(obj); /* code to restart with */
1083 return ThreadYielding;
1085 switch ( get_itbl(obj)->type ) {
1086 case INVALID_OBJECT:
1087 barf("Invalid object %p",obj);
1090 StgBCO* bco = stgCast(StgBCO*,obj);
1092 #if 1 /* We don't use an explicit HP_CHECK anymore */
1093 if (doYouWantToGC()) {
1094 PushCPtr(obj); /* code to restart with */
1095 return HeapOverflow;
1099 ASSERT(pc < bco->n_instrs);
1101 fprintf(stderr,"Sp = %p\tSu = %p\tpc = %d\t", Sp, Su, pc);
1103 /*fprintf(stderr,"\t"); printStackObj(Sp); */
1104 fprintf(stderr,"\n");
1106 switch (bcoInstr(bco,pc++)) {
1107 case i_INTERNAL_ERROR:
1108 barf("INTERNAL_ERROR at %p:%d",bco,pc-1);
1110 barf("PANIC at %p:%d",bco,pc-1);
1114 int n = bcoInstr(bco,pc++);
1115 /* ToDo: we could allocate the whole thing now and
1116 * slice it up ourselves
1118 if (doYouWantToGC()) {
1119 PushCPtr(obj); /* code to restart with */
1120 return HeapOverflow;
1127 int n = bcoInstr(bco,pc++);
1128 if (Sp - n < SpLim) {
1129 PushCPtr(obj); /* code to restart with */
1130 return StackOverflow;
1136 /* ToDo: make sure that hp check allows for possible PAP */
1137 nat n = bcoInstr(bco,pc++);
1138 if (stgCast(StgPtr,Sp + n) > stgCast(StgPtr,Su)) {
1139 StgWord words = (P_)Su - Sp;
1141 /* first build a PAP */
1142 ASSERT((P_)Su >= Sp); /* was (words >= 0) but that's always true */
1143 if (words == 0) { /* optimisation */
1144 /* Skip building the PAP and update with an indirection. */
1145 } else { /* Build the PAP. */
1146 /* In the evaluator, we avoid the need to do
1147 * a heap check here by including the size of
1148 * the PAP in the heap check we performed
1149 * when we entered the BCO.
1152 StgPAP* pap = stgCast(StgPAP*,grabHpNonUpd(PAP_sizeW(words)));
1153 SET_HDR(pap,&PAP_info,CC_pap);
1154 pap->n_args = words;
1156 for(i = 0; i < (I_)words; ++i) {
1157 payloadWord(pap,i) = Sp[i];
1160 obj = stgCast(StgClosure*,pap);
1163 /* now deal with "update frame" */
1164 /* as an optimisation, we process all on top of stack instead of just the top one */
1167 switch (get_itbl(Su)->type) {
1172 PopUpdateFrame(obj);
1176 return ThreadFinished;
1181 barf("Invalid update frame during argcheck");
1183 } while (Sp==(P_)Su);
1190 int words = bcoInstr(bco,pc++);
1191 PushPtr(grabHpUpd(AP_sizeW(words)));
1194 case i_ALLOC_CONSTR:
1196 StgInfoTable* info = bcoConstAddr(bco,bcoInstr(bco,pc++));
1197 StgClosure* c = stgCast(StgClosure*,grabHpNonUpd(sizeW_fromITBL(info)));
1199 PushPtr(stgCast(StgPtr,c));
1204 int x = bcoInstr(bco,pc++); /* ToDo: Word not Int! */
1205 int y = bcoInstr(bco,pc++);
1206 StgAP_UPD* o = stgCast(StgAP_UPD*,stackPtr(x));
1207 SET_HDR(o,&AP_UPD_info,??);
1209 o->fun = stgCast(StgClosure*,PopPtr());
1210 for(x=0; x < y; ++x) {
1211 payloadWord(o,x) = PopWord();
1214 fprintf(stderr,"\tBuilt ");
1215 printObj(stgCast(StgClosure*,o));
1221 int x = bcoInstr(bco,pc++);
1222 int y = bcoInstr(bco,pc++);
1223 StgPAP* o = stgCast(StgPAP*,stackPtr(x));
1224 SET_HDR(o,&PAP_info,??);
1226 o->fun = stgCast(StgClosure*,PopPtr());
1227 for(x=0; x < y; ++x) {
1228 payloadWord(o,x) = PopWord();
1231 fprintf(stderr,"\tBuilt ");
1232 printObj(stgCast(StgClosure*,o));
1238 int offset = bcoInstr(bco,pc++);
1239 StgClosure* o = stgCast(StgClosure*,stackPtr(offset));
1240 const StgInfoTable* info = get_itbl(o);
1241 nat p = info->layout.payload.ptrs;
1242 nat np = info->layout.payload.nptrs;
1244 for(i=0; i < p; ++i) {
1245 payloadCPtr(o,i) = PopCPtr();
1247 for(i=0; i < np; ++i) {
1248 payloadWord(o,p+i) = 0xdeadbeef;
1251 fprintf(stderr,"\tBuilt ");
1252 printObj(stgCast(StgClosure*,o));
1258 int x = bcoInstr(bco,pc++);
1259 int y = bcoInstr(bco,pc++);
1260 ASSERT(Sp+x+y <= stgCast(StgPtr,Su));
1261 /* a_1, .. a_x, b_1, .. b_y, s => a_1, .. a_x, s */
1263 setStackWord(x+y,stackWord(x));
1275 PushPtr(bcoConstPtr(bco,bcoInstr(bco,pc++)));
1276 PushPtr(stgCast(StgPtr,&ret_bco_info));
1281 int tag = bcoInstr(bco,pc++);
1282 StgWord offset = bcoInstr(bco,pc++);
1283 if (constrTag(stgCast(StgClosure*,stackPtr(0))) != tag) {
1290 StgClosure* o = stgCast(StgClosure*,stackPtr(0));
1291 const StgInfoTable* itbl = get_itbl(o);
1292 int i = itbl->layout.payload.ptrs;
1293 ASSERT( itbl->type == CONSTR
1294 || itbl->type == CONSTR_STATIC
1295 || itbl->type == CONSTR_NOCAF_STATIC
1298 PushCPtr(payloadCPtr(o,i));
1304 PushPtr(stackPtr(bcoInstr(bco,pc++)));
1309 PushPtr(stgCast(StgPtr,bcoConstPtr(bco,bcoInstr(bco,pc++))));
1314 StgWord o1 = bcoInstr(bco,pc++);
1315 StgWord o2 = bcoInstr(bco,pc++);
1316 StgWord o = o1*256 + o2;
1317 PushPtr(stgCast(StgPtr,bcoConstPtr(bco,o)));
1322 PushTaggedRealWorld();
1327 PushTaggedInt(taggedStackInt(bcoInstr(bco,pc++)));
1332 PushTaggedInt(bcoConstInt(bco,bcoInstr(bco,pc++)));
1342 StgClosure* o = stgCast(StgClosure*,grabHpNonUpd(Izh_sizeW));
1343 SET_HDR(o,&Izh_con_info,??);
1344 payloadWord(o,0) = PopTaggedInt();
1346 fprintf(stderr,"\tBuilt ");
1347 printObj(stgCast(StgClosure*,o));
1349 PushPtr(stgCast(StgPtr,o));
1354 StgClosure* con = stgCast(StgClosure*,stackPtr(0));
1355 /* ASSERT(isIntLike(con)); */
1356 PushTaggedInt(payloadWord(con,0));
1361 StgWord offset = bcoInstr(bco,pc++);
1362 StgInt x = PopTaggedInt();
1363 StgInt y = PopTaggedInt();
1369 #ifdef PROVIDE_INT64
1372 PushTaggedInt64(taggedStackInt64(bcoInstr(bco,pc++)));
1377 PushTaggedInt64(bcoConstInt64(bco,bcoInstr(bco,pc++)));
1380 case i_RETURN_INT64:
1382 ASSERT(0); /* ToDo(); */
1387 StgClosure* o = stgCast(StgClosure*,grabHpNonUpd(I64zh_sizeW));
1388 SET_HDR(o,&I64zh_con_info,??);
1389 ASSIGN_Int64(&payloadWord(o,0),PopTaggedInt64());
1391 fprintf(stderr,"\tBuilt ");
1392 printObj(stgCast(StgClosure*,o));
1394 PushPtr(stgCast(StgPtr,o));
1397 case i_UNPACK_INT64:
1399 StgClosure* con = stgCast(StgClosure*,stackPtr(0));
1400 /*ASSERT(isInt64Like(con)); */
1401 PushTaggedInt64(PK_Int64(&payloadWord(con,0)));
1405 #ifdef PROVIDE_INTEGER
1406 case i_CONST_INTEGER:
1408 char* s = bcoConstAddr(bco,bcoInstr(bco,pc++));
1409 mpz_ptr r = mpz_alloc();
1410 if (s[0] == '0' && s[1] == 'x') {
1411 mpz_set_str(r,s+2,16);
1413 mpz_set_str(r,s,10);
1415 PushTaggedInteger(r);
1423 PushTaggedWord(taggedStackWord(bcoInstr(bco,pc++)));
1428 PushTaggedWord(bcoConstWord(bco,bcoInstr(bco,pc++)));
1438 StgClosure* o = stgCast(StgClosure*,grabHpNonUpd(Wzh_sizeW));
1440 SET_HDR(o,&Wzh_con_info,??);
1441 payloadWord(o,0) = PopTaggedWord();
1443 fprintf(stderr,"\tBuilt ");
1444 printObj(stgCast(StgClosure*,o));
1446 PushPtr(stgCast(StgPtr,o));
1451 StgClosure* con = stgCast(StgClosure*,stackPtr(0));
1452 /* ASSERT(isWordLike(con)); */
1453 PushTaggedWord(payloadWord(con,0));
1460 PushTaggedAddr(taggedStackAddr(bcoInstr(bco,pc++)));
1465 PushTaggedAddr(bcoConstAddr(bco,bcoInstr(bco,pc++)));
1475 StgClosure* o = stgCast(StgClosure*,grabHpNonUpd(Azh_sizeW));
1476 SET_HDR(o,&Azh_con_info,??);
1477 payloadPtr(o,0) = PopTaggedAddr();
1479 fprintf(stderr,"\tBuilt ");
1480 printObj(stgCast(StgClosure*,o));
1482 PushPtr(stgCast(StgPtr,o));
1487 StgClosure* con = stgCast(StgClosure*,stackPtr(0));
1488 /* ASSERT(isAddrLike(con)); */
1489 PushTaggedAddr(payloadPtr(con,0));
1495 PushTaggedChar(taggedStackChar(bcoInstr(bco,pc++)));
1500 PushTaggedChar(bcoConstChar(bco,bcoInstr(bco,pc++)));
1510 StgClosure* o = stgCast(StgClosure*,grabHpNonUpd(Czh_sizeW));
1511 SET_HDR(o,&Czh_con_info,??);
1512 payloadWord(o,0) = PopTaggedChar();
1513 PushPtr(stgCast(StgPtr,o));
1515 fprintf(stderr,"\tBuilt ");
1516 printObj(stgCast(StgClosure*,o));
1522 StgClosure* con = stgCast(StgClosure*,stackPtr(0));
1523 /* ASSERT(isCharLike(con)); */
1524 PushTaggedChar(payloadWord(con,0));
1529 PushTaggedFloat(taggedStackFloat(bcoInstr(bco,pc++)));
1534 PushTaggedFloat(bcoConstFloat(bco,bcoInstr(bco,pc++)));
1537 case i_RETURN_FLOAT:
1544 StgClosure* o = stgCast(StgClosure*,grabHpNonUpd(Fzh_sizeW));
1545 SET_HDR(o,&Fzh_con_info,??);
1546 ASSIGN_FLT(&payloadWord(o,0),PopTaggedFloat());
1548 fprintf(stderr,"\tBuilt ");
1549 printObj(stgCast(StgClosure*,o));
1551 PushPtr(stgCast(StgPtr,o));
1554 case i_UNPACK_FLOAT:
1556 StgClosure* con = stgCast(StgClosure*,stackPtr(0));
1557 /* ASSERT(isFloatLike(con)); */
1558 PushTaggedFloat(PK_FLT(&payloadWord(con,0)));
1563 PushTaggedDouble(taggedStackDouble(bcoInstr(bco,pc++)));
1566 case i_CONST_DOUBLE:
1568 PushTaggedDouble(bcoConstDouble(bco,bcoInstr(bco,pc++)));
1571 case i_RETURN_DOUBLE:
1578 StgClosure* o = stgCast(StgClosure*,grabHpNonUpd(Dzh_sizeW));
1579 SET_HDR(o,&Dzh_con_info,??);
1580 ASSIGN_DBL(&payloadWord(o,0),PopTaggedDouble());
1582 fprintf(stderr,"\tBuilt ");
1583 printObj(stgCast(StgClosure*,o));
1585 PushPtr(stgCast(StgPtr,o));
1588 case i_UNPACK_DOUBLE:
1590 StgClosure* con = stgCast(StgClosure*,stackPtr(0));
1591 /* ASSERT(isDoubleLike(con)); */
1592 PushTaggedDouble(PK_DBL(&payloadWord(con,0)));
1595 #ifdef PROVIDE_STABLE
1598 PushTaggedStablePtr(taggedStackStable(bcoInstr(bco,pc++)));
1601 case i_RETURN_STABLE:
1608 StgClosure* o = stgCast(StgClosure*,grabHpNonUpd(Stablezh_sizeW));
1609 SET_HDR(o,&StablePtr_con_info,??);
1610 payloadWord(o,0) = PopTaggedStablePtr();
1612 fprintf(stderr,"\tBuilt ");
1613 printObj(stgCast(StgClosure*,o));
1615 PushPtr(stgCast(StgPtr,o));
1618 case i_UNPACK_STABLE:
1620 StgClosure* con = stgCast(StgClosure*,stackPtr(0));
1621 /* ASSERT(isStableLike(con)); */
1622 PushTaggedStablePtr(payloadWord(con,0));
1628 switch (bcoInstr(bco,pc++)) {
1629 case i_INTERNAL_ERROR1:
1630 barf("INTERNAL_ERROR1 at %p:%d",bco,pc-1);
1632 case i_gtChar: OP_CC_B(x>y); break;
1633 case i_geChar: OP_CC_B(x>=y); break;
1634 case i_eqChar: OP_CC_B(x==y); break;
1635 case i_neChar: OP_CC_B(x!=y); break;
1636 case i_ltChar: OP_CC_B(x<y); break;
1637 case i_leChar: OP_CC_B(x<=y); break;
1638 case i_charToInt: OP_C_I(x); break;
1639 case i_intToChar: OP_I_C(x); break;
1641 case i_gtInt: OP_II_B(x>y); break;
1642 case i_geInt: OP_II_B(x>=y); break;
1643 case i_eqInt: OP_II_B(x==y); break;
1644 case i_neInt: OP_II_B(x!=y); break;
1645 case i_ltInt: OP_II_B(x<y); break;
1646 case i_leInt: OP_II_B(x<=y); break;
1647 case i_minInt: OP__I(INT_MIN); break;
1648 case i_maxInt: OP__I(INT_MAX); break;
1649 case i_plusInt: OP_II_I(x+y); break;
1650 case i_minusInt: OP_II_I(x-y); break;
1651 case i_timesInt: OP_II_I(x*y); break;
1654 int x = PopTaggedInt();
1655 int y = PopTaggedInt();
1657 obj = raiseDiv0("quotInt");
1660 /* ToDo: protect against minInt / -1 errors
1661 * (repeat for all other division primops)
1668 int x = PopTaggedInt();
1669 int y = PopTaggedInt();
1671 obj = raiseDiv0("remInt");
1679 StgInt x = PopTaggedInt();
1680 StgInt y = PopTaggedInt();
1682 obj = raiseDiv0("quotRemInt");
1685 PushTaggedInt(x%y); /* last result */
1686 PushTaggedInt(x/y); /* first result */
1689 case i_negateInt: OP_I_I(-x); break;
1691 case i_andInt: OP_II_I(x&y); break;
1692 case i_orInt: OP_II_I(x|y); break;
1693 case i_xorInt: OP_II_I(x^y); break;
1694 case i_notInt: OP_I_I(~x); break;
1695 case i_shiftLInt: OP_IW_I(x<<y); break;
1696 case i_shiftRAInt: OP_IW_I(x>>y); break; /* ToDo */
1697 case i_shiftRLInt: OP_IW_I(x>>y); break; /* ToDo */
1699 #ifdef PROVIDE_INT64
1700 case i_gtInt64: OP_zz_B(x>y); break;
1701 case i_geInt64: OP_zz_B(x>=y); break;
1702 case i_eqInt64: OP_zz_B(x==y); break;
1703 case i_neInt64: OP_zz_B(x!=y); break;
1704 case i_ltInt64: OP_zz_B(x<y); break;
1705 case i_leInt64: OP_zz_B(x<=y); break;
1706 case i_minInt64: OP__z(0x800000000000LL); break;
1707 case i_maxInt64: OP__z(0x7fffffffffffLL); break;
1708 case i_plusInt64: OP_zz_z(x+y); break;
1709 case i_minusInt64: OP_zz_z(x-y); break;
1710 case i_timesInt64: OP_zz_z(x*y); break;
1713 StgInt64 x = PopTaggedInt64();
1714 StgInt64 y = PopTaggedInt64();
1716 obj = raiseDiv0("quotInt64");
1719 /* ToDo: protect against minInt64 / -1 errors
1720 * (repeat for all other division primops)
1722 PushTaggedInt64(x/y);
1727 StgInt64 x = PopTaggedInt64();
1728 StgInt64 y = PopTaggedInt64();
1730 obj = raiseDiv0("remInt64");
1733 PushTaggedInt64(x%y);
1736 case i_quotRemInt64:
1738 StgInt64 x = PopTaggedInt64();
1739 StgInt64 y = PopTaggedInt64();
1741 obj = raiseDiv0("quotRemInt64");
1744 PushTaggedInt64(x%y); /* last result */
1745 PushTaggedInt64(x/y); /* first result */
1748 case i_negateInt64: OP_z_z(-x); break;
1750 case i_andInt64: OP_zz_z(x&y); break;
1751 case i_orInt64: OP_zz_z(x|y); break;
1752 case i_xorInt64: OP_zz_z(x^y); break;
1753 case i_notInt64: OP_z_z(~x); break;
1754 case i_shiftLInt64: OP_zW_z(x<<y); break;
1755 case i_shiftRAInt64: OP_zW_z(x>>y); break; /* ToDo */
1756 case i_shiftRLInt64: OP_zW_z(x>>y); break; /* ToDo */
1758 case i_int64ToInt: OP_z_I(x); break;
1759 case i_intToInt64: OP_I_z(x); break;
1761 case i_int64ToWord: OP_z_W(x); break;
1762 case i_wordToInt64: OP_W_z(x); break;
1764 case i_int64ToFloat: OP_z_F(x); break;
1765 case i_floatToInt64: OP_F_z(x); break;
1766 case i_int64ToDouble: OP_z_D(x); break;
1767 case i_doubleToInt64: OP_D_z(x); break;
1770 case i_gtWord: OP_WW_B(x>y); break;
1771 case i_geWord: OP_WW_B(x>=y); break;
1772 case i_eqWord: OP_WW_B(x==y); break;
1773 case i_neWord: OP_WW_B(x!=y); break;
1774 case i_ltWord: OP_WW_B(x<y); break;
1775 case i_leWord: OP_WW_B(x<=y); break;
1776 case i_minWord: OP__W(0); break;
1777 case i_maxWord: OP__W(UINT_MAX); break;
1778 case i_plusWord: OP_WW_W(x+y); break;
1779 case i_minusWord: OP_WW_W(x-y); break;
1780 case i_timesWord: OP_WW_W(x*y); break;
1783 StgWord x = PopTaggedWord();
1784 StgWord y = PopTaggedWord();
1786 obj = raiseDiv0("quotWord");
1789 PushTaggedWord(x/y);
1794 StgWord x = PopTaggedWord();
1795 StgWord y = PopTaggedWord();
1797 obj = raiseDiv0("remWord");
1800 PushTaggedWord(x%y);
1805 StgWord x = PopTaggedWord();
1806 StgWord y = PopTaggedWord();
1808 obj = raiseDiv0("quotRemWord");
1811 PushTaggedWord(x%y); /* last result */
1812 PushTaggedWord(x/y); /* first result */
1815 case i_negateWord: OP_W_W(-x); break;
1816 case i_andWord: OP_WW_W(x&y); break;
1817 case i_orWord: OP_WW_W(x|y); break;
1818 case i_xorWord: OP_WW_W(x^y); break;
1819 case i_notWord: OP_W_W(~x); break;
1820 case i_shiftLWord: OP_WW_W(x<<y); break;
1821 case i_shiftRAWord: OP_WW_W(x>>y); break; /* ToDo */
1822 case i_shiftRLWord: OP_WW_W(x>>y); break; /* ToDo */
1823 case i_intToWord: OP_I_W(x); break;
1824 case i_wordToInt: OP_W_I(x); break;
1827 case i_gtAddr: OP_AA_B(x>y); break;
1828 case i_geAddr: OP_AA_B(x>=y); break;
1829 case i_eqAddr: OP_AA_B(x==y); break;
1830 case i_neAddr: OP_AA_B(x!=y); break;
1831 case i_ltAddr: OP_AA_B(x<y); break;
1832 case i_leAddr: OP_AA_B(x<=y); break;
1833 case i_intToAddr: OP_I_A((StgAddr)x); break; /* ToDo */
1834 case i_addrToInt: OP_A_I((StgInt)x); break; /* ToDo */
1836 case i_indexCharOffAddr: OP_AI_C(indexCharOffAddrzh(r,x,y)); break;
1837 case i_readCharOffAddr: OP_AI_C(indexCharOffAddrzh(r,x,y)); break;
1838 case i_writeCharOffAddr: OP_AIC_(writeCharOffAddrzh(x,y,z)); break;
1840 case i_indexIntOffAddr: OP_AI_I(indexIntOffAddrzh(r,x,y)); break;
1841 case i_readIntOffAddr: OP_AI_I(indexIntOffAddrzh(r,x,y)); break;
1842 case i_writeIntOffAddr: OP_AII_(writeIntOffAddrzh(x,y,z)); break;
1843 #ifdef PROVIDE_INT64
1844 case i_indexInt64OffAddr: OP_AI_z(indexInt64OffAddrzh(r,x,y)); break;
1845 case i_readInt64OffAddr: OP_AI_z(indexInt64OffAddrzh(r,x,y)); break;
1846 case i_writeInt64OffAddr: OP_AIz_(writeInt64OffAddrzh(x,y,z)); break;
1849 case i_indexAddrOffAddr: OP_AI_A(indexAddrOffAddrzh(r,x,y)); break;
1850 case i_readAddrOffAddr: OP_AI_A(indexAddrOffAddrzh(r,x,y)); break;
1851 case i_writeAddrOffAddr: OP_AIA_(writeAddrOffAddrzh(x,y,z)); break;
1853 case i_indexFloatOffAddr: OP_AI_F(indexFloatOffAddrzh(r,x,y)); break;
1854 case i_readFloatOffAddr: OP_AI_F(indexFloatOffAddrzh(r,x,y)); break;
1855 case i_writeFloatOffAddr: OP_AIF_(writeFloatOffAddrzh(x,y,z)); break;
1857 case i_indexDoubleOffAddr: OP_AI_D(indexDoubleOffAddrzh(r,x,y)); break;
1858 case i_readDoubleOffAddr: OP_AI_D(indexDoubleOffAddrzh(r,x,y)); break;
1859 case i_writeDoubleOffAddr: OP_AID_(writeDoubleOffAddrzh(x,y,z)); break;
1861 #ifdef PROVIDE_STABLE
1862 case i_indexStableOffAddr: OP_AI_s(indexStablePtrOffAddrzh(r,x,y)); break;
1863 case i_readStableOffAddr: OP_AI_s(indexStablePtrOffAddrzh(r,x,y)); break;
1864 case i_writeStableOffAddr: OP_AIs_(writeStablePtrOffAddrzh(x,y,z)); break;
1867 #endif /* PROVIDE_ADDR */
1869 #ifdef PROVIDE_INTEGER
1870 case i_compareInteger:
1872 mpz_ptr x = PopTaggedInteger();
1873 mpz_ptr y = PopTaggedInteger();
1874 StgInt r = mpz_cmp(x,y);
1875 PushTaggedInt(r<0 ? -1 : (r>0 ? 1 : 0));
1878 case i_negateInteger: OP_Z_Z(mpz_neg(r,x)); break;
1879 case i_plusInteger: OP_ZZ_Z(mpz_add(r,x,y)); break;
1880 case i_minusInteger: OP_ZZ_Z(mpz_sub(r,x,y)); break;
1881 case i_timesInteger: OP_ZZ_Z(mpz_mul(r,x,y)); break;
1882 case i_quotRemInteger:
1884 mpz_ptr x = PopTaggedInteger();
1885 mpz_ptr y = PopTaggedInteger();
1886 mpz_ptr q = mpz_alloc();
1887 mpz_ptr r = mpz_alloc();
1888 if (mpz_sgn(y) == 0) {
1889 obj = raiseDiv0("quotRemInteger");
1892 mpz_tdiv_qr(q,r,x,y);
1893 PushTaggedInteger(r); /* last result */
1894 PushTaggedInteger(q); /* first result */
1897 case i_divModInteger:
1899 mpz_ptr x = PopTaggedInteger();
1900 mpz_ptr y = PopTaggedInteger();
1901 mpz_ptr q = mpz_alloc();
1902 mpz_ptr r = mpz_alloc();
1903 if (mpz_sgn(y) == 0) {
1904 obj = raiseDiv0("divModInteger");
1907 mpz_fdiv_qr(q,r,x,y);
1908 PushTaggedInteger(r); /* last result */
1909 PushTaggedInteger(q); /* first result */
1912 case i_integerToInt: OP_Z_I(mpz_get_si(x)); break;
1913 case i_intToInteger: OP_I_Z(mpz_set_si(r,x)); break;
1914 #ifdef PROVIDE_INT64
1915 case i_integerToInt64: OP_Z_z(mpz_get_si(x)); break;
1916 case i_int64ToInteger: OP_z_Z(mpz_set_si(r,x)); break;
1919 /* NB Use of mpz_get_si is quite deliberate since otherwise
1920 * -255 is converted to 255.
1922 case i_integerToWord: OP_Z_W(mpz_get_si(x)); break;
1923 case i_wordToInteger: OP_W_Z(mpz_set_ui(r,x)); break;
1925 case i_integerToFloat: OP_Z_F(mpz_get_d(x)); break;
1926 case i_floatToInteger: OP_F_Z(mpz_set_d(r,x)); break;
1927 case i_integerToDouble: OP_Z_D(mpz_get_d(x)); break;
1928 case i_doubleToInteger: OP_D_Z(mpz_set_d(r,x)); break;
1929 #endif /* PROVIDE_INTEGER */
1931 case i_gtFloat: OP_FF_B(x>y); break;
1932 case i_geFloat: OP_FF_B(x>=y); break;
1933 case i_eqFloat: OP_FF_B(x==y); break;
1934 case i_neFloat: OP_FF_B(x!=y); break;
1935 case i_ltFloat: OP_FF_B(x<y); break;
1936 case i_leFloat: OP_FF_B(x<=y); break;
1937 case i_minFloat: OP__F(FLT_MIN); break;
1938 case i_maxFloat: OP__F(FLT_MAX); break;
1939 case i_radixFloat: OP__I(FLT_RADIX); break;
1940 case i_digitsFloat: OP__I(FLT_MANT_DIG); break;
1941 case i_minExpFloat: OP__I(FLT_MIN_EXP); break;
1942 case i_maxExpFloat: OP__I(FLT_MAX_EXP); break;
1943 case i_plusFloat: OP_FF_F(x+y); break;
1944 case i_minusFloat: OP_FF_F(x-y); break;
1945 case i_timesFloat: OP_FF_F(x*y); break;
1948 StgFloat x = PopTaggedFloat();
1949 StgFloat y = PopTaggedFloat();
1952 obj = raiseDiv0("divideFloat");
1956 PushTaggedFloat(x/y);
1959 case i_negateFloat: OP_F_F(-x); break;
1960 case i_floatToInt: OP_F_I(x); break;
1961 case i_intToFloat: OP_I_F(x); break;
1962 case i_expFloat: OP_F_F(exp(x)); break;
1963 case i_logFloat: OP_F_F(log(x)); break;
1964 case i_sqrtFloat: OP_F_F(sqrt(x)); break;
1965 case i_sinFloat: OP_F_F(sin(x)); break;
1966 case i_cosFloat: OP_F_F(cos(x)); break;
1967 case i_tanFloat: OP_F_F(tan(x)); break;
1968 case i_asinFloat: OP_F_F(asin(x)); break;
1969 case i_acosFloat: OP_F_F(acos(x)); break;
1970 case i_atanFloat: OP_F_F(atan(x)); break;
1971 case i_sinhFloat: OP_F_F(sinh(x)); break;
1972 case i_coshFloat: OP_F_F(cosh(x)); break;
1973 case i_tanhFloat: OP_F_F(tanh(x)); break;
1974 case i_powerFloat: OP_FF_F(pow(x,y)); break;
1976 #ifdef PROVIDE_INT64
1977 /* Based on old Hugs code */
1978 /* ToDo: use ~/fptools/ghc/runtime/prims/PrimArith.lc */
1979 case i_encodeFloatz: OP_zI_F(ldexp(x,y)); break;
1980 case i_decodeFloatz:
1982 /* ToDo: this code is known to give very approximate results
1983 * (even when StgInt64 overflow doesn't occur)
1985 double f0 = PopTaggedFloat();
1987 double f1 = frexp((double)(f0),&n); /* 0.5 <= f1 < 1 */
1988 double f2 = ldexp(f1,FLT_MANT_DIG); /* 2^m-1 <= f2 < 2^m, m=FLT_MANT_DIG */
1989 PushTaggedInt(n-FLT_MANT_DIG);
1990 PushTaggedInt64((StgInt64)f2);
1991 #if 1 /* paranoia */
1992 if (ldexp((StgInt64)f2,n-FLT_MANT_DIG) != f0) {
1993 fprintf(stderr,"*** primDecodeFloat mismatch: %.10f != %.10f\n",
1994 ldexp((StgInt64)f2,n-FLT_MANT_DIG),f0);
1999 #endif /* PROVIDE_INT64 */
2000 #ifdef PROVIDE_INTEGER
2001 case i_encodeFloatZ: OP_ZI_F(__encodeFloat(x,y)); break;
2002 case i_decodeFloatZ: OP_F_ZI(__decodeFloat(r1,&r2,x)); break;
2004 case i_isNaNFloat: OP_F_B(isFloatNaN(x)); break;
2005 case i_isInfiniteFloat: OP_F_B(isFloatInfinite(x)); break;
2006 case i_isNegativeZeroFloat: OP_F_B(isFloatNegativeZero(x)); break;
2007 case i_isDenormalizedFloat: OP_F_B(isFloatDenormalized(x)); break;
2008 case i_gtDouble: OP_DD_B(x>y); break;
2009 case i_geDouble: OP_DD_B(x>=y); break;
2010 case i_eqDouble: OP_DD_B(x==y); break;
2011 case i_neDouble: OP_DD_B(x!=y); break;
2012 case i_ltDouble: OP_DD_B(x<y); break;
2013 case i_leDouble: OP_DD_B(x<=y) break;
2014 case i_minDouble: OP__D(DBL_MIN); break;
2015 case i_maxDouble: OP__D(DBL_MAX); break;
2016 case i_radixDouble: OP__I(FLT_RADIX); break;
2017 case i_digitsDouble: OP__I(DBL_MANT_DIG); break;
2018 case i_minExpDouble: OP__I(DBL_MIN_EXP); break;
2019 case i_maxExpDouble: OP__I(DBL_MAX_EXP); break;
2020 case i_plusDouble: OP_DD_D(x+y); break;
2021 case i_minusDouble: OP_DD_D(x-y); break;
2022 case i_timesDouble: OP_DD_D(x*y); break;
2023 case i_divideDouble:
2025 StgDouble x = PopTaggedDouble();
2026 StgDouble y = PopTaggedDouble();
2029 obj = raiseDiv0("divideDouble");
2033 PushTaggedDouble(x/y);
2036 case i_negateDouble: OP_D_D(-x); break;
2037 case i_doubleToInt: OP_D_I(x); break;
2038 case i_intToDouble: OP_I_D(x); break;
2039 case i_doubleToFloat: OP_D_F(x); break;
2040 case i_floatToDouble: OP_F_F(x); break;
2041 case i_expDouble: OP_D_D(exp(x)); break;
2042 case i_logDouble: OP_D_D(log(x)); break;
2043 case i_sqrtDouble: OP_D_D(sqrt(x)); break;
2044 case i_sinDouble: OP_D_D(sin(x)); break;
2045 case i_cosDouble: OP_D_D(cos(x)); break;
2046 case i_tanDouble: OP_D_D(tan(x)); break;
2047 case i_asinDouble: OP_D_D(asin(x)); break;
2048 case i_acosDouble: OP_D_D(acos(x)); break;
2049 case i_atanDouble: OP_D_D(atan(x)); break;
2050 case i_sinhDouble: OP_D_D(sinh(x)); break;
2051 case i_coshDouble: OP_D_D(cosh(x)); break;
2052 case i_tanhDouble: OP_D_D(tanh(x)); break;
2053 case i_powerDouble: OP_DD_D(pow(x,y)); break;
2054 #ifdef PROVIDE_INT64
2055 case i_encodeDoublez: OP_zI_D(ldexp(x,y)); break;
2056 case i_decodeDoublez:
2058 /* ToDo: this code is known to give very approximate results
2059 * (even when StgInt64 overflow doesn't occur)
2061 double f0 = PopTaggedDouble();
2063 double f1 = frexp((double)(f0),&n); /* 0.5 <= f1 < 1 */
2064 double f2 = ldexp(f1,FLT_MANT_DIG); /* 2^m-1 <= f2 < 2^m, m=FLT_MANT_DIG */
2065 PushTaggedInt(n-FLT_MANT_DIG);
2066 PushTaggedInt64((StgInt64)f2);
2067 #if 1 /* paranoia */
2068 if (ldexp((StgInt64)f2,n-FLT_MANT_DIG) != f0) {
2069 fprintf(stderr,"*** primDecodeDouble mismatch: %.10f != %.10f\n",
2070 ldexp((StgInt64)f2,n-FLT_MANT_DIG),f0);
2075 #endif /* PROVIDE_INT64 */
2076 #ifdef PROVIDE_INTEGER
2077 case i_encodeDoubleZ: OP_ZI_D(__encodeDouble(x,y)); break;
2078 case i_decodeDoubleZ: OP_D_ZI(__decodeDouble(r1,&r2,x)); break;
2079 #endif /* PROVIDE_INTEGER */
2080 case i_isNaNDouble: OP_D_B(isDoubleNaN(x)); break;
2081 case i_isInfiniteDouble: OP_D_B(isDoubleInfinite(x)); break;
2082 case i_isNegativeZeroDouble: OP_D_B(isDoubleNegativeZero(x)); break;
2083 case i_isDenormalizedDouble: OP_D_B(isDoubleDenormalized(x)); break;
2084 case i_isIEEEDouble:
2086 PushTaggedBool(rtsTrue);
2090 barf("Unrecognised primop1");
2096 switch (bcoInstr(bco,pc++)) {
2097 case i_INTERNAL_ERROR2:
2098 barf("INTERNAL_ERROR2 at %p:%d",bco,pc-1);
2099 case i_catch: /* catch#{e,h} */
2105 /* catch suffers the same problem as takeMVar:
2106 * it tries to do control flow even if it isn't
2107 * the last instruction in the BCO.
2108 * This can leave a mess on the stack if the
2109 * last instructions are anything important
2110 * like SLIDE. Our vile hack depends on the
2111 * fact that with the current code generator,
2112 * we know exactly that i_catch is followed
2113 * by code that drops 2 variables off the
2122 case i_raise: /* raise#{err} */
2124 StgClosure* err = PopCPtr();
2125 obj = raiseAnError(err);
2128 case i_force: /* force#{x} (evaluate x, primreturn nothing) */
2133 /* force suffers the same problem as takeMVar:
2134 * it tries to do control flow even if it isn't
2135 * the last instruction in the BCO.
2136 * This can leave a mess on the stack if the
2137 * last instructions are anything important
2138 * like SLIDE. Our vile hack depends on the
2139 * fact that with the current code generator,
2140 * we know exactly that i_force is followed
2141 * by code that drops 1 variable off the stack.
2149 #ifdef PROVIDE_ARRAY
2152 StgClosure* init = PopCPtr();
2154 = stgCast(StgMutVar*,allocate(sizeofW(StgMutVar)));
2155 SET_HDR(mv,&MUT_VAR_info,CCCS);
2157 PushPtr(stgCast(StgPtr,mv));
2162 StgMutVar* mv = stgCast(StgMutVar*,PopPtr());
2168 StgMutVar* mv = stgCast(StgMutVar*,PopPtr());
2169 StgClosure* value = PopCPtr();
2175 nat n = PopTaggedInt(); /* or Word?? */
2176 StgClosure* init = PopCPtr();
2177 StgWord size = sizeofW(StgMutArrPtrs) + n;
2180 = stgCast(StgMutArrPtrs*,allocate(size));
2181 SET_HDR(arr,&MUT_ARR_PTRS_info,CCCS);
2183 for (i = 0; i < n; ++i) {
2184 arr->payload[i] = init;
2186 PushPtr(stgCast(StgPtr,arr));
2192 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
2193 nat i = PopTaggedInt(); /* or Word?? */
2194 StgWord n = arr->ptrs;
2196 obj = raiseIndex("{index,read}Array");
2199 PushCPtr(arr->payload[i]);
2204 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
2205 nat i = PopTaggedInt(); /* or Word? */
2206 StgClosure* v = PopCPtr();
2207 StgWord n = arr->ptrs;
2209 obj = raiseIndex("{index,read}Array");
2212 arr->payload[i] = v;
2216 case i_sizeMutableArray:
2218 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
2219 PushTaggedInt(arr->ptrs);
2222 case i_unsafeFreezeArray:
2224 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
2225 SET_INFO(arr,&MUT_ARR_PTRS_FROZEN_info);
2226 PushPtr(stgCast(StgPtr,arr));
2229 case i_unsafeFreezeByteArray:
2231 /* Delightfully simple :-) */
2235 case i_sameMutableArray:
2236 case i_sameMutableByteArray:
2238 StgPtr x = PopPtr();
2239 StgPtr y = PopPtr();
2240 PushTaggedBool(x==y);
2244 case i_newByteArray:
2246 nat n = PopTaggedInt(); /* or Word?? */
2247 StgInt words = (n+sizeof(W_)-1)/sizeof(W_);
2248 StgWord size = sizeofW(StgArrWords) + words;
2250 StgArrWords* arr = stgCast(StgArrWords*,allocate(size));
2251 SET_HDR(arr,&ARR_WORDS_info,CCCS);
2254 for (i = 0; i < n; ++i) {
2255 arr->payload[i] = 0xdeadbeef;
2258 PushPtr(stgCast(StgPtr,arr));
2262 /* Most of these generate alignment warnings on Sparcs and similar architectures.
2263 * These are harmless and are caused by the cast to C* in BYTE_ARR_CTS.
2265 case i_indexCharArray: OP_mI_ty(Char,"indexCharArray", indexCharArrayzh(r,x,i)); break;
2266 case i_readCharArray: OP_mI_ty(Char,"readCharArray", readCharArrayzh(r,x,i)); break;
2267 case i_writeCharArray: OP_mIty_(Char,"writeCharArray", writeCharArrayzh(x,i,z)); break;
2269 case i_indexIntArray: OP_mI_ty(Int,"indexIntArray", indexIntArrayzh(r,x,i)); break;
2270 case i_readIntArray: OP_mI_ty(Int,"readIntArray", readIntArrayzh(r,x,i)); break;
2271 case i_writeIntArray: OP_mIty_(Int,"writeIntArray", writeIntArrayzh(x,i,z)); break;
2272 #ifdef PROVIDE_INT64
2273 case i_indexInt64Array: OP_mI_ty(Int64,"indexInt64Array", indexInt64Arrayzh(r,x,i)); break;
2274 case i_readInt64Array: OP_mI_ty(Int64,"readInt64Array", readInt64Arrayzh(r,x,i)); break;
2275 case i_writeInt64Array: OP_mIty_(Int64,"writeInt64Array", writeInt64Arrayzh(x,i,z)); break;
2278 case i_indexAddrArray: OP_mI_ty(Addr,"indexAddrArray", indexAddrArrayzh(r,x,i)); break;
2279 case i_readAddrArray: OP_mI_ty(Addr,"readAddrArray", readAddrArrayzh(r,x,i)); break;
2280 case i_writeAddrArray: OP_mIty_(Addr,"writeAddrArray", writeAddrArrayzh(x,i,z)); break;
2282 case i_indexFloatArray: OP_mI_ty(Float,"indexFloatArray", indexFloatArrayzh(r,x,i)); break;
2283 case i_readFloatArray: OP_mI_ty(Float,"readFloatArray", readFloatArrayzh(r,x,i)); break;
2284 case i_writeFloatArray: OP_mIty_(Float,"writeFloatArray", writeFloatArrayzh(x,i,z)); break;
2286 case i_indexDoubleArray: OP_mI_ty(Double,"indexDoubleArray", indexDoubleArrayzh(r,x,i)); break;
2287 case i_readDoubleArray: OP_mI_ty(Double,"readDoubleArray", readDoubleArrayzh(r,x,i)); break;
2288 case i_writeDoubleArray: OP_mIty_(Double,"writeDoubleArray", writeDoubleArrayzh(x,i,z)); break;
2290 #ifdef PROVIDE_STABLE
2291 case i_indexStableArray: OP_mI_ty(StablePtr,"indexStableArray", indexStablePtrArrayzh(r,x,i)); break;
2292 case i_readStableArray: OP_mI_ty(StablePtr,"readStableArray", readStablePtrArrayzh(r,x,i)); break;
2293 case i_writeStableArray: OP_mIty_(StablePtr,"writeStableArray", writeStablePtrArrayzh(x,i,z)); break;
2296 #endif /* PROVIDE_ARRAY */
2297 #ifdef PROVIDE_COERCE
2298 case i_unsafeCoerce:
2300 /* Another nullop */
2304 #ifdef PROVIDE_PTREQUALITY
2305 case i_reallyUnsafePtrEquality:
2306 { /* identical to i_sameRef */
2307 StgPtr x = PopPtr();
2308 StgPtr y = PopPtr();
2309 PushTaggedBool(x==y);
2313 #ifdef PROVIDE_FOREIGN
2314 /* ForeignObj# operations */
2315 case i_makeForeignObj:
2317 StgForeignObj *result
2318 = stgCast(StgForeignObj*,allocate(sizeofW(StgForeignObj)));
2319 SET_HDR(result,&FOREIGN_info,CCCS);
2320 result -> data = PopTaggedAddr();
2321 PushPtr(stgCast(StgPtr,result));
2324 #endif /* PROVIDE_FOREIGN */
2329 = stgCast(StgWeak*,allocate(sizeofW(StgWeak)));
2330 SET_HDR(w, &WEAK_info, CCCS);
2332 w->value = PopCPtr();
2333 w->finalizer = PopCPtr();
2334 w->link = weak_ptr_list;
2336 IF_DEBUG(weak, fprintf(stderr,"New weak pointer at %p\n",w));
2337 PushPtr(stgCast(StgPtr,w));
2342 StgWeak *w = stgCast(StgWeak*,PopPtr());
2343 if (w->header.info == &WEAK_info) {
2344 PushCPtr(w->value); /* last result */
2345 PushTaggedInt(1); /* first result */
2347 PushPtr(stgCast(StgPtr,w)); /* ToDo: error thunk would be better */
2352 #endif /* PROVIDE_WEAK */
2353 #ifdef PROVIDE_STABLE
2354 /* StablePtr# operations */
2355 case i_makeStablePtr:
2356 case i_deRefStablePtr:
2357 case i_freeStablePtr:
2358 { fprintf(stderr,"Evaluator.c:stablePtrOp unimp\n" );
2363 case i_makeStablePtr:
2365 StgStablePtr stable_ptr;
2366 if (stable_ptr_free == NULL) {
2367 enlargeStablePtrTable();
2370 stable_ptr = stable_ptr_free - stable_ptr_table;
2371 stable_ptr_free = (P_*)*stable_ptr_free;
2372 stable_ptr_table[stable_ptr] = PopPtr();
2374 PushTaggedStablePtr(stable_ptr);
2377 case i_deRefStablePtr:
2379 StgStablePtr stable_ptr = PopTaggedStablePtr();
2380 PushPtr(stable_ptr_table[stable_ptr]);
2384 case i_freeStablePtr:
2386 StgStablePtr stable_ptr = PopTaggedStablePtr();
2387 stable_ptr_table[stable_ptr] = (P_)stable_ptr_free;
2388 stable_ptr_free = stable_ptr_table + stable_ptr;
2394 #endif /* PROVIDE_STABLE */
2395 #ifdef PROVIDE_CONCURRENT
2398 StgClosure* c = PopCPtr();
2399 StgTSO* t = createGenThread(RtsFlags.GcFlags.initialStkSize,c);
2400 PushPtr(stgCast(StgPtr,t));
2402 /* switch at the earliest opportunity */
2404 /* but don't automatically switch to GHC - or you'll waste your
2405 * time slice switching back.
2407 * Actually, there's more to it than that: the default
2408 * (ThreadEnterGHC) causes the thread to crash - don't
2409 * understand why. - ADR
2411 t->whatNext = ThreadEnterHugs;
2416 StgTSO* tso = stgCast(StgTSO*,PopPtr());
2418 if (tso == CurrentTSO) { /* suicide */
2419 return ThreadFinished;
2424 { /* identical to i_sameRef */
2425 StgPtr x = PopPtr();
2426 StgPtr y = PopPtr();
2427 PushTaggedBool(x==y);
2432 StgMVar *mvar = stgCast(StgMVar*,allocate(sizeofW(StgMVar)));
2433 SET_INFO(mvar,&EMPTY_MVAR_info);
2434 mvar->head = mvar->tail = EndTSOQueue;
2435 /* ToDo: this is a little strange */
2436 mvar->value = stgCast(StgClosure*,&END_TSO_QUEUE_closure);
2437 PushPtr(stgCast(StgPtr,mvar));
2442 ToDo: another way out of the problem might be to add an explicit
2443 continuation to primTakeMVar: takeMVar v = primTakeMVar v takeMVar.
2444 The problem with this plan is that now I dont know how much to chop
2449 StgMVar *mvar = stgCast(StgMVar*,PopPtr());
2450 /* If the MVar is empty, put ourselves
2451 * on its blocking queue, and wait
2452 * until we're woken up.
2454 if (GET_INFO(mvar) != &FULL_MVAR_info) {
2455 if (mvar->head == EndTSOQueue) {
2456 mvar->head = CurrentTSO;
2458 mvar->tail->link = CurrentTSO;
2460 CurrentTSO->link = EndTSOQueue;
2461 mvar->tail = CurrentTSO;
2463 /* Hack, hack, hack.
2464 * When we block, we push a restart closure
2465 * on the stack - but which closure?
2466 * We happen to know that the BCO we're
2467 * executing looks like this:
2476 * 14: ALLOC_CONSTR 0x8213a80
2486 * so we rearrange the stack to look the
2487 * way it did when we entered this BCO
2489 * What a disgusting hack!
2495 return ThreadBlocked;
2498 PushCPtr(mvar->value);
2499 SET_INFO(mvar,&EMPTY_MVAR_info);
2500 /* ToDo: this is a little strange */
2501 mvar->value = (StgClosure*)&END_TSO_QUEUE_closure;
2508 StgMVar* mvar = stgCast(StgMVar*,PopPtr());
2509 StgClosure* value = PopCPtr();
2510 if (GET_INFO(mvar) == &FULL_MVAR_info) {
2511 obj = raisePrim("putMVar {full MVar}");
2514 /* wake up the first thread on the
2515 * queue, it will continue with the
2516 * takeMVar operation and mark the
2519 StgTSO* tso = mvar->head;
2520 SET_INFO(mvar,&FULL_MVAR_info);
2521 mvar->value = value;
2522 if (tso != EndTSOQueue) {
2523 PUSH_ON_RUN_QUEUE(tso);
2524 mvar->head = tso->link;
2525 tso->link = EndTSOQueue;
2526 if (mvar->head == EndTSOQueue) {
2527 mvar->tail = EndTSOQueue;
2531 /* yield for better communication performance */
2538 /* As PrimOps.h says: Hmm, I'll think about these later. */
2541 #endif /* PROVIDE_CONCURRENT */
2545 CFunDescriptor* descriptor = PopTaggedAddr();
2546 StgAddr funPtr = PopTaggedAddr();
2547 ccall(descriptor,funPtr);
2551 barf("Unrecognised primop2");
2556 barf("Unrecognised instruction");
2559 barf("Ran off the end of bco - yoiks");
2564 StgCAF* caf = stgCast(StgCAF*,obj);
2565 if (Sp - sizeofW(StgUpdateFrame) < SpLim) {
2566 PushCPtr(obj); /* code to restart with */
2567 return StackOverflow;
2569 /* ToDo: look for Sp==Su && stackInt(0) == UPD_FRAME and insert an indirection immediately */
2571 /*was StgBlackHole* */
2572 StgBlockingQueue* bh
2573 = stgCast(StgBlockingQueue*,grabHpUpd(BLACKHOLE_sizeW()));
2574 SET_INFO(bh,&CAF_BLACKHOLE_info);
2575 bh->blocking_queue = EndTSOQueue;
2576 IF_DEBUG(gccafs,fprintf(stderr,"Created CAF_BLACKHOLE %p for CAF %p in evaluator\n",bh,caf));
2577 SET_INFO(caf,&CAF_ENTERED_info);
2578 caf->value = stgCast(StgClosure*,bh);
2579 PUSH_UPD_FRAME(bh,0);
2580 Sp -= sizeofW(StgUpdateFrame);
2582 caf->link = enteredCAFs;
2589 StgCAF* caf = stgCast(StgCAF*,obj);
2590 obj = caf->value; /* it's just a fancy indirection */
2596 /*was StgBlackHole* */
2597 StgBlockingQueue* bh = stgCast(StgBlockingQueue*,obj);
2598 /* Put ourselves on the blocking queue for this black hole and block */
2599 CurrentTSO->link = bh->blocking_queue;
2600 bh->blocking_queue = CurrentTSO;
2601 PushCPtr(obj); /* code to restart with */
2602 return ThreadBlocked;
2606 StgAP_UPD* ap = stgCast(StgAP_UPD*,obj);
2608 if (Sp - (i + sizeofW(StgUpdateFrame)) < SpLim) {
2609 PushCPtr(obj); /* code to restart with */
2610 return StackOverflow;
2612 /* ToDo: look for Sp==Su && stackInt(0) == UPD_FRAME and insert an indirection immediately */
2613 PUSH_UPD_FRAME(ap,0);
2614 Sp -= sizeofW(StgUpdateFrame);
2616 PushWord(payloadWord(ap,i));
2619 #ifndef LAZY_BLACKHOLING
2621 /* superfluous - but makes debugging easier */
2622 StgBlackHole* bh = stgCast(StgBlackHole*,ap);
2623 SET_INFO(bh,&BLACKHOLE_info);
2624 bh->blocking_queue = EndTSOQueue;
2625 IF_DEBUG(gccafs,fprintf(stderr,"Eagerly blackholed AP_UPD %p in evaluator\n",bh));
2628 #endif /* LAZY_BLACKHOLING */
2633 StgPAP* pap = stgCast(StgPAP*,obj);
2634 int i = pap->n_args; /* ToDo: stack check */
2635 /* ToDo: if PAP is in whnf, we can update any update frames
2639 PushWord(payloadWord(pap,i));
2646 obj = stgCast(StgInd*,obj)->indirectee;
2650 case CONSTR_INTLIKE:
2651 case CONSTR_CHARLIKE:
2653 case CONSTR_NOCAF_STATIC:
2656 switch (get_itbl(stgCast(StgClosure*,Sp))->type) {
2661 PopUpdateFrame(obj);
2671 /*fprintf(stderr,"Sp = %p\tSu = %p\n", Sp, Su);*/
2672 /*printStack(Sp,CurrentTSO->stack+CurrentTSO->stack_size,Su);*/
2675 return ThreadFinished;
2686 case RET_SMALL: /* return to GHC */
2690 barf("todo: RET_[VEC_]{BIG,SMALL}");
2692 belch("entered CONSTR with invalid continuation on stack");
2694 printObj(stgCast(StgClosure*,Sp))
2696 barf("bailing out");
2702 CurrentTSO->whatNext = ThreadEnterGHC;
2703 PushCPtr(obj); /* code to restart with */
2704 return ThreadYielding;
2707 barf("Ran off the end of enter - yoiks");
2710 /* -----------------------------------------------------------------------------
2711 * ccall support code:
2712 * marshall moves args from C stack to Haskell stack
2713 * unmarshall moves args from Haskell stack to C stack
2714 * argSize calculates how much space you need on the C stack
2715 * ---------------------------------------------------------------------------*/
2717 /* Pop arguments off the C stack and Push them onto the Hugs stack.
2718 * Used when preparing for C calling Haskell or in response to
2719 * Haskell calling C.
2721 nat marshall(char arg_ty, void* arg)
2725 PushTaggedInt(*((int*)arg));
2726 return ARG_SIZE(INT_TAG);
2727 #ifdef PROVIDE_INT64
2729 PushTaggedInt64(*((StgInt64*)arg));
2730 return ARG_SIZE(INT64_TAG);
2732 #ifdef TODO_PROVIDE_INTEGER
2734 PushTaggedInteger(*((mpz_ptr*)arg));
2735 return ARG_SIZE(INTEGER_TAG);
2739 PushTaggedWord(*((unsigned int*)arg));
2740 return ARG_SIZE(WORD_TAG);
2743 PushTaggedChar(*((char*)arg));
2744 return ARG_SIZE(CHAR_TAG);
2746 PushTaggedFloat(*((float*)arg));
2747 return ARG_SIZE(FLOAT_TAG);
2749 PushTaggedDouble(*((double*)arg));
2750 return ARG_SIZE(DOUBLE_TAG);
2753 PushTaggedAddr(*((void**)arg));
2754 return ARG_SIZE(ADDR_TAG);
2757 PushTaggedStablePtr(*((StgStablePtr*)arg));
2758 return ARG_SIZE(STABLE_TAG);
2760 /* Not allowed in this direction - you have to
2761 * call makeForeignPtr explicitly
2763 barf("marshall: ForeignPtr#\n");
2765 #ifdef PROVIDE_ARRAY
2769 /* Not allowed in this direction */
2770 barf("marshall: [Mutable]ByteArray#\n");
2773 barf("marshall: unrecognised arg type %d\n",arg_ty);
2778 /* Pop arguments off the Hugs stack and Push them onto the C stack.
2779 * Used when preparing for Haskell calling C or in response to
2780 * C calling Haskell.
2782 nat unmarshall(char res_ty, void* res)
2786 *((int*)res) = PopTaggedInt();
2787 return ARG_SIZE(INT_TAG);
2788 #ifdef PROVIDE_INT64
2790 *((StgInt64*)res) = PopTaggedInt64();
2791 return ARG_SIZE(INT64_TAG);
2793 #ifdef TODO_PROVIDE_INTEGER
2795 *((mpz_ptr*)res) = PopTaggedInteger();
2796 return ARG_SIZE(INTEGER_TAG);
2800 *((unsigned int*)res) = PopTaggedWord();
2801 return ARG_SIZE(WORD_TAG);
2804 *((int*)res) = PopTaggedChar();
2805 return ARG_SIZE(CHAR_TAG);
2807 *((float*)res) = PopTaggedFloat();
2808 return ARG_SIZE(FLOAT_TAG);
2810 *((double*)res) = PopTaggedDouble();
2811 return ARG_SIZE(DOUBLE_TAG);
2814 *((void**)res) = PopTaggedAddr();
2815 return ARG_SIZE(ADDR_TAG);
2818 *((StgStablePtr*)res) = PopTaggedStablePtr();
2819 return ARG_SIZE(STABLE_TAG);
2822 StgForeignObj *result = stgCast(StgForeignObj*,PopPtr());
2823 *((void**)res) = result->data;
2824 return sizeofW(StgPtr);
2826 #ifdef PROVIDE_ARRAY
2831 StgMutArrPtrs* arr = stgCast(StgMutArrPtrs*,PopPtr());
2832 *((void**)res) = stgCast(void*,&(arr->payload));
2833 return sizeofW(StgPtr);
2836 barf("unmarshall: unrecognised result type %d\n",res_ty);
2840 nat argSize( const char* ks )
2843 for( ; *ks != '\0'; ++ks) {
2846 sz += sizeof(StgWord) * ARG_SIZE(INT_TAG);
2848 #ifdef PROVIDE_INT64
2850 sz += sizeof(StgWord) * ARG_SIZE(INT64_TAG);
2853 #ifdef TODO_PROVIDE_INTEGER
2855 sz += sizeof(StgWord) * ARG_SIZE(INTEGER_TAG);
2860 sz += sizeof(StgWord) * ARG_SIZE(WORD_TAG);
2864 sz += sizeof(StgWord) * ARG_SIZE(CHAR_TAG);
2867 sz += sizeof(StgWord) * ARG_SIZE(FLOAT_TAG);
2870 sz += sizeof(StgWord) * ARG_SIZE(DOUBLE_TAG);
2874 sz += sizeof(StgWord) * ARG_SIZE(ADDR_TAG);
2877 #ifdef PROVIDE_STABLE
2879 sz += sizeof(StgWord) * ARG_SIZE(STABLE_TAG);
2882 #ifdef PROVIDE_FOREIGN
2885 #ifdef PROVIDE_ARRAY
2889 sz += sizeof(StgPtr);
2892 barf("argSize: unrecognised result type %d\n",*ks);
2899 #endif /* INTERPRETER */