-# endif /* ndef REFERENCE_INTERPRETER */
-
- /* Handle arg check failure. General case: copy the
- spare args into a PAP frame. */
- pap = (StgPAP*)allocate_UPD(PAP_sizeW(arg_words_avail));
- SET_HDR(pap,&stg_PAP_info,CCS_SYSTEM/*ToDo*/);
- pap->n_args = arg_words_avail;
- pap->fun = obj;
- for (i = 0; i < arg_words_avail; i++)
- pap->payload[i] = (StgClosure*)StackWord(i);
-
- /* Push on the stack and defer to the scheduler. */
- iSp = (StgPtr)iSu;
- iSp --;
- StackWord(0) = (W_)pap;
- IF_DEBUG(evaluator,
- fprintf(stderr,"\tBuilt ");
- printObj((StgClosure*)pap);
- );
- cap->rCurrentTSO->what_next = ThreadEnterGHC;
- RETURN(ThreadYielding);
- }
- case bci_PUSH_L: {
- int o1 = BCO_NEXT;
- ASSERT((W_*)iSp+o1 < (W_*)iSu);
- StackWord(-1) = StackWord(o1);
- iSp--;
- do_print_stack = 0;
- goto nextInsn;
- }
- case bci_PUSH_LL: {
- int o1 = BCO_NEXT;
- int o2 = BCO_NEXT;
- ASSERT((W_*)iSp+o1 < (W_*)iSu);
- ASSERT((W_*)iSp+o2 < (W_*)iSu);
- StackWord(-1) = StackWord(o1);
- StackWord(-2) = StackWord(o2);
- iSp -= 2;
- goto nextInsn;
- }
- case bci_PUSH_LLL: {
- int o1 = BCO_NEXT;
- int o2 = BCO_NEXT;
- int o3 = BCO_NEXT;
- ASSERT((W_*)iSp+o1 < (W_*)iSu);
- ASSERT((W_*)iSp+o2 < (W_*)iSu);
- ASSERT((W_*)iSp+o3 < (W_*)iSu);
- StackWord(-1) = StackWord(o1);
- StackWord(-2) = StackWord(o2);
- StackWord(-3) = StackWord(o3);
- iSp -= 3;
- goto nextInsn;
- }
- case bci_PUSH_G: {
- int o1 = BCO_NEXT;
- StackWord(-1) = BCO_PTR(o1);
- iSp -= 1;
- goto nextInsn;
- }
- case bci_PUSH_AS: {
- int o_bco = BCO_NEXT;
- int o_itbl = BCO_NEXT;
- StackWord(-2) = BCO_LIT(o_itbl);
- StackWord(-1) = BCO_PTR(o_bco);
- iSp -= 2;
- goto nextInsn;
- }
- case bci_PUSH_UBX: {
- int i;
- int o_lits = BCO_NEXT;
- int n_words = BCO_NEXT;
- iSp -= n_words;
- for (i = 0; i < n_words; i++)
- StackWord(i) = BCO_LIT(o_lits+i);
- do_print_stack = 0;
- goto nextInsn;
- }
- case bci_PUSH_TAG: {
- W_ tag = (W_)(BCO_NEXT);
- StackWord(-1) = tag;
- iSp --;
- goto nextInsn;
- }
- case bci_SLIDE: {
- int n = BCO_NEXT;
- int by = BCO_NEXT;
- ASSERT((W_*)iSp+n+by <= (W_*)iSu);
- /* a_1, .. a_n, b_1, .. b_by, s => a_1, .. a_n, s */
- while(--n >= 0) {
- StackWord(n+by) = StackWord(n);
- }
- iSp += by;
-# ifdef INTERP_STATS
- it_slides++;
-# endif
- goto nextInsn;
- }
- case bci_ALLOC: {
- StgAP_UPD* ap;
- int n_payload = BCO_NEXT - 1;
- int request = AP_sizeW(n_payload);
- ap = (StgAP_UPD*)allocate_UPD(request);
- StackWord(-1) = (W_)ap;
- ap->n_args = n_payload;
- SET_HDR(ap, &stg_AP_UPD_info, ??)
- iSp --;
- goto nextInsn;
- }
- case bci_MKAP: {
- int i;
- int stkoff = BCO_NEXT;
- int n_payload = BCO_NEXT - 1;
- StgAP_UPD* ap = (StgAP_UPD*)StackWord(stkoff);
- ASSERT((int)ap->n_args == n_payload);
- ap->fun = (StgClosure*)StackWord(0);
- for (i = 0; i < n_payload; i++)
- ap->payload[i] = (StgClosure*)StackWord(i+1);
- iSp += n_payload+1;
- IF_DEBUG(evaluator,
- fprintf(stderr,"\tBuilt ");
- printObj((StgClosure*)ap);
- );
- goto nextInsn;
- }
- case bci_UNPACK: {
- /* Unpack N ptr words from t.o.s constructor */
- /* The common case ! */
- int i;
- int n_words = BCO_NEXT;
- StgClosure* con = (StgClosure*)StackWord(0);
- iSp -= n_words;
- for (i = 0; i < n_words; i++)
- StackWord(i) = (W_)con->payload[i];
- goto nextInsn;
- }
- case bci_UPK_TAG: {
- /* Unpack N (non-ptr) words from offset M in the
- constructor K words down the stack, and then push
- N as a tag, on top of it. Slow but general; we
- hope it will be the rare case. */
- int i;
- int n_words = BCO_NEXT;
- int con_off = BCO_NEXT;
- int stk_off = BCO_NEXT;
- StgClosure* con = (StgClosure*)StackWord(stk_off);
- iSp -= n_words;
- for (i = 0; i < n_words; i++)
- StackWord(i) = (W_)con->payload[con_off + i];
- iSp --;
- StackWord(0) = n_words;
- goto nextInsn;
- }
- case bci_PACK: {
- int i;
- int o_itbl = BCO_NEXT;
- int n_words = BCO_NEXT;
- StgInfoTable* itbl = INFO_PTR_TO_STRUCT(BCO_ITBL(o_itbl));
- int request = CONSTR_sizeW( itbl->layout.payload.ptrs,
- itbl->layout.payload.nptrs );
- StgClosure* con = (StgClosure*)allocate_NONUPD(request);
- ASSERT( itbl->layout.payload.ptrs + itbl->layout.payload.nptrs > 0);
- SET_HDR(con, BCO_ITBL(o_itbl), CCS_SYSTEM/*ToDo*/);
- for (i = 0; i < n_words; i++)
- con->payload[i] = (StgClosure*)StackWord(i);
- iSp += n_words;
- iSp --;
- StackWord(0) = (W_)con;
- IF_DEBUG(evaluator,
- fprintf(stderr,"\tBuilt ");
- printObj((StgClosure*)con);
- );
- goto nextInsn;
- }
- case bci_TESTLT_P: {
- int discr = BCO_NEXT;
- int failto = BCO_NEXT;
- StgClosure* con = (StgClosure*)StackWord(0);
- if (constrTag(con) >= discr)
- bciPtr = failto;
- goto nextInsn;
- }
- case bci_TESTEQ_P: {
- int discr = BCO_NEXT;
- int failto = BCO_NEXT;
- StgClosure* con = (StgClosure*)StackWord(0);
- if (constrTag(con) != discr)
- bciPtr = failto;
- goto nextInsn;
- }
- case bci_TESTLT_I: {
- /* The top thing on the stack should be a tagged int. */
- int discr = BCO_NEXT;
- int failto = BCO_NEXT;
- I_ stackInt = (I_)StackWord(1);
- ASSERT(1 == StackWord(0));
- if (stackInt >= (I_)BCO_LIT(discr))
- bciPtr = failto;
- goto nextInsn;
- }
- case bci_TESTEQ_I: {
- /* The top thing on the stack should be a tagged int. */
- int discr = BCO_NEXT;
- int failto = BCO_NEXT;
- I_ stackInt = (I_)StackWord(1);
- ASSERT(1 == StackWord(0));
- if (stackInt != (I_)BCO_LIT(discr))
- bciPtr = failto;
- goto nextInsn;
- }
- case bci_TESTLT_D: {
- /* The top thing on the stack should be a tagged double. */
- int discr = BCO_NEXT;
- int failto = BCO_NEXT;
- StgDouble stackDbl, discrDbl;
- ASSERT(sizeofW(StgDouble) == StackWord(0));
- stackDbl = PK_DBL( & StackWord(1) );
- discrDbl = PK_DBL( & BCO_LIT(discr) );
- if (stackDbl >= discrDbl)
- bciPtr = failto;
- goto nextInsn;
- }
- case bci_TESTEQ_D: {
- /* The top thing on the stack should be a tagged double. */
- int discr = BCO_NEXT;
- int failto = BCO_NEXT;
- StgDouble stackDbl, discrDbl;
- ASSERT(sizeofW(StgDouble) == StackWord(0));
- stackDbl = PK_DBL( & StackWord(1) );
- discrDbl = PK_DBL( & BCO_LIT(discr) );
- if (stackDbl != discrDbl)
- bciPtr = failto;
- goto nextInsn;
- }
-
- /* Control-flow ish things */
- case bci_ENTER: {
- goto nextEnter;
- }
- case bci_RETURN: {
- /* Figure out whether returning to interpreted or
- compiled code. */
- int o_itoc_itbl = BCO_NEXT;
- int tag = StackWord(0);
- StgInfoTable* ret_itbl = (StgInfoTable*)StackWord(tag +1);
- ASSERT(tag <= 2); /* say ... */
- if (ret_itbl == (StgInfoTable*)&stg_ctoi_ret_R1p_info
- || ret_itbl == (StgInfoTable*)&stg_ctoi_ret_R1n_info
- || ret_itbl == (StgInfoTable*)&stg_ctoi_ret_F1_info
- || ret_itbl == (StgInfoTable*)&stg_ctoi_ret_D1_info) {
- /* Returning to interpreted code. Interpret the BCO
- immediately underneath the itbl. */
- StgBCO* ret_bco = (StgBCO*)StackWord(tag +1+1);
- iSp --;
- StackWord(0) = (W_)ret_bco;
- goto nextEnter;
- } else {
- /* Returning (unboxed value) to compiled code.
- Replace tag with a suitable itbl and ask the
- scheduler to run it. The itbl code will copy
- the TOS value into R1/F1/D1 and do a standard
- compiled-code return. */
- StgInfoTable* magic_itbl = BCO_ITBL(o_itoc_itbl);
- StackWord(0) = (W_)magic_itbl;
- cap->rCurrentTSO->what_next = ThreadRunGHC;
- RETURN(ThreadYielding);
- }
- }
-
- case bci_CASEFAIL:
- barf("interpretBCO: hit a CASEFAIL");
-
- /* As yet unimplemented */
- case bci_TESTLT_F:
- case bci_TESTEQ_F:
-
- /* Errors */
- default:
- barf("interpretBCO: unknown or unimplemented opcode");
-
- } /* switch on opcode */
-
- barf("interpretBCO: fell off end of insn loop");
-
- }
- /* ---------------------------------------------------- */
- /* End of the bytecode interpreter */
- /* ---------------------------------------------------- */
-
- defer_to_sched:
- default: {
-# ifdef INTERP_STATS
- { int j = get_itbl(obj)->type;
- ASSERT(j >= 0 && j < N_CLOSURE_TYPES);
- it_unknown_entries[j]++;
- it_total_unknown_entries++;
- }
-# endif
-
- /* Can't handle this object; yield to sched. */
- IF_DEBUG(evaluator,
- fprintf(stderr, "entering unknown closure -- yielding to sched\n");
- printObj(obj);
- );
- iSp--; StackWord(0) = (W_)obj;
- cap->rCurrentTSO->what_next = ThreadEnterGHC;
- RETURN(ThreadYielding);
- }
- } /* switch on object kind */
-
- barf("fallen off end of object-type switch in interpretBCO()");
-}
+ INTERP_TICK(it_insns);
+
+#ifdef INTERP_STATS
+ ASSERT( (int)instrs[bciPtr] >= 0 && (int)instrs[bciPtr] < 27 );
+ it_ofreq[ (int)instrs[bciPtr] ] ++;
+ it_oofreq[ it_lastopc ][ (int)instrs[bciPtr] ] ++;
+ it_lastopc = (int)instrs[bciPtr];
+#endif
+
+ switch (BCO_NEXT) {
+
+ case bci_STKCHECK: {
+ // Explicit stack check at the beginning of a function
+ // *only* (stack checks in case alternatives are
+ // propagated to the enclosing function).
+ int stk_words_reqd = BCO_NEXT + 1;
+ if (Sp - stk_words_reqd < SpLim) {
+ Sp -= 2;
+ Sp[1] = (W_)obj;
+ Sp[0] = (W_)&stg_apply_interp_info;
+ RETURN_TO_SCHEDULER(ThreadInterpret, StackOverflow);
+ } else {
+ goto nextInsn;
+ }
+ }
+
+ case bci_PUSH_L: {
+ int o1 = BCO_NEXT;
+ Sp[-1] = Sp[o1];
+ Sp--;
+ goto nextInsn;
+ }
+
+ case bci_PUSH_LL: {
+ int o1 = BCO_NEXT;
+ int o2 = BCO_NEXT;
+ Sp[-1] = Sp[o1];
+ Sp[-2] = Sp[o2];
+ Sp -= 2;
+ goto nextInsn;
+ }
+
+ case bci_PUSH_LLL: {
+ int o1 = BCO_NEXT;
+ int o2 = BCO_NEXT;
+ int o3 = BCO_NEXT;
+ Sp[-1] = Sp[o1];
+ Sp[-2] = Sp[o2];
+ Sp[-3] = Sp[o3];
+ Sp -= 3;
+ goto nextInsn;
+ }
+
+ case bci_PUSH_G: {
+ int o1 = BCO_NEXT;
+ Sp[-1] = BCO_PTR(o1);
+ Sp -= 1;
+ goto nextInsn;
+ }
+
+ case bci_PUSH_ALTS: {
+ int o_bco = BCO_NEXT;
+ Sp[-2] = (W_)&stg_ctoi_R1p_info;
+ Sp[-1] = BCO_PTR(o_bco);
+ Sp -= 2;
+ goto nextInsn;
+ }
+
+ case bci_PUSH_ALTS_P: {
+ int o_bco = BCO_NEXT;
+ Sp[-2] = (W_)&stg_ctoi_R1unpt_info;
+ Sp[-1] = BCO_PTR(o_bco);
+ Sp -= 2;
+ goto nextInsn;
+ }
+
+ case bci_PUSH_ALTS_N: {
+ int o_bco = BCO_NEXT;
+ Sp[-2] = (W_)&stg_ctoi_R1n_info;
+ Sp[-1] = BCO_PTR(o_bco);
+ Sp -= 2;
+ goto nextInsn;
+ }
+
+ case bci_PUSH_ALTS_F: {
+ int o_bco = BCO_NEXT;
+ Sp[-2] = (W_)&stg_ctoi_F1_info;
+ Sp[-1] = BCO_PTR(o_bco);
+ Sp -= 2;
+ goto nextInsn;
+ }
+
+ case bci_PUSH_ALTS_D: {
+ int o_bco = BCO_NEXT;
+ Sp[-2] = (W_)&stg_ctoi_D1_info;
+ Sp[-1] = BCO_PTR(o_bco);
+ Sp -= 2;
+ goto nextInsn;
+ }
+
+ case bci_PUSH_ALTS_L: {
+ int o_bco = BCO_NEXT;
+ Sp[-2] = (W_)&stg_ctoi_L1_info;
+ Sp[-1] = BCO_PTR(o_bco);
+ Sp -= 2;
+ goto nextInsn;
+ }
+
+ case bci_PUSH_ALTS_V: {
+ int o_bco = BCO_NEXT;
+ Sp[-2] = (W_)&stg_ctoi_V_info;
+ Sp[-1] = BCO_PTR(o_bco);
+ Sp -= 2;
+ goto nextInsn;
+ }
+
+ case bci_PUSH_APPLY_N:
+ Sp--; Sp[0] = (W_)&stg_ap_n_info;
+ goto nextInsn;
+ case bci_PUSH_APPLY_V:
+ Sp--; Sp[0] = (W_)&stg_ap_v_info;
+ goto nextInsn;
+ case bci_PUSH_APPLY_F:
+ Sp--; Sp[0] = (W_)&stg_ap_f_info;
+ goto nextInsn;
+ case bci_PUSH_APPLY_D:
+ Sp--; Sp[0] = (W_)&stg_ap_d_info;
+ goto nextInsn;
+ case bci_PUSH_APPLY_L:
+ Sp--; Sp[0] = (W_)&stg_ap_l_info;
+ goto nextInsn;
+ case bci_PUSH_APPLY_P:
+ Sp--; Sp[0] = (W_)&stg_ap_p_info;
+ goto nextInsn;
+ case bci_PUSH_APPLY_PP:
+ Sp--; Sp[0] = (W_)&stg_ap_pp_info;
+ goto nextInsn;
+ case bci_PUSH_APPLY_PPP:
+ Sp--; Sp[0] = (W_)&stg_ap_ppp_info;
+ goto nextInsn;
+ case bci_PUSH_APPLY_PPPP:
+ Sp--; Sp[0] = (W_)&stg_ap_pppp_info;
+ goto nextInsn;
+ case bci_PUSH_APPLY_PPPPP:
+ Sp--; Sp[0] = (W_)&stg_ap_ppppp_info;
+ goto nextInsn;
+ case bci_PUSH_APPLY_PPPPPP:
+ Sp--; Sp[0] = (W_)&stg_ap_pppppp_info;
+ goto nextInsn;
+
+ case bci_PUSH_UBX: {
+ int i;
+ int o_lits = BCO_NEXT;
+ int n_words = BCO_NEXT;
+ Sp -= n_words;
+ for (i = 0; i < n_words; i++) {
+ Sp[i] = (W_)BCO_LIT(o_lits+i);
+ }
+ goto nextInsn;
+ }
+
+ case bci_SLIDE: {
+ int n = BCO_NEXT;
+ int by = BCO_NEXT;
+ /* a_1, .. a_n, b_1, .. b_by, s => a_1, .. a_n, s */
+ while(--n >= 0) {
+ Sp[n+by] = Sp[n];
+ }
+ Sp += by;
+ INTERP_TICK(it_slides);
+ goto nextInsn;
+ }
+
+ case bci_ALLOC_AP: {
+ StgAP* ap;
+ int n_payload = BCO_NEXT;
+ ap = (StgAP*)allocate(AP_sizeW(n_payload));
+ Sp[-1] = (W_)ap;
+ ap->n_args = n_payload;
+ SET_HDR(ap, &stg_AP_info, CCS_SYSTEM/*ToDo*/)
+ Sp --;
+ goto nextInsn;
+ }
+
+ case bci_ALLOC_PAP: {
+ StgPAP* pap;
+ int arity = BCO_NEXT;
+ int n_payload = BCO_NEXT;
+ pap = (StgPAP*)allocate(PAP_sizeW(n_payload));
+ Sp[-1] = (W_)pap;
+ pap->n_args = n_payload;
+ pap->arity = arity;
+ SET_HDR(pap, &stg_PAP_info, CCS_SYSTEM/*ToDo*/)
+ Sp --;
+ goto nextInsn;
+ }
+
+ case bci_MKAP: {
+ int i;
+ int stkoff = BCO_NEXT;
+ int n_payload = BCO_NEXT;
+ StgAP* ap = (StgAP*)Sp[stkoff];
+ ASSERT((int)ap->n_args == n_payload);
+ ap->fun = (StgClosure*)Sp[0];
+
+ // The function should be a BCO, and its bitmap should
+ // cover the payload of the AP correctly.
+ ASSERT(get_itbl(ap->fun)->type == BCO
+ && BCO_BITMAP_SIZE(ap->fun) == ap->n_args);
+
+ for (i = 0; i < n_payload; i++)
+ ap->payload[i] = (StgClosure*)Sp[i+1];
+ Sp += n_payload+1;
+ IF_DEBUG(interpreter,
+ debugBelch("\tBuilt ");
+ printObj((StgClosure*)ap);
+ );
+ goto nextInsn;
+ }
+
+ case bci_MKPAP: {
+ int i;
+ int stkoff = BCO_NEXT;
+ int n_payload = BCO_NEXT;
+ StgPAP* pap = (StgPAP*)Sp[stkoff];
+ ASSERT((int)pap->n_args == n_payload);
+ pap->fun = (StgClosure*)Sp[0];
+
+ // The function should be a BCO
+ ASSERT(get_itbl(pap->fun)->type == BCO);
+
+ for (i = 0; i < n_payload; i++)
+ pap->payload[i] = (StgClosure*)Sp[i+1];
+ Sp += n_payload+1;
+ IF_DEBUG(interpreter,
+ debugBelch("\tBuilt ");
+ printObj((StgClosure*)pap);
+ );
+ goto nextInsn;
+ }
+
+ case bci_UNPACK: {
+ /* Unpack N ptr words from t.o.s constructor */
+ int i;
+ int n_words = BCO_NEXT;
+ StgClosure* con = (StgClosure*)Sp[0];
+ Sp -= n_words;
+ for (i = 0; i < n_words; i++) {
+ Sp[i] = (W_)con->payload[i];
+ }
+ goto nextInsn;
+ }
+
+ case bci_PACK: {
+ int i;
+ int o_itbl = BCO_NEXT;
+ int n_words = BCO_NEXT;
+ StgInfoTable* itbl = INFO_PTR_TO_STRUCT(BCO_ITBL(o_itbl));
+ int request = CONSTR_sizeW( itbl->layout.payload.ptrs,
+ itbl->layout.payload.nptrs );
+ StgClosure* con = (StgClosure*)allocate_NONUPD(request);
+ ASSERT( itbl->layout.payload.ptrs + itbl->layout.payload.nptrs > 0);
+ SET_HDR(con, BCO_ITBL(o_itbl), CCS_SYSTEM/*ToDo*/);
+ for (i = 0; i < n_words; i++) {
+ con->payload[i] = (StgClosure*)Sp[i];
+ }
+ Sp += n_words;
+ Sp --;
+ Sp[0] = (W_)con;
+ IF_DEBUG(interpreter,
+ debugBelch("\tBuilt ");
+ printObj((StgClosure*)con);
+ );
+ goto nextInsn;
+ }
+
+ case bci_TESTLT_P: {
+ unsigned int discr = BCO_NEXT;
+ int failto = BCO_NEXT;
+ StgClosure* con = (StgClosure*)Sp[0];
+ if (GET_TAG(con) >= discr) {
+ bciPtr = failto;
+ }
+ goto nextInsn;
+ }
+
+ case bci_TESTEQ_P: {
+ unsigned int discr = BCO_NEXT;
+ int failto = BCO_NEXT;
+ StgClosure* con = (StgClosure*)Sp[0];
+ if (GET_TAG(con) != discr) {
+ bciPtr = failto;
+ }
+ goto nextInsn;
+ }
+
+ case bci_TESTLT_I: {
+ // There should be an Int at Sp[1], and an info table at Sp[0].
+ int discr = BCO_NEXT;
+ int failto = BCO_NEXT;
+ I_ stackInt = (I_)Sp[1];
+ if (stackInt >= (I_)BCO_LIT(discr))
+ bciPtr = failto;
+ goto nextInsn;
+ }
+
+ case bci_TESTEQ_I: {
+ // There should be an Int at Sp[1], and an info table at Sp[0].
+ int discr = BCO_NEXT;
+ int failto = BCO_NEXT;
+ I_ stackInt = (I_)Sp[1];
+ if (stackInt != (I_)BCO_LIT(discr)) {
+ bciPtr = failto;
+ }
+ goto nextInsn;
+ }
+
+ case bci_TESTLT_D: {
+ // There should be a Double at Sp[1], and an info table at Sp[0].
+ int discr = BCO_NEXT;
+ int failto = BCO_NEXT;
+ StgDouble stackDbl, discrDbl;
+ stackDbl = PK_DBL( & Sp[1] );
+ discrDbl = PK_DBL( & BCO_LIT(discr) );
+ if (stackDbl >= discrDbl) {
+ bciPtr = failto;
+ }
+ goto nextInsn;
+ }
+
+ case bci_TESTEQ_D: {
+ // There should be a Double at Sp[1], and an info table at Sp[0].
+ int discr = BCO_NEXT;
+ int failto = BCO_NEXT;
+ StgDouble stackDbl, discrDbl;
+ stackDbl = PK_DBL( & Sp[1] );
+ discrDbl = PK_DBL( & BCO_LIT(discr) );
+ if (stackDbl != discrDbl) {
+ bciPtr = failto;
+ }
+ goto nextInsn;
+ }
+
+ case bci_TESTLT_F: {
+ // There should be a Float at Sp[1], and an info table at Sp[0].
+ int discr = BCO_NEXT;
+ int failto = BCO_NEXT;
+ StgFloat stackFlt, discrFlt;
+ stackFlt = PK_FLT( & Sp[1] );
+ discrFlt = PK_FLT( & BCO_LIT(discr) );
+ if (stackFlt >= discrFlt) {
+ bciPtr = failto;
+ }
+ goto nextInsn;
+ }
+
+ case bci_TESTEQ_F: {
+ // There should be a Float at Sp[1], and an info table at Sp[0].
+ int discr = BCO_NEXT;
+ int failto = BCO_NEXT;
+ StgFloat stackFlt, discrFlt;
+ stackFlt = PK_FLT( & Sp[1] );
+ discrFlt = PK_FLT( & BCO_LIT(discr) );
+ if (stackFlt != discrFlt) {
+ bciPtr = failto;
+ }
+ goto nextInsn;
+ }
+
+ // Control-flow ish things
+ case bci_ENTER:
+ // Context-switch check. We put it here to ensure that
+ // the interpreter has done at least *some* work before
+ // context switching: sometimes the scheduler can invoke
+ // the interpreter with context_switch == 1, particularly
+ // if the -C0 flag has been given on the cmd line.
+ if (context_switch) {
+ Sp--; Sp[0] = (W_)&stg_enter_info;
+ RETURN_TO_SCHEDULER(ThreadInterpret, ThreadYielding);
+ }
+ goto eval;
+
+ case bci_RETURN:
+ obj = (StgClosure *)Sp[0];
+ Sp++;
+ goto do_return;
+
+ case bci_RETURN_P:
+ Sp--;
+ Sp[0] = (W_)&stg_gc_unpt_r1_info;
+ goto do_return_unboxed;
+ case bci_RETURN_N:
+ Sp--;
+ Sp[0] = (W_)&stg_gc_unbx_r1_info;
+ goto do_return_unboxed;
+ case bci_RETURN_F:
+ Sp--;
+ Sp[0] = (W_)&stg_gc_f1_info;
+ goto do_return_unboxed;
+ case bci_RETURN_D:
+ Sp--;
+ Sp[0] = (W_)&stg_gc_d1_info;
+ goto do_return_unboxed;
+ case bci_RETURN_L:
+ Sp--;
+ Sp[0] = (W_)&stg_gc_l1_info;
+ goto do_return_unboxed;
+ case bci_RETURN_V:
+ Sp--;
+ Sp[0] = (W_)&stg_gc_void_info;
+ goto do_return_unboxed;
+
+ case bci_SWIZZLE: {
+ int stkoff = BCO_NEXT;
+ signed short n = (signed short)(BCO_NEXT);
+ Sp[stkoff] += (W_)n;
+ goto nextInsn;
+ }
+
+ case bci_CCALL: {
+ void *tok;
+ int stk_offset = BCO_NEXT;
+ int o_itbl = BCO_NEXT;
+ void(*marshall_fn)(void*) = (void (*)(void*))BCO_LIT(o_itbl);
+ int ret_dyn_size =
+ RET_DYN_BITMAP_SIZE + RET_DYN_NONPTR_REGS_SIZE
+ + sizeofW(StgRetDyn);
+
+#ifdef THREADED_RTS
+ // Threaded RTS:
+ // Arguments on the TSO stack are not good, because garbage
+ // collection might move the TSO as soon as we call
+ // suspendThread below.
+
+ W_ arguments[stk_offset];
+
+ memcpy(arguments, Sp, sizeof(W_) * stk_offset);
+#endif
+
+ // Restore the Haskell thread's current value of errno
+ errno = cap->r.rCurrentTSO->saved_errno;
+
+ // There are a bunch of non-ptr words on the stack (the
+ // ccall args, the ccall fun address and space for the
+ // result), which we need to cover with an info table
+ // since we might GC during this call.
+ //
+ // We know how many (non-ptr) words there are before the
+ // next valid stack frame: it is the stk_offset arg to the
+ // CCALL instruction. So we build a RET_DYN stack frame
+ // on the stack frame to describe this chunk of stack.
+ //
+ Sp -= ret_dyn_size;
+ ((StgRetDyn *)Sp)->liveness = NO_PTRS | N_NONPTRS(stk_offset);
+ ((StgRetDyn *)Sp)->info = (StgInfoTable *)&stg_gc_gen_info;
+
+ SAVE_STACK_POINTERS;
+ tok = suspendThread(&cap->r);
+
+#ifndef THREADED_RTS
+ // Careful:
+ // suspendThread might have shifted the stack
+ // around (stack squeezing), so we have to grab the real
+ // Sp out of the TSO to find the ccall args again.
+
+ marshall_fn ( (void*)(cap->r.rCurrentTSO->sp + ret_dyn_size) );
+#else
+ // Threaded RTS:
+ // We already made a copy of the arguments above.
+
+ marshall_fn ( arguments );
+#endif