- removed warnings
[cacao.git] / src / vm / jit / loop / tracing.c
1 /* jit/loop/tracing.c - trace functions
2
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4    R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5    M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6    P. Tomsich, J. Wenninger
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Christopher Kruegel
28
29    Contains the functions which create a trace. A trace is a
30    structure, that contains the source of the arguments of a given
31    instruction. For more details see function tracing(basicblock, int,
32    int) below.
33
34    $Id: tracing.c 576 2003-11-09 17:31:38Z twisti $
35
36 */
37
38
39 #include <stdio.h>
40 #include "tracing.h"
41 #include "loop.h"
42 #include "toolbox/memory.h"
43
44
45 /*      Test function -> will be removed in final release
46 */
47 void printTraceResult(struct Trace *p)
48 {
49         printf("TRACE: ");
50
51         switch (p->type) {
52         case TRACE_UNKNOWN:
53                 printf("\tUnknown");
54                 break;
55         case TRACE_ICONST:
56                 printf("\tconst - %d", p->constant);
57                 break;
58         case TRACE_ALENGTH:
59                 printf("\tarray - (%d)%d - %d", p->neg, p->var, p->constant);
60                 break;
61         case TRACE_IVAR:
62                 printf("\tivar - (%d)%d - %d", p->neg, p->var, p->constant);
63                 break;
64         case TRACE_AVAR:
65                 printf("\tavar - %d", p->var);
66                 break;
67                 }
68         
69         printf("\n");
70 }
71
72     
73 /*      A function that creates a new trace structure and initializes its values
74 */
75 struct Trace* create_trace(int type, int var, int constant, int nr)
76 {
77         struct Trace *t;
78 /*      if ((t = (struct Trace *) malloc(sizeof(struct Trace))) == NULL) */
79 /*              c_mem_error(); */
80         t = DNEW(struct Trace);
81
82         t->type = type;
83
84         t->neg = 1;
85         t->var = var;
86         t->nr = nr;
87
88         t->constant = constant;
89
90         return t;
91 }
92
93
94 /*      When the function tracing(...) encounters an add instruction during its 
95         backward scan over the instructions, it trys to identify the source of the
96         arguments of this add function. The following function performs this task.
97 */
98 struct Trace* add(struct Trace* a, struct Trace* b)
99 {
100         switch (a->type) {                      /* check the first argument of add. when it             */
101         case TRACE_UNKNOWN:                     /* is unknown or array-address, return unknown  */
102         case TRACE_AVAR:
103                 return create_trace(TRACE_UNKNOWN, -1, 0, 0);
104
105         case TRACE_ICONST:                      /* when it is constant, check second argument   */
106                 switch (b->type) {
107                 case TRACE_IVAR:                        /* when second argument is a variable value */
108                 case TRACE_ALENGTH:                     /* or array length, just add the constant       */
109                         a->type = b->type;
110                         a->var  = b->var;
111                         a->neg  = b->neg;
112                         a->constant += b->constant;
113                         break;
114                 case TRACE_UNKNOWN:                     /* when unknown/array ref. return unknown       */
115                 case TRACE_AVAR:
116                       return create_trace(TRACE_UNKNOWN, -1, 0, 0);
117             case TRACE_ICONST:                  /* when both are constant, just add them        */
118                         a->constant += b->constant;
119                         break;
120                         }
121                 break;
122
123         case TRACE_IVAR:                        /* when it is a variable value or array length, */
124         case TRACE_ALENGTH:                     /* check second argument                                                */
125                 switch (b->type) {
126                 case TRACE_IVAR:                        /* when it is not a constant return unknown     */
127                 case TRACE_ALENGTH:
128                 case TRACE_UNKNOWN:
129                 case TRACE_AVAR:
130                         return create_trace(TRACE_UNKNOWN, -1, 0, 0);
131                 case TRACE_ICONST:                      /* when it is a constant, just add it           */
132                         a->constant += b->constant;
133                         break;
134                         }
135                 break;
136                 }
137
138         return a;
139 }
140
141
142 /*      When the function tracing(...) encounters a neg instruction during its 
143         backward scan over the instructions, it trys to identify the source of the
144         argument of this neg function. The following function performs this task.
145 */
146 struct Trace* negate(struct Trace* a)
147 {
148         switch (a->type) {                              /* check argument type                                          */
149         case TRACE_IVAR:                                /* when it is variable/array length value       */
150         case TRACE_ALENGTH:                                     
151                 a->neg = -(a->neg);                             /* invert negate flag                                   */
152                 a->constant = -(a->constant);   /* and negate constant                                  */
153                 break;
154         
155         case TRACE_ICONST:                              /* when it is a constant, negate it                     */
156                 a->constant = -(a->constant);
157                 break;
158
159         default:
160                 a->type = TRACE_UNKNOWN;        /* else return unknown                                          */
161                 break;
162                 }
163
164   return a;
165 }
166
167
168 /*      When the function tracing(...) encounters a sub instruction during its backward
169         scan over the instructions, it trys to identify the source of the arguments of
170         this sub function. The following function performs this task, by applaying the
171         negate function on the second argument and then adds the values.
172 */
173 struct Trace* sub(struct Trace* a, struct Trace* b)
174 {
175         struct Trace *c = negate(b);
176         return add(a, c);
177 }
178
179
180 /*      When the function tracing(...) encounters an array length instruction during
181         its backward scan over the instructions, it trys to identify the source of 
182         the argument ofthis array length function. The following function performs 
183         this task.
184 */
185 struct Trace* array_length(struct Trace* a)
186 {
187         if (a->type == TRACE_AVAR)      /* if argument is an array ref., mark the type  */
188                 a->type = TRACE_ALENGTH;        /* as array length of this array reference      */
189         else
190                 a->type = TRACE_UNKNOWN;        /* else it's unknown                                    */
191
192         return a;
193 }
194
195
196 /*      This function is used to identify the types of operands of an intermediate 
197         code instruction.It is needed by functions, that analyze array accesses. If 
198         something is stored into or loaded from an array, we have to find out, which 
199         array really has been accessed. When a compare instruction is encountered at
200         a loop header, the type of its operands have to be detected to construct
201         dynamic bounds for some variables in the loop. This function returns a struct
202         Trace (see loop.h for more details about this structure). block is the basic
203         block to be examined, index holds the offset of the examined instruction in
204         this block. The arguments are retrieved by using the stack structure, the 
205         compilation process sets up. During the backwards scan of the code, it is 
206         possible, that other instructions temporaray put or get values from the stack
207         and hide the value, we are interested in below them. The value temp counts
208         the number of values on the stack, the are located beyond the target value.
209 */
210 struct Trace* tracing(basicblock *block, int index, int temp)
211 {
212         int args, retval;
213         instruction *ip;
214         methodinfo *m;
215
216         if (index >= 0) {
217                 ip = block->iinstr+index;
218
219 /*      printf("TRACING with %d %d %d\n", index, temp, ip->opc);
220 */
221                 switch (ip->opc) {
222                 
223                 /* nop, nullcheckpop                                                                                                    */
224                 case ICMD_NOP:                          /* ...  ==> ...                                                         */
225                         return tracing(block, index-1, temp);
226                         break;
227       
228                 case ICMD_NULLCHECKPOP:         /* ..., objectref  ==> ...                                      */
229                         return tracing(block, index-1, temp+1);
230                         break;
231
232                 /* Constants                                                                                                                    */
233                 case ICMD_LCONST:                               
234                 case ICMD_DCONST:
235                 case ICMD_FCONST:
236                 case ICMD_ACONST:
237                         if (temp > 0)                           
238                                 return tracing(block, index-1, temp-1);         
239                         else
240                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
241                         break;                                          
242
243                 case ICMD_ICONST:
244                         if (temp > 0)           /* if the target argument is not on top                 */
245                                 return tracing(block, index-1, temp-1); /* look further                 */
246                         else
247                                 return create_trace(TRACE_ICONST, -1, ip->val.i, index);
248                         break;                          /* else, return the value, found at this instr. */
249
250                 /* Load/Store                                                                                                                   */
251         case ICMD_LLOAD:                
252                 case ICMD_DLOAD:    
253                 case ICMD_FLOAD:
254                         if (temp > 0)
255                                 return tracing(block, index-1, temp-1);
256                         else
257                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
258                         break;
259     
260                 case ICMD_ILOAD:
261                         if (temp > 0)
262                                 return tracing(block, index-1, temp-1);
263                     else
264                                 return create_trace(TRACE_IVAR, ip->op1, 0, index);
265                         break;
266
267                 case ICMD_ALOAD:    
268                         if (temp > 0)
269                                 return tracing(block, index-1, temp-1);
270                         else
271                                 return create_trace(TRACE_AVAR, ip->op1, 0, index);                     
272                         break;
273                 
274                 case ICMD_LSTORE:    
275                 case ICMD_DSTORE:    
276                 case ICMD_FSTORE:
277                 case ICMD_ISTORE:
278                 case ICMD_ASTORE:    
279                         return tracing(block, index-1, temp+1);
280                         break;
281         
282
283                 /* pop/dup/swap                                                                                                                 */
284                 case ICMD_POP:      
285                         return tracing(block, index-1, temp+1);
286                         break;
287      
288                 case ICMD_POP2:  
289                         return tracing(block, index-1, temp+2);
290                         break;
291
292                 case ICMD_DUP:
293                         if (temp > 0)
294                                 return tracing(block, index-1, temp-1);
295                         else
296                                 return tracing(block, index-1, temp);
297                         break;
298
299                 case ICMD_DUP_X1:                       /* ..., a, b ==> ..., b, a, b                           */
300                         switch (temp) {
301                         case 0:                                 /* when looking for top or third element,       */
302                         case 2:                                 /* just return top element                                      */
303                                 return tracing(block, index-1, 0);
304                         case 1:
305                                 return tracing(block, index-1, 1);
306                         default:
307                                 return tracing(block, index-1, temp-1);
308                                 }
309                         break;
310
311                 case ICMD_DUP2:                         /* ..., a, b ==> ..., a, b, a, b                        */
312                         switch (temp) { 
313                         case 0:                                 /* when looking for top or third element        */
314                         case 2:                                 /* just return top element                                      */
315                                 return tracing(block, index-1, 0);
316                         case 1:                                 /* when looking for second or fourth element*/
317                         case 3:                                 /* just return second element                           */
318                                 return tracing(block, index-1, 1);
319                         default:
320                                 return tracing(block, index-1, temp-2);
321                                 }
322                         break;
323
324                 case ICMD_DUP2_X1:                      /* ..., a, b, c ==> ..., b, c, a, b, c          */
325                         switch (temp) {
326                         case 0:
327                         case 3:
328                                 return tracing(block, index-1, 0);
329                         case 1:
330                         case 4:
331                                 return tracing(block, index-1, 1);
332                         case 2:
333                                 return tracing(block, index-1, 2);
334                         default:
335                                 return tracing(block, index-1, temp-2);
336                                 }
337                         break;
338
339                 case ICMD_DUP_X2:                       /* ..., a, b, c ==> ..., c, a, b, c                     */
340                         switch (temp) {    
341                         case 0:
342                         case 3:
343                                 return tracing(block, index-1, 0);
344                         case 1:
345                         case 4:
346                                 return tracing(block, index-1, 1);
347                         case 2:
348                                 return tracing(block, index-1, 2);
349                         default:
350                                 return tracing(block, index-1, temp-2);
351                                 }
352                         break;
353
354                 case ICMD_DUP2_X2:                      /* .., a, b, c, d ==> ..., c, d, a, b, c, d     */
355                         switch (temp) {
356                         case 0:
357                         case 4:
358                                 return tracing(block, index-1, 0);
359                         case 1:
360                         case 5:
361                                 return tracing(block, index-1, 1);
362                         case 2:
363                                 return tracing(block, index-1, 2);
364                         case 3:
365                                 return tracing(block, index-1, 3);
366                         default:
367                                 return tracing(block, index-1, temp-2);
368                                 }
369                         break;
370
371                 case ICMD_SWAP:                         /* ..., a, b ==> ..., b, a                                      */
372                         switch (temp) {
373                         case 0:
374                                 return tracing(block, index-1, 1);
375                         case 1:
376                                 return tracing(block, index-1, 0);
377                         default:
378                                 return tracing(block, index-1, temp);
379                                 }
380                         break;
381       
382                 /* Interger operations                                                                                                  */
383             case ICMD_INEG:                             /* ..., value  ==> ..., - value                         */
384                         if (temp > 0)
385                                 return tracing(block, index-1, temp);
386                         else                                    /* if an inter neg. operation is found,         */
387                                                                         /* invokethe negate function                            */
388                                 return negate(tracing(block, index-1, temp));
389                         break;
390
391                 case ICMD_LNEG:                         /* ..., value  ==> ..., - value                         */
392                 case ICMD_I2L:                          /* ..., value  ==> ..., value                           */
393                 case ICMD_L2I:                          /* ..., value  ==> ..., value                           */
394                 case ICMD_INT2BYTE:                     /* ..., value  ==> ..., value                           */
395                 case ICMD_INT2CHAR:                     /* ..., value  ==> ..., value                           */
396                 case ICMD_INT2SHORT:            /* ..., value  ==> ..., value                           */
397                         if (temp > 0)
398                                 return tracing(block, index-1, temp);
399                         else
400                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
401                         break;
402
403                 case ICMD_IADD:                         /* ..., val1, val2  ==> ..., val1 + val2        */
404                         if (temp > 0)
405                                 return tracing(block, index-1, temp+1);
406                         else                                    /* when add is encountered, invoke add func     */
407                                 return add(tracing(block, index-1, 0), tracing(block, index-1, 1));
408                         break;
409
410                 case ICMD_IADDCONST:            /* ..., value  ==> ..., value + constant        */
411                         if (temp > 0)
412                                 return tracing(block, index-1, temp);
413                         else                                    /* when a constant is added, create a           */
414                                                                         /* constant-trace and use add function          */
415                                 return add(tracing(block, index-1, 0), create_trace(TRACE_ICONST, -1, ip->val.i, index));
416                         break;
417
418                 case ICMD_ISUB:                         /* ..., val1, val2  ==> ..., val1 - val2        */
419                         if (temp > 0)
420                                 return tracing(block, index-1, temp+1);
421                         else                                    /* use sub function for sub instructions        */
422                                 return sub(tracing(block, index-1, 1), tracing(block, index-1, 0));
423                         break;
424
425                 case ICMD_ISUBCONST:            /* ..., value  ==> ..., value + constant        */
426                         if (temp > 0)
427                                 return tracing(block, index-1, temp);
428                         else
429                                 return sub(tracing(block, index-1, 0), create_trace(TRACE_ICONST, -1, ip->val.i, index));
430                         break;
431
432                 case ICMD_LADD:                         /* ..., val1, val2  ==> ..., val1 + val2        */
433                 case ICMD_LSUB:                         /* ..., val1, val2  ==> ..., val1 - val2        */
434                 case ICMD_IMUL:                         /* ..., val1, val2  ==> ..., val1 * val2        */
435                 case ICMD_LMUL:                         /* ..., val1, val2  ==> ..., val1 * val2        */
436                 case ICMD_ISHL:                         /* ..., val1, val2  ==> ..., val1 << val2       */
437                 case ICMD_ISHR:                         /* ..., val1, val2  ==> ..., val1 >> val2       */
438                 case ICMD_IUSHR:                        /* ..., val1, val2  ==> ..., val1 >>> val2      */
439                 case ICMD_LSHL:                         /* ..., val1, val2  ==> ..., val1 << val2       */
440                 case ICMD_LSHR:                         /* ..., val1, val2  ==> ..., val1 >> val2       */
441                 case ICMD_LUSHR:                        /* ..., val1, val2  ==> ..., val1 >>> val2      */
442                 case ICMD_IAND:                         /* ..., val1, val2  ==> ..., val1 & val2        */
443                 case ICMD_LAND:  
444                 case ICMD_IOR:                          /* ..., val1, val2  ==> ..., val1 | val2        */
445                 case ICMD_LOR:
446                 case ICMD_IXOR:                         /* ..., val1, val2  ==> ..., val1 ^ val2        */
447                 case ICMD_LXOR:
448                         if (temp > 0)
449                                 return tracing(block, index-1, temp+1);
450                         else
451                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
452                         break;
453      
454                 case ICMD_LADDCONST:            /* ..., value  ==> ..., value + constant        */
455                 case ICMD_LSUBCONST:            /* ..., value  ==> ..., value - constant        */
456                 case ICMD_IMULCONST:            /* ..., value  ==> ..., value * constant        */
457                 case ICMD_LMULCONST:            /* ..., value  ==> ..., value * constant        */
458                 case ICMD_IDIVPOW2:                     /* ..., value  ==> ..., value << constant       */
459                 case ICMD_LDIVPOW2:                     /* val.i = constant                                                     */
460                 case ICMD_ISHLCONST:            /* ..., value  ==> ..., value << constant       */
461                 case ICMD_ISHRCONST:            /* ..., value  ==> ..., value >> constant       */
462                 case ICMD_IUSHRCONST:           /* ..., value  ==> ..., value >>> constant      */
463                 case ICMD_LSHLCONST:            /* ..., value  ==> ..., value << constant       */
464                 case ICMD_LSHRCONST:            /* ..., value  ==> ..., value >> constant       */
465                 case ICMD_LUSHRCONST:           /* ..., value  ==> ..., value >>> constant      */
466                 case ICMD_IANDCONST:            /* ..., value  ==> ..., value & constant        */
467                 case ICMD_IREMPOW2:                     /* ..., value  ==> ..., value % constant        */
468                 case ICMD_IREM0X10001:          /* ..., value  ==> ..., value % 0x100001        */
469                 case ICMD_LANDCONST:            /* ..., value  ==> ..., value & constant        */
470                 case ICMD_LREMPOW2:                     /* ..., value  ==> ..., value % constant        */
471                 case ICMD_LREM0X10001:          /* ..., value  ==> ..., value % 0x10001         */
472                 case ICMD_IORCONST:                     /* ..., value  ==> ..., value | constant        */
473                 case ICMD_LORCONST:                     /* ..., value  ==> ..., value | constant        */  
474                 case ICMD_IXORCONST:            /* ..., value  ==> ..., value ^ constant        */
475                 case ICMD_LXORCONST:            /* ..., value  ==> ..., value ^ constant        */
476                 case ICMD_LCMP:                         /* ..., val1, val2  ==> ..., val1 cmp val2      */
477                         if (temp > 0)
478                                 return tracing(block, index-1, temp);
479                         else
480                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
481                         break;
482
483                 case ICMD_IINC:                         /* ..., value  ==> ..., value + constant        */
484                         return tracing(block, index-1, temp);
485                         break;
486
487
488                 /* floating operations                                                                                                  */
489                 case ICMD_FADD:                         /* ..., val1, val2  ==> ..., val1 + val2        */
490                 case ICMD_DADD:                         /* ..., val1, val2  ==> ..., val1 + val2        */
491                 case ICMD_FSUB:                         /* ..., val1, val2  ==> ..., val1 - val2        */
492                 case ICMD_DSUB:                         /* ..., val1, val2  ==> ..., val1 - val2        */
493                 case ICMD_FMUL:                         /* ..., val1, val2  ==> ..., val1 * val2        */
494                 case ICMD_DMUL:                         /* ..., val1, val2  ==> ..., val1 *** val2      */
495                 case ICMD_FDIV:                         /* ..., val1, val2  ==> ..., val1 / val2        */
496                 case ICMD_DDIV:                         /* ..., val1, val2  ==> ..., val1 / val2        */
497                 case ICMD_FREM:                         /* ..., val1, val2  ==> ..., val1 % val2        */
498                 case ICMD_DREM:                         /* ..., val1, val2  ==> ..., val1 % val2        */
499                 case ICMD_FCMPL:                        /* .., val1, val2  ==> ..., val1 fcmpl val2     */
500                 case ICMD_DCMPL:
501                 case ICMD_FCMPG:                        /* .., val1, val2  ==> ..., val1 fcmpg val2     */
502                 case ICMD_DCMPG:
503                         if (temp > 0)
504                                 return tracing(block, index-1, temp+1);
505                         else
506                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
507                         break;
508
509                 case ICMD_FNEG:                         /* ..., value  ==> ..., - value                         */
510                 case ICMD_DNEG:                         /* ..., value  ==> ..., - value                         */  
511                 case ICMD_I2F:                          /* ..., value  ==> ..., (float) value           */
512                 case ICMD_L2F:
513                 case ICMD_I2D:                          /* ..., value  ==> ..., (double) value          */
514                 case ICMD_L2D:
515                 case ICMD_F2I:                          /* ..., value  ==> ..., (int) value                     */
516                 case ICMD_D2I:
517                 case ICMD_F2L:                          /* ..., value  ==> ..., (long) value            */
518                 case ICMD_D2L:  
519                 case ICMD_F2D:                          /* ..., value  ==> ..., (double) value          */
520                 case ICMD_D2F:                          /* ..., value  ==> ..., (double) value          */
521                         if (temp > 0)
522                                 return tracing(block, index-1, temp);
523                         else
524                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
525                         break;
526    
527                 /* memory operations                                                                                                    */
528                  case ICMD_ARRAYLENGTH:         /* ..., arrayref  ==> ..., length                       */
529                         if (temp > 0)
530                                 return tracing(block, index-1, temp);
531                         else
532                                 return array_length(tracing(block, index-1, 0));
533                         break;
534
535                 case ICMD_AALOAD:                       /* ..., arrayref, index  ==> ..., value         */
536                 case ICMD_LALOAD:                       /* ..., arrayref, index  ==> ..., value         */  
537                 case ICMD_IALOAD:                       /* ..., arrayref, index  ==> ..., value         */
538                 case ICMD_FALOAD:                       /* ..., arrayref, index  ==> ..., value         */
539                 case ICMD_DALOAD:                       /* ..., arrayref, index  ==> ..., value         */
540                 case ICMD_CALOAD:                       /* ..., arrayref, index  ==> ..., value         */
541                 case ICMD_SALOAD:                       /* ..., arrayref, index  ==> ..., value         */
542                 case ICMD_BALOAD:                       /* ..., arrayref, index  ==> ..., value         */
543                         if (temp > 0)           
544                                 return tracing(block, index-1, temp+1);
545                         else
546                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
547                         break;
548
549                 case ICMD_AASTORE:                      /* ..., arrayref, index, value  ==> ...         */
550                 case ICMD_LASTORE:                      /* ..., arrayref, index, value  ==> ...         */
551                 case ICMD_IASTORE:                      /* ..., arrayref, index, value  ==> ...         */
552                 case ICMD_FASTORE:                      /* ..., arrayref, index, value  ==> ...         */
553                 case ICMD_DASTORE:                      /* ..., arrayref, index, value  ==> ...         */
554                 case ICMD_CASTORE:                      /* ..., arrayref, index, value  ==> ...         */
555                 case ICMD_SASTORE:                      /* ..., arrayref, index, value  ==> ...         */
556                 case ICMD_BASTORE:                      /* ..., arrayref, index, value  ==> ...         */
557                         return tracing(block, index-1, temp+3);
558                         break;
559  
560                 case ICMD_PUTSTATIC:            /* ..., value  ==> ...                                          */
561                 case ICMD_PUTFIELD:                     /* ..., value  ==> ...                                          */
562                         return tracing(block, index-1, temp+1);
563                         break;
564  
565                 case ICMD_GETSTATIC:            /* ...  ==> ..., value                                          */
566                 case ICMD_GETFIELD:                     /* ...  ==> ..., value                                          */
567                         if (temp > 0)
568                                 return tracing(block, index-1, temp-1);
569                         else
570                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
571                         break;
572
573
574                 /* branch: should not be encountered, but function calls possible               */
575                 case ICMD_INVOKESTATIC:         /* ..., [arg1, [arg2 ...]] ==> ...                      */
576                         m = ip->val.a;                  /* get method pointer and                                       */
577                         args = ip->op1;                 /* number of arguments                                          */
578                         if (m->returntype != TYPE_VOID)
579                                 retval = 1;                     /* if function returns a value, it is on        */
580                         else                                    /* top of stack                                                         */
581                                 retval = 0;
582       
583                         if (temp > 0)                   /* temp is increased by number of arguments     */
584                                                                         /* less a possible result value                         */
585                                 return tracing(block, index-1, temp+(args-retval));
586                         else
587                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
588                         break;
589
590                 case ICMD_INVOKESPECIAL:        /* ..., objectref, [arg1, [arg2 ...]] ==> .     */
591                 case ICMD_INVOKEVIRTUAL:        /* ..., objectref, [arg1, [arg2 ...]] ==> .     */
592                 case ICMD_INVOKEINTERFACE:      /* ..., objectref, [arg1, [arg2 ...]] ==> . */
593                         m = ip->val.a;
594                         args = ip->op1; 
595                         if (m->returntype != TYPE_VOID)
596                                 retval = 1;
597                         else
598                                 retval = 0;
599                         
600                         if (temp > 0)                   /* same as above but add 1 for object ref       */
601                                 return tracing(block, index-1, temp+(args-retval+1));
602                         else
603                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
604                         break;
605  
606                 /* special                                                                                                                              */  
607                 case ICMD_INSTANCEOF:           /* ..., objectref ==> ..., intresult            */
608                 case ICMD_CHECKCAST:            /* ..., objectref ==> ..., objectref            */
609                         if (temp > 0)
610                                 return tracing(block, index-1, temp);
611                         else
612                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
613                         break;
614       
615                 case ICMD_MULTIANEWARRAY:       /* ..., cnt1, [cnt2, ...] ==> ..., arrayref     */
616                                                                         /* op1 = dimension                                                      */ 
617
618                         if (temp > 0)                   /* temp increased by number of dimensions       */
619                                                                         /* minus one for array ref                                      */
620                                 return tracing(block, index-1, temp+(ip->op1 - 1));
621                         else
622                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
623                         break;
624        
625                 case ICMD_BUILTIN3:                     /* ..., arg1, arg2, arg3 ==> ...                        */
626                         if (ip->op1 != TYPE_VOID)
627                                 retval = 1;
628                         else
629                                 retval = 0;
630       
631                         if (temp > 0)                   /* increase temp by 3 minus possible return     */
632                                                                         /* value                                                                        */
633                                 return tracing(block, index-1, temp+(3-retval));
634                         else
635                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
636                         break;
637
638                 case ICMD_BUILTIN2:                     /* ..., arg1, arg2 ==> ...                                      */
639                         if (ip->op1 != TYPE_VOID)
640                                 retval = 1;
641                         else
642                                 retval = 0;
643                         if (temp > 0)
644                                 return tracing(block, index-1, temp+(2-retval));
645                         else
646                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
647                         break;
648
649                 case ICMD_BUILTIN1:     /* ..., arg1 ==> ...                                                    */
650                         if (ip->op1 != TYPE_VOID)
651                                 retval = 1;
652                         else
653                                 retval = 0;
654                         if (temp > 0)
655                                 return tracing(block, index-1, temp+(1-retval));
656                         else
657                                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
658                         break;
659
660                 /* others                                                                                                                               */
661                 default:
662                         return create_trace(TRACE_UNKNOWN, -1, 0, index);
663                         }       /* switch       */
664                 }               /* if           */
665         else
666                 return create_trace(TRACE_UNKNOWN, -1, 0, index);
667 }
668
669
670 /*
671  * These are local overrides for various environment variables in Emacs.
672  * Please do not remove this and leave it at the end of the file, where
673  * Emacs will automagically detect them.
674  * ---------------------------------------------------------------------
675  * Local variables:
676  * mode: c
677  * indent-tabs-mode: t
678  * c-basic-offset: 4
679  * tab-width: 4
680  * End:
681  */