[project @ 2001-01-03 15:30:48 by simonmar]
[ghc-hetmet.git] / ghc / rts / Interpreter.c
1
2 /* -----------------------------------------------------------------------------
3  * Bytecode evaluator
4  *
5  * Copyright (c) 1994-2000.
6  *
7  * $RCSfile: Interpreter.c,v $
8  * $Revision: 1.6 $
9  * $Date: 2001/01/03 15:30:48 $
10  * ---------------------------------------------------------------------------*/
11
12 #ifdef GHCI
13
14 #include "Rts.h"
15 #include "RtsAPI.h"
16 #include "RtsUtils.h"
17 #include "Closures.h"
18 #include "TSO.h"
19 #include "Schedule.h"
20 #include "RtsFlags.h"
21 #include "Storage.h"
22 #include "Updates.h"
23
24 #include "Bytecodes.h"
25 #include "Printer.h"
26 #include "Disassembler.h"
27 #include "Interpreter.h"
28
29
30 /* --------------------------------------------------------------------------
31  * The new bytecode interpreter
32  * ------------------------------------------------------------------------*/
33
34 /* Sp points to the lowest live word on the stack. */
35
36 #define StackWord(n)  iSp[n]
37 #define BCO_NEXT      instrs[bciPtr++]
38 #define BCO_PTR(n)    (W_)ptrs[n]
39 #define BCO_LIT(n)    (W_)literals[n]
40 #define BCO_ITBL(n)   itbls[n]
41
42 StgThreadReturnCode interpretBCO ( Capability* cap )
43 {
44    /* On entry, the closure to interpret is on the top of the
45       stack. */
46  
47    /* Use of register here is primarily to make it clear to compilers
48       that these entities are non-aliasable.
49    */
50     register W_*              iSp;    /* local state -- stack pointer */
51     register StgUpdateFrame*  iSu;    /* local state -- frame pointer */
52     register StgPtr           iSpLim; /* local state -- stack lim pointer */
53     register StgClosure*      obj;
54
55     iSp    = cap->rCurrentTSO->sp;
56     iSu    = cap->rCurrentTSO->su;
57     iSpLim = cap->rCurrentTSO->stack + RESERVED_STACK_WORDS;
58
59     IF_DEBUG(evaluator,
60              fprintf(stderr, 
61              "\n---------------------------------------------------------------\n");
62              fprintf(stderr,"Entering: "); printObj((StgClosure*)StackWord(0));
63              fprintf(stderr,"iSp = %p\tiSu = %p\n", iSp, iSu);
64              fprintf(stderr, "\n" );
65              printStack(iSp,cap->rCurrentTSO->stack+cap->rCurrentTSO->stack_size,iSu);
66              fprintf(stderr, "\n\n");
67             );
68
69     /* Main object-entering loop.  Object to be entered is on top of
70        stack. */
71     nextEnter:
72
73     obj = (StgClosure*)StackWord(0); iSp++;
74
75     switch ( get_itbl(obj)->type ) {
76        case INVALID_OBJECT:
77                barf("Invalid object %p",(StgPtr)obj);
78
79        case BCO:
80
81        /* ---------------------------------------------------- */
82        /* Start of the bytecode interpreter                    */
83        /* ---------------------------------------------------- */
84        {
85           register int       bciPtr     = 1; /* instruction pointer */
86           register StgBCO*   bco        = (StgBCO*)obj;
87           register UShort*   instrs     = (UShort*)(&bco->instrs->payload[0]);
88           register StgWord*  literals   = (StgWord*)(&bco->literals->payload[0]);
89           register StgPtr*   ptrs       = (StgPtr*)(&bco->ptrs->payload[0]);
90           register StgInfoTable** itbls = (StgInfoTable**)
91                                              (&bco->itbls->payload[0]);
92
93           if (doYouWantToGC()) {
94              iSp--; StackWord(0) = (W_)bco;
95              return HeapOverflow;
96           }
97
98           nextInsn:
99
100           ASSERT(bciPtr <= instrs[0]);
101           IF_DEBUG(evaluator,
102           fprintf(stderr,"iSp = %p\tiSu = %p\tpc = %d\t", iSp, iSu, bciPtr);
103                   disInstr(bco,bciPtr);
104                   if (0) { int i;
105                            fprintf(stderr,"\n");
106                            for (i = 8; i >= 0; i--) 
107                               fprintf(stderr, "%d  %p\n", i, (StgPtr)(*(iSp+i)));
108                          }
109                   fprintf(stderr,"\n");
110                  );
111
112           switch (BCO_NEXT) {
113
114               case bci_ARGCHECK: {
115                  int i;
116                  StgPAP* pap;
117                  int arg_words_reqd = BCO_NEXT;
118                  int arg_words_avail = ((W_*)iSu) - ((W_*)iSp);
119                  if (arg_words_avail >= arg_words_reqd) goto nextInsn;
120                  /* Handle arg check failure.  Copy the spare args
121                     into a PAP frame. */
122                  pap = (StgPAP*)allocate(PAP_sizeW(arg_words_avail));
123                  SET_HDR(pap,&stg_PAP_info,CCS_SYSTEM/*ToDo*/);
124                  pap->n_args = arg_words_avail;
125                  for (i = 0; i < arg_words_avail; i++)
126                     pap->payload[i] = (StgClosure*)StackWord(i);
127                  /* Push on the stack and defer to the scheduler. */
128                  iSp = (StgPtr)iSu;
129                  iSp --;
130                  StackWord(0) = (W_)pap;
131                  return ThreadEnterGHC;
132               }
133               case bci_PUSH_L: {
134                  int o1 = BCO_NEXT;
135                  StackWord(-1) = StackWord(o1);
136                  iSp--;
137                  goto nextInsn;
138               }
139               case bci_PUSH_LL: {
140                  int o1 = BCO_NEXT;
141                  int o2 = BCO_NEXT;
142                  StackWord(-1) = StackWord(o1);
143                  StackWord(-2) = StackWord(o2);
144                  iSp -= 2;
145                  goto nextInsn;
146               }
147               case bci_PUSH_LLL: {
148                  int o1 = BCO_NEXT;
149                  int o2 = BCO_NEXT;
150                  int o3 = BCO_NEXT;
151                  StackWord(-1) = StackWord(o1);
152                  StackWord(-2) = StackWord(o2);
153                  StackWord(-3) = StackWord(o3);
154                  iSp -= 3;
155                  goto nextInsn;
156               }
157               case bci_PUSH_G: {
158                  int o1 = BCO_NEXT;
159                  StackWord(-1) = BCO_PTR(o1);
160                  iSp -= 1;
161                  goto nextInsn;
162               }
163               case bci_PUSH_AS: {
164                  int o_bco  = BCO_NEXT;
165                  int o_itbl = BCO_NEXT;
166                  StackWord(-1) = BCO_LIT(o_itbl);
167                  StackWord(-2) = BCO_PTR(o_bco);
168                  iSp -= 2;
169                  goto nextInsn;
170               }
171               case bci_PUSH_UBX: {
172                  int o_lits = BCO_NEXT;
173                  int n_words = BCO_NEXT;
174                  for (; n_words > 0; n_words--) {
175                     iSp --;
176                     StackWord(0) = BCO_LIT(o_lits);
177                     o_lits++;
178                  }
179                  goto nextInsn;
180               }
181               case bci_PUSH_TAG: {
182                  W_ tag = (W_)(BCO_NEXT);
183                  StackWord(-1) = tag;
184                  iSp --;
185                  goto nextInsn;
186               }
187               case bci_SLIDE: {
188                  int n  = BCO_NEXT;
189                  int by = BCO_NEXT;
190                  ASSERT(iSp+n+by <= (W_*)iSu);
191                  /* a_1, .. a_n, b_1, .. b_by, s => a_1, .. a_n, s */
192                  while(--n >= 0) {
193                     StackWord(n+by) = StackWord(n);
194                  }
195                  iSp += by;
196                  goto nextInsn;
197               }
198               case bci_ALLOC: {
199                  int n_payload = BCO_NEXT;
200                  P_ p = allocate(AP_sizeW(n_payload));
201                  StackWord(-1) = (W_)p;
202                  iSp --;
203                  goto nextInsn;
204               }
205               case bci_MKAP: {
206                  int i;
207                  int stkoff = BCO_NEXT;
208                  int n_payload = BCO_NEXT - 1;
209                  StgAP_UPD* ap = (StgAP_UPD*)StackWord(stkoff);
210                  ap->n_args = n_payload;
211                  ap->fun = (StgClosure*)StackWord(0);
212                  for (i = 0; i < n_payload; i++)
213                     ap->payload[i] = (StgClosure*)StackWord(i+1);
214                  iSp += n_payload+1;
215                  goto nextInsn;
216               }
217               case bci_UNPACK: {
218                  /* Unpack N ptr words from t.o.s constructor */
219                  /* The common case ! */
220                  int i;
221                  int n_words = BCO_NEXT;
222                  StgClosure* con = (StgClosure*)StackWord(0);
223                  iSp -= n_words;
224                  for (i = 0; i < n_words; i++)
225                     StackWord(i) = (W_)con->payload[i];
226                  goto nextInsn;
227               }
228               case bci_UPK_TAG: {
229                  /* Unpack N (non-ptr) words from offset M in the
230                     constructor K words down the stack, and then push
231                     N as a tag, on top of it.  Slow but general; we
232                     hope it will be the rare case. */
233                  int i;                
234                  int n_words = BCO_NEXT;
235                  int con_off = BCO_NEXT;
236                  int stk_off = BCO_NEXT;
237                  StgClosure* con = (StgClosure*)StackWord(stk_off);
238                  iSp -= n_words;
239                  for (i = 0; i < n_words; i++) 
240                     StackWord(i) = (W_)con->payload[con_off + i];
241                  iSp --;
242                  StackWord(0) = n_words;
243                  goto nextInsn;
244               }
245               case bci_PACK: {
246                  int i;
247                  int o_itbl         = BCO_NEXT;
248                  int n_words        = BCO_NEXT;
249                  StgInfoTable* itbl = BCO_ITBL(o_itbl);
250                  /* A bit of a kludge since n_words = n_p + n_np */
251                  int request        = CONSTR_sizeW( n_words, 0 );
252                  StgClosure* con = (StgClosure*)allocate(request);
253                  SET_HDR(con, itbl, CCS_SYSTEM/*ToDo*/);
254                  for (i = 0; i < n_words; i++)
255                     con->payload[i] = (StgClosure*)StackWord(i);
256                  iSp += n_words;
257                  iSp --;
258                  StackWord(0) = (W_)con;
259                  goto nextInsn;
260               }
261               case bci_TESTLT_P: {
262                  int discr  = BCO_NEXT;
263                  int failto = BCO_NEXT;
264                  StgClosure* con = (StgClosure*)StackWord(0);
265                  if (constrTag(con) < discr)
266                     bciPtr = failto;
267                  goto nextInsn;
268               }
269               case bci_TESTEQ_P: {
270                  int discr  = BCO_NEXT;
271                  int failto = BCO_NEXT;
272                  StgClosure* con = (StgClosure*)StackWord(0);
273                  if (constrTag(con) != discr)
274                     bciPtr = failto;
275                  goto nextInsn;
276               }
277
278               /* Control-flow ish things */
279               case bci_ENTER: {
280                  goto nextEnter;
281               }
282               case bci_RETURN: {
283                  /* Figure out whether returning to interpreted or
284                     compiled code. */
285                  int           o_itoc_itbl = BCO_NEXT;
286                  int           tag         = StackWord(0);
287                  StgInfoTable* ret_itbl    = (StgInfoTable*)StackWord(tag+1 +1);
288                  ASSERT(tag <= 2); /* say ... */
289                  if (ret_itbl == (StgInfoTable*)&stg_ctoi_ret_R1_info
290                      /* || ret_itbl == stg_ctoi_ret_F1_info
291                         || ret_itbl == stg_ctoi_ret_D1_info */) {
292                      /* Returning to interpreted code.  Interpret the BCO 
293                         immediately underneath the itbl. */
294                      StgBCO* ret_bco = (StgBCO*)StackWord(tag+1 +1+1);
295                      iSp --;
296                      StackWord(0) = (W_)ret_bco;
297                      goto nextEnter;
298                  } else {
299                      /* Returning (unboxed value) to compiled code.
300                         Replace tag with a suitable itbl and ask the
301                         scheduler to run it.  The itbl code will copy
302                         the TOS value into R1/F1/D1 and do a standard
303                         compiled-code return. */
304                      StgInfoTable* magic_itbl = BCO_ITBL(o_itoc_itbl);
305                      StackWord(0) = (W_)magic_itbl;
306                      return ThreadRunGHC;
307                  }
308               }
309         
310               case bci_CASEFAIL:
311                  barf("interpretBCO: hit a CASEFAIL");
312
313               /* As yet unimplemented */
314               case bci_TESTLT_I:
315               case bci_TESTEQ_I:
316               case bci_TESTLT_F:
317               case bci_TESTEQ_F:
318               case bci_TESTLT_D:
319               case bci_TESTEQ_D:
320
321               /* Errors */
322               default: 
323                  barf("interpretBCO: unknown or unimplemented opcode");
324
325           } /* switch on opcode */
326
327           barf("interpretBCO: fell off end of insn loop");
328
329        }
330        /* ---------------------------------------------------- */
331        /* End of the bytecode interpreter                      */
332        /* ---------------------------------------------------- */
333
334        default: {
335           /* Can't handle this object; yield to sched. */
336           fprintf(stderr, "entering unknown closure -- yielding to sched\n"); 
337           printObj(obj);
338           cap->rCurrentTSO->what_next = ThreadEnterGHC;
339           iSp--; StackWord(0) = (W_)obj;
340           return ThreadYielding;
341        }
342     } /* switch on object kind */
343
344     barf("fallen off end of object-type switch in interpretBCO()");
345 }
346
347 #endif /* GHCI */