detect branches to middle of instruction
[cacao.git] / src / vm / jit / verify / typecheck.c
1 /* jit/typecheck.c - typechecking (part of bytecode verification)
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: Edwin Steiner
28
29    $Id: typecheck.c 726 2003-12-10 15:41:07Z edwin $
30
31 */
32
33 #include "global.h" /* must be here because of CACAO_TYPECHECK */
34
35 #ifdef CACAO_TYPECHECK
36
37 #include <string.h>
38 #include "jit.h"
39 #include "builtin.h"
40 #include "tables.h"
41 #include "loader.h"
42 #include "types.h"
43 #include "toolbox/loging.h"
44 #include "toolbox/memory.h"
45
46 #define TOUCHED_YES    0x01
47 #define TOUCHED_NO     0x02
48 #define TOUCHED_MAYBE  (TOUCHED_YES | TOUCHED_NO)
49
50 #define REACH_STD      0  /* reached by branch or fallthrough */
51 #define REACH_JSR      1  /* reached by JSR */
52 #define REACH_RET      2  /* reached by RET */ /* XXX ? */
53 #define REACH_THROW    3  /* reached by THROW (exception handler) */
54
55 /****************************************************************************/
56 /* DEBUG HELPERS                                                            */
57 /****************************************************************************/
58
59 #ifdef TYPECHECK_VERBOSE_OPT
60 bool typecheckverbose = false;
61 #define DOLOG(action)  do { if (typecheckverbose) {action;} } while(0)
62 #else
63 #define DOLOG(action)
64 #endif
65
66 #ifdef TYPECHECK_VERBOSE
67 #define TYPECHECK_VERBOSE_IMPORTANT
68 #define LOG(str)           DOLOG(log_text(str))
69 #define LOG1(str,a)        DOLOG(dolog(str,a))
70 #define LOG2(str,a,b)      DOLOG(dolog(str,a,b))
71 #define LOG3(str,a,b,c)    DOLOG(dolog(str,a,b,c))
72 #define LOGIF(cond,str)    DOLOG(do {if (cond) log_text(str);} while(0))
73 #define LOGINFO(info)      DOLOG(do {typeinfo_print_short(get_logfile(),info);log_plain("\n");} while(0))
74 #define LOGFLUSH           DOLOG(fflush(get_logfile()))
75 #define LOGNL              DOLOG(log_plain("\n"))
76 #define LOGSTR(str)        DOLOG(dolog_plain(str))
77 #define LOGSTR1(str,a)     DOLOG(dolog_plain(str,a))
78 #define LOGSTR2(str,a,b)   DOLOG(dolog_plain(str,a,b))
79 #define LOGSTR3(str,a,b,c) DOLOG(dolog_plain(str,a,b,c))
80 #define LOGSTRu(utf)       DOLOG(log_plain_utf(utf))
81 #else
82 #define LOG(str)
83 #define LOG1(str,a)
84 #define LOG2(str,a,b)
85 #define LOG3(str,a,b,c)
86 #define LOGIF(cond,str)
87 #define LOGINFO(info)
88 #define LOGFLUSH
89 #define LOGNL
90 #define LOGSTR(str)
91 #define LOGSTR1(str,a)
92 #define LOGSTR2(str,a,b)
93 #define LOGSTR3(str,a,b,c)
94 #define LOGSTRu(utf)
95 #endif
96
97 #ifdef TYPECHECK_VERBOSE_IMPORTANT
98 #define LOGimp(str)     DOLOG(log_text(str))
99 #define LOGimpSTR(str)  DOLOG(dolog_plain(str))
100 #define LOGimpSTRu(utf) DOLOG(log_plain_utf(utf))
101 #else
102 #define LOGimp(str)
103 #define LOGimpSTR(str)
104 #define LOGimpSTRu(utf)
105 #endif
106
107 #if defined(TYPECHECK_VERBOSE) || defined(TYPECHECK_VERBOSE_IMPORTANT)
108
109 #include <stdio.h>
110
111 static
112 void
113 typeinfo_print_locals(FILE *file,u1 *vtype,typeinfo *vinfo,u1 *touched,int num)
114 {
115     int i;
116
117     for (i=0; i<num; ++i) {
118         if (touched)
119             fprintf(file," %d%s=",i,
120                     (touched[i]==TOUCHED_YES) ? "*"
121                     : ((touched[i]==TOUCHED_NO) ? "" : "~"));
122         else
123             fprintf(file," %d=",i);
124         typeinfo_print_type(file,vtype[i],vinfo+i);
125     }
126 }
127
128 static
129 void
130 typeinfo_print_stack(FILE *file,stackptr stack)
131 {
132     while (stack) {
133         typeinfo_print_type(file,stack->type,&stack->typeinfo);
134         stack = stack->prev;
135         if (stack) fprintf(file," ");
136     }
137 }
138
139 static
140 void
141 typeinfo_print_block(FILE *file,stackptr instack,
142                      int vnum,u1 *vtype,typeinfo *vinfo,u1 *touched)
143 {
144     fprintf(file,"Stack: ");
145     typeinfo_print_stack(file,instack);
146     fprintf(file," Locals:");
147     typeinfo_print_locals(file,vtype,vinfo,touched,vnum);
148 }
149
150
151 static
152 void
153 typeinfo_print_blocks(FILE *file,int vnum,u1 *vtype,typeinfo *vinfo)
154 {
155     int bi;
156     /*    int j;*/
157
158     for (bi=0; bi<block_count; ++bi) {
159         fprintf(file,"%04d: (%3d) ",bi,block[bi].flags);
160         typeinfo_print_block(file,block[bi].instack,
161                              vnum,vtype+vnum*bi,vinfo+vnum*bi,NULL);
162         fprintf(file,"\n");
163
164 /*         for (j=0; j<block[bi].icount; ++j) { */
165 /*             fprintf(file,"\t%s\n",icmd_names[block[bi].iinstr[j].opc]); */
166 /*         } */
167
168         show_icmd_block(block+bi);
169     }
170 }
171
172 #endif
173
174 /****************************************************************************/
175 /* STATISTICS                                                               */
176 /****************************************************************************/
177
178 #ifdef TYPECHECK_DEBUG
179 /*#define TYPECHECK_STATISTICS*/
180 #endif
181
182 #ifdef TYPECHECK_STATISTICS
183 #define TYPECHECK_COUNT(cnt)  (cnt)++
184 #else
185 #define TYPECHECK_COUNT(cnt)
186 #endif
187
188 /****************************************************************************/
189 /* INTERNAL DATA STRUCTURES                                                 */
190 /****************************************************************************/
191
192 typedef struct jsr_record jsr_record;
193
194 /*
195  * For each basic block we store the chain of JSR instructions which
196  * were used to reach the block (usually zero or one). For more
197  * details on verifying JSR and RET instructions see the Java VM
198  * Specification.
199  *
200  * CAUTION: The fields starting with sbr_ are only valid for the
201  * jsr_record of the first block of the subroutine.
202  */
203 struct jsr_record {
204     basicblock *target;      /* target of the JSR instruction (first block of subroutine) */
205     jsr_record *next;        /* for chaining in nested try ... finally */ /* XXX make it sbr_next? */
206     u1         *sbr_touched; /* specifies which variables the subroutine touches */
207     u1         *sbr_vtype;   /* Types of local variables after RET */
208     typeinfo   *sbr_vinfo;   /* Types of local variables after RET */
209     u1          touched[1];  /* touched flags for local variables */
210 };
211
212 /****************************************************************************/
213 /* MACROS USED INTERNALLY IN typecheck()                                    */
214 /****************************************************************************/
215
216 #define TOUCH_VARIABLE(num)                                                                             \
217         do {if (jsrchain) touched[num] = TOUCHED_YES;} while (0)
218 #define TOUCH_TWOWORD(num)                                                                              \
219         do {TOUCH_VARIABLE(num);TOUCH_VARIABLE((num)+1);} while (0)
220
221 #define INDEX_ONEWORD(num)                                                                              \
222         do { if((num)<0 || (num)>=validlocals)                                          \
223                         panic("Invalid local variable index"); } while (0)
224 #define INDEX_TWOWORD(num)                                                                              \
225         do { if((num)<0 || ((num)+1)>=validlocals)                                      \
226                         panic("Invalid local variable index"); } while (0)
227
228 #define SET_VARIABLE(num,type)                                                                  \
229         do {vtype[num] = (type);                                                                        \
230                 if ((num)>0 && IS_2_WORD_TYPE(vtype[(num)-1])) {                \
231                         vtype[(num)-1] = TYPE_VOID;                                                     \
232                         TOUCH_VARIABLE((num)-1);                                                        \
233                 }                                                                                                               \
234                 TOUCH_VARIABLE(num);} while(0)
235
236 #define STORE_ONEWORD(num,type)                                                                 \
237         do {INDEX_ONEWORD(num);                                                                         \
238                 SET_VARIABLE(num,type);} while(0)
239
240 #define STORE_TWOWORD(num,type)                                                                 \
241         do {INDEX_TWOWORD(num);                                                                         \
242                 SET_VARIABLE(num,type);                                                                 \
243                 vtype[(num)+1] = TYPE_VOID;                                                             \
244                 TOUCH_VARIABLE((num)+1);} while(0)
245
246 #define CHECK_ONEWORD(num,type)                                                                                 \
247         do {INDEX_ONEWORD(num);                                                                                         \
248                 if (vtype[(num)] != (type)) panic("Variable type mismatch");    \
249                 TOUCH_VARIABLE(num);} while(0)
250
251 #define CHECK_TWOWORD(num,type)                                                                                 \
252         do {INDEX_TWOWORD(num);                                                                                         \
253                 if (vtype[(num)] != (type)) panic("Variable type mismatch");    \
254                 TOUCH_VARIABLE(num);                                                                                    \
255                 TOUCH_VARIABLE((num)+1);} while(0)
256
257 /* XXX maybe it's faster to copy always */
258 #define COPYTYPE(source,dest)   \
259             {if ((source)->type == TYPE_ADR) \
260                  TYPEINFO_COPY((source)->typeinfo,(dest)->typeinfo);}
261
262 #define ISBUILTIN(v)   (iptr->val.a == (functionptr)(v))
263
264 #define TYPECHECK_STACK(sp,tp)                                                                                  \
265         do { if ((sp)->type != (tp))                                                                            \
266                         panic("Wrong data type on stack"); } while(0)
267
268 #define TYPECHECK_ADR(sp)  TYPECHECK_STACK(sp,TYPE_ADR)
269 #define TYPECHECK_INT(sp)  TYPECHECK_STACK(sp,TYPE_INT)
270 #define TYPECHECK_LNG(sp)  TYPECHECK_STACK(sp,TYPE_LNG)
271 #define TYPECHECK_FLT(sp)  TYPECHECK_STACK(sp,TYPE_FLT)
272 #define TYPECHECK_DBL(sp)  TYPECHECK_STACK(sp,TYPE_DBL)
273
274 /* TYPECHECK_COPYVARS: copy the types and typeinfos of the current local
275  *     variables to the local variables of the target block.
276  * Input:
277  *     vtype......current local variable types
278  *     vinfo......current local variable typeinfos
279  *     ttype......local variable types of target block
280  *     tinfo......local variable typeinfos of target block
281  *     numlocals..number of local variables
282  * Used:
283  *     macro_i
284  */
285 #define TYPECHECK_COPYVARS                                      \
286     do {                                                        \
287     LOG("TYPECHECK_COPYVARS");                                  \
288     for (macro_i=0; macro_i<numlocals; ++macro_i) {             \
289         if ((ttype[macro_i] = vtype[macro_i]) == TYPE_ADR)      \
290             TYPEINFO_CLONE(vinfo[macro_i],tinfo[macro_i]);      \
291     } } while(0)
292
293 /* TYPECHECK_MERGEVARS: merge the local variables of the target block
294  *     with the current local variables.
295  * Input:
296  *     vtype......current local variable types
297  *     vinfo......current local variable typeinfos
298  *     ttype......local variable types of target block
299  *     tinfo......local variable typeinfos of target block
300  *     numlocals..number of local variables
301  * Ouput:
302  *     changed....set to true if any typeinfo has changed
303  * Used:
304  *     macro_i
305  */
306 #define TYPECHECK_MERGEVARS                                             \
307     do {                                                                \
308     LOG("TYPECHECK_MERGEVARS");                                         \
309     for (macro_i=0; macro_i<numlocals; ++macro_i) {                     \
310         if ((ttype[macro_i] != TYPE_VOID) && (vtype[macro_i] != ttype[macro_i])) { \
311             LOG3("var %d: type %d + type %d = void",macro_i,ttype[macro_i],vtype[macro_i]); \
312             ttype[macro_i] = TYPE_VOID;                                 \
313             changed = true;                                             \
314         } else if (ttype[macro_i] == TYPE_ADR) {                        \
315             if ( ((TYPEINFO_IS_PRIMITIVE(tinfo[macro_i])) ? 1 : 0)      \
316                  ^                                                      \
317                  ((TYPEINFO_IS_PRIMITIVE(vinfo[macro_i])) ? 1 : 0)) {   \
318                 LOG1("var %d: primitive + reference merge",macro_i);    \
319                 ttype[macro_i] = TYPE_VOID;                             \
320                 changed = true;                                         \
321             }                                                           \
322             else {                                                      \
323                 LOG1("var %d:",macro_i);                                \
324                 LOGINFO(tinfo+macro_i);                                 \
325                 LOGINFO(vinfo+macro_i);                                 \
326                 changed |= typeinfo_merge(tinfo+macro_i,vinfo+macro_i); \
327                 LOGINFO(tinfo+macro_i);                                 \
328                 LOGIF(changed,"vars have changed");                     \
329             }                                                           \
330         };                                                              \
331     } } while (0)
332
333 /* TYPECHECK_MERGEJSR:
334  *
335  * Input:
336  * Ouput:
337  *     tbptr......target block
338  *     changed....set to true if any typeinfo has changed
339  *     numlocals..number of local variables
340  *     touched....current touched flags of local variables
341  * Used:
342  *     macro_i, jsrtemp, jsrtemp2
343  */
344 #define TYPECHECK_MERGEJSR                                              \
345     do {                                                                \
346         LOG("TYPECHECK_MERGEJSR");                                      \
347     jsrtemp = jsrbuffer[tbptr-block];                                   \
348     jsrtemp2 = jsrchain;                                                \
349     while (jsrtemp || jsrtemp2) {                                       \
350         if (!jsrtemp || !jsrtemp2)                                      \
351             panic("Merging JSR subroutines of different depth");        \
352         if (jsrtemp->target != jsrtemp2->target)                        \
353             panic("Merging different JSR subroutines");                 \
354         jsrtemp = jsrtemp->next;                                        \
355         jsrtemp2 = jsrtemp2->next;                                      \
356     }                                                                   \
357     jsrtemp = jsrbuffer[tbptr-block];                                   \
358     if (jsrtemp)                                                        \
359         for (macro_i=0; macro_i<numlocals; ++macro_i) {                 \
360             jsrtemp->touched[i] |= touched[i];                          \
361     } } while (0)
362
363 /* TYPECHECK_COPYSTACK: copy the typeinfos of the current stack to
364  *     the input stack of the target block.
365  * Input:
366  *     srcstack...current stack
367  *     dststack...input stack of target block
368  */
369 #define TYPECHECK_COPYSTACK                                             \
370     do {                                                                \
371     LOG("TYPECHECK_COPYSTACK");                                         \
372     while (srcstack) {                                                  \
373         LOG1("copy %d",srcstack->type);                                 \
374         if (!dststack) panic("Stack depth mismatch");                   \
375         if (srcstack->type != dststack->type)                           \
376             panic("Type mismatch on stack");                            \
377         if (srcstack->type == TYPE_ADR) {                               \
378             TYPEINFO_CLONE(srcstack->typeinfo,dststack->typeinfo);      \
379         }                                                               \
380         dststack = dststack->prev;                                      \
381         srcstack = srcstack->prev;                                      \
382     }                                                                   \
383     if (dststack) panic("Stack depth mismatch");                        \
384     } while (0)
385
386 /* TYPECHECK_MERGESTACK: merge the input stack of the target block
387  *     with the current stack.
388  * Input:
389  *     srcstack...current stack
390  *     dststack...input stack of target block
391  * Ouput:
392  *     changed....set to true if any typeinfo has changed
393  */
394 #define TYPECHECK_MERGESTACK                                            \
395     do {                                                                \
396     LOG("TYPECHECK_MERGESTACK");                                        \
397     while (srcstack) {                                                  \
398         if (!dststack) panic("Stack depth mismatch");                   \
399         if (srcstack->type != dststack->type)                           \
400             panic("Type mismatch on stack");                            \
401         if (srcstack->type == TYPE_ADR) {                               \
402             LOGINFO(&dststack->typeinfo);                               \
403             LOGINFO(&srcstack->typeinfo);  LOGFLUSH;                    \
404             changed |= typeinfo_merge(&dststack->typeinfo,              \
405                                       &srcstack->typeinfo);             \
406             LOGINFO(&dststack->typeinfo);                               \
407             LOG((changed)?"CHANGED!\n":"not changed.\n");               \
408         }                                                               \
409         dststack = dststack->prev;                                      \
410         srcstack = srcstack->prev;                                      \
411     }                                                                   \
412     if (dststack) panic("Stack depth mismatch");                        \
413     } while(0)
414
415
416 /* TYPECHECK_CHECK_JSR_CHAIN: checks if the target block is reached by
417  *     the same JSR targets on all control paths.
418  *
419  * Input:
420  *     tbptr......target block
421  *     jsrchain...current JSR target chain
422  *     jsrbuffer..JSR target chain for each basic block
423  * Output:
424  *     panic if the JSR target chains don't match
425  * Used:
426  *     jsrtemp, jsrtemp2
427  */
428 #define TYPECHECK_CHECK_JSR_CHAIN                                       \
429     do {                                                                \
430     jsrtemp = jsrbuffer[tbptr-block];                                   \
431     if (!jsrtemp) panic("non-subroutine called by JSR");                \
432     if (jsrtemp->target != tbptr)                                       \
433         panic("Merging different JSR subroutines");                     \
434     jsrtemp = jsrtemp->next;                                            \
435     jsrtemp2 = jsrchain;                                                \
436     while (jsrtemp || jsrtemp2) {                                       \
437         if (!jsrtemp || !jsrtemp2)                                      \
438             panic("Merging JSR subroutines of different depth");        \
439         if (jsrtemp->target != jsrtemp2->target)                        \
440             panic("Merging different JSR subroutines");                 \
441         jsrtemp = jsrtemp->next;                                        \
442         jsrtemp2 = jsrtemp2->next;                                      \
443     } } while (0)
444
445 /* TYPECHECK_ADD_JSR: add a JSR target to the current JSR target chain
446  *     and store the resulting chain in the target block.
447  *
448  * Input:
449  *     jsrchain...current JSR target chain
450  *     tbptr.....the basic block targeted by the JSR
451  *     numlocals..number of local variables
452  *     jsrbuffer..JSR target chain for each basic block
453  * Used:
454  *     jsrtemp
455  */
456 #define TYPECHECK_ADD_JSR                                               \
457     do {                                                                \
458         LOG1("adding JSR to block %04d",(tbptr)-block);                 \
459     jsrtemp = (jsr_record *) dump_alloc(sizeof(jsr_record)+(numlocals-1)*sizeof(u1)); \
460     jsrtemp->target = (tbptr);                                          \
461     jsrtemp->next = jsrchain;                                           \
462     jsrtemp->sbr_touched = NULL;                                        \
463     memset(&jsrtemp->touched,TOUCHED_NO,sizeof(u1)*numlocals);          \
464     jsrbuffer[tbptr-block] = jsrtemp;                                   \
465     } while (0)
466
467 /* TYPECHECK_COPYJSR: copy the current JSR chain to the target block.
468  *
469  * Input:
470  *     chain......current JSR target chain
471  *     tbptr.....the basic block targeted by the JSR
472  *     numlocals..number of local variables
473  *     jsrbuffer..JSR target chain for each basic block
474  *     touched....current touched flags of local variables
475  * Used:
476  *     jsrtemp
477  */
478 #define TYPECHECK_COPYJSR(chain)                                        \
479     do {                                                                \
480         LOG("TYPECHECK_COPYJSR");                                       \
481         if (chain) {                                                    \
482             jsrtemp = (jsr_record *) dump_alloc(sizeof(jsr_record)+(numlocals-1)*sizeof(u1)); \
483             jsrtemp->target = (chain)->target;                          \
484             jsrtemp->next = (chain)->next;                              \
485             jsrtemp->sbr_touched = NULL;                                \
486             memcpy(&jsrtemp->touched,touched,sizeof(u1)*numlocals);     \
487             jsrbuffer[tbptr-block] = jsrtemp;                           \
488         }                                                               \
489         else                                                            \
490             jsrbuffer[tbptr-block] = NULL;                              \
491     } while (0)
492
493 /* TYPECHECK_BRANCH_BACKWARDS: executed when control flow moves
494  *     backwards. Checks if there are uninitialized objects on the
495  *     stack or in local variables.
496  * Input:
497  *     dst........current output stack pointer (not needed for REACH_THROW)
498  *     vtype......current local variable types
499  *     vinfo......current local variable typeinfos
500  * Used:
501  *     srcstack, macro_i
502  */
503 #define TYPECHECK_BRANCH_BACKWARDS                                      \
504     do {                                                                \
505         LOG("BACKWARDS!");                                              \
506         srcstack = dst;                                                 \
507         while (srcstack) {                                              \
508             if (srcstack->type == TYPE_ADR &&                           \
509                 TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo))              \
510                 panic("Branching backwards with uninitialized object on stack"); \
511             srcstack = srcstack->prev;                                  \
512         }                                                               \
513         for (macro_i=0; macro_i<numlocals; ++macro_i)                   \
514             if (vtype[macro_i] == TYPE_ADR &&                           \
515                 TYPEINFO_IS_NEWOBJECT(vinfo[macro_i]))                  \
516                 panic("Branching backwards with uninitialized object in local variable"); \
517     } while(0)
518
519 /* TYPECHECK_REACH: executed, when the target block (tbptr) can be reached
520  *     from the current block (bptr). The types of local variables and
521  *     stack slots are propagated to the target block.
522  * Input:
523  *     bptr.......current block
524  *     tbptr......target block
525  *     dst........current output stack pointer (not needed for REACH_THROW)
526  *     numlocals..number of local variables
527  *     vtype......current local variable types
528  *     vinfo......current local variable typeinfos
529  *     jsrchain...current JSR target chain
530  *     jsrbuffer..JSR target chain for each basic block
531  *     way........in which way the block is reached (REACH_ constant)
532  *     touched....current touched flags of local variables
533  * Output:
534  *     repeat.....changed to true if a block before the current
535  *                block has changed
536  * Used:
537  *     ttype, tinfo, srcstack, dststack, changed, macro_i
538  */
539 #define TYPECHECK_REACH(way)                                            \
540     do {                                                                \
541     LOG2("reaching block %04d (%d)",tbptr-block,way);                   \
542     if (tbptr <= bptr && way != REACH_THROW)                            \
543         TYPECHECK_BRANCH_BACKWARDS;                                     \
544     srcstack = dst;                                                     \
545     dststack = tbptr->instack;                                          \
546     ttype = vartype + numlocals*(tbptr-block);                          \
547     tinfo = vartypeinfo + numlocals*(tbptr-block);                      \
548     if (tbptr->flags == BBTYPECHECK_UNDEF) {                            \
549         /* This block is reached for the first time */                  \
550         if (way == REACH_JSR) {                                         \
551             TYPECHECK_ADD_JSR;                                          \
552             TYPECHECK_COPYVARS;                                         \
553         }                                                               \
554         else {                                                          \
555             TYPECHECK_COPYJSR(jsrchain);                                \
556             TYPECHECK_COPYVARS;                                         \
557         }                                                               \
558         if (way != REACH_THROW) TYPECHECK_COPYSTACK;                    \
559         changed = true;                                                 \
560     } else {                                                            \
561         /* This block has been reached before */                        \
562         changed = false;                                                \
563         if (way == REACH_JSR)                                           \
564             TYPECHECK_CHECK_JSR_CHAIN;                                  \
565         else                                                            \
566             TYPECHECK_MERGEJSR;                                         \
567         TYPECHECK_MERGEVARS;                                            \
568         if (way != REACH_THROW) TYPECHECK_MERGESTACK;                   \
569     }                                                                   \
570     if (changed) {                                                      \
571         LOG("REACHED!");                                                \
572         tbptr->flags = BBTYPECHECK_REACHED;                             \
573         if (tbptr <= bptr) {repeat = true; LOG("REPEAT!");}             \
574     }                                                                   \
575     LOG("done.");                                                       \
576     } while (0)
577
578 /* TYPECHECK_LEAVE: executed when the method is exited non-abruptly
579  * Input:
580  *     class........class of the current method
581  *     numlocals....number of local variables
582  *     vtype........current local variable types
583  *     vinfo........current local variable typeinfos
584  *     initmethod...true if this is an <init> method
585  */
586 #define TYPECHECK_LEAVE                                                 \
587     do {                                                                \
588         if (initmethod && class != class_java_lang_Object) {            \
589             /* check the marker variable */                             \
590             LOG("Checking <init> marker");                              \
591             if (vtype[numlocals-1] == TYPE_VOID)                        \
592                 panic("<init> method does not initialize 'this'");      \
593         }                                                               \
594     } while (0)
595
596 /****************************************************************************/
597 /* typecheck()                                                              */
598 /****************************************************************************/
599
600 #define MAXPARAMS 255
601
602 /* typecheck is called directly after analyse_stack */
603 void
604 typecheck()
605 {
606     int b_count, b_index;
607     stackptr curstack;      /* input stack top for current instruction */
608     stackptr srcstack;         /* source stack for copying and merging */
609     stackptr dststack;         /* target stack for copying and merging */
610     int opcode;                                      /* current opcode */
611     int macro_i, i;                              /* temporary counters */
612     int len;                        /* for counting instructions, etc. */
613     bool superblockend;        /* true if no fallthrough to next block */
614     bool repeat;            /* if true, blocks are iterated over again */
615     bool changed;                                    /* used in macros */
616     instruction *iptr;               /* pointer to current instruction */
617     basicblock *bptr;                /* pointer to current basic block */
618     basicblock *tbptr;                   /* temporary for target block */
619     int numlocals;                        /* number of local variables */
620         int validlocals;         /* number of valid local variable indices */
621     u1 *vartype;            /* type of each local for each basic block */
622     typeinfo *vartypeinfo;  /* type of each local for each basic block */
623     u1 *vtype;           /* type of each local for current instruction */
624     typeinfo *vinfo;     /* type of each local for current instruction */
625     u1 *ttype;                                    /* temporary pointer */
626     typeinfo *tinfo;                              /* temporary pointer */
627     typeinfo tempinfo;                                    /* temporary */
628     int returntype;                   /* return type of current method */
629     typeinfo returntypeinfo;               /* typeinfo for return type */
630     u1 *ptype;                     /* parameter types of called method */
631     typeinfo *pinfo;           /* parameter typeinfos of called method */
632     int rtype;                         /* return type of called method */
633     typeinfo rinfo;       /* typeinfo for return type of called method */
634     stackptr dst;               /* output stack of current instruction */
635     basicblock **tptr;    /* pointer into target list of switch instructions */
636     jsr_record **jsrbuffer;   /* JSR target chain for each basic block */
637     jsr_record *jsrchain;               /* JSR chain for current block */
638     jsr_record *jsrtemp,*jsrtemp2;              /* temporary variables */
639     jsr_record *subroutine;    /* jsr_record of the current subroutine */
640     u1 *touched;                  /* touched flags for local variables */
641     xtable **handlers;                    /* active exception handlers */
642     classinfo *cls;                                       /* temporary */
643     bool maythrow;               /* true if this instruction may throw */
644     utf *name_init;                                        /* "<init>" */
645     bool initmethod;             /* true if this is an "<init>" method */
646
647 #ifdef TYPECHECK_STATISTICS
648         int count_iterations = 0;
649 #endif
650
651     LOGSTR("\n==============================================================================\n");
652     DOLOG(show_icmd_method());
653     LOGSTR("\n==============================================================================\n");
654     LOGimpSTR("Entering typecheck: ");
655     LOGimpSTRu(method->name);
656     LOGimpSTR("    ");
657     LOGimpSTRu(method->descriptor);
658     LOGimpSTR("    (class ");
659     LOGimpSTRu(method->class->name);
660     LOGimpSTR(")\n");
661
662     name_init = utf_new_char("<init>");
663     initmethod = (method->name == name_init);
664
665     ptype = DMNEW(u1,MAXPARAMS);
666     pinfo = DMNEW(typeinfo,MAXPARAMS);
667     
668     LOG("Buffer allocated.\n");
669
670     /* reset all BBFINISHED blocks to BBTYPECHECK_UNDEF. */
671     b_count = block_count;
672     bptr = block;
673     while (--b_count >= 0) {
674 #ifdef TYPECHECK_DEBUG
675         if (bptr->flags != BBFINISHED && bptr->flags != BBDELETED
676             && bptr->flags != BBUNDEF)
677         {
678             show_icmd_method();
679             LOGSTR1("block flags: %d\n",bptr->flags); LOGFLUSH;
680             panic("Internal error: Unexpected block flags in typecheck()");
681         }
682 #endif
683         if (bptr->flags >= BBFINISHED) {
684             bptr->flags = BBTYPECHECK_UNDEF;
685         }
686         bptr++;
687     }
688
689     /* The first block is always reached */
690     if (block_count && block[0].flags == BBTYPECHECK_UNDEF)
691         block[0].flags = BBTYPECHECK_REACHED;
692
693     LOG("Blocks reset.\n");
694
695     /* number of local variables */
696     
697     /* In <init> methods we use an extra local variable to signal if
698      * the 'this' reference has been initialized. */
699     numlocals = maxlocals;
700         validlocals = numlocals;
701     if (initmethod) numlocals++;
702
703     /* allocate the buffers for local variables */
704     vartype = DMNEW(u1,numlocals * (block_count+1));
705     vartypeinfo = DMNEW(typeinfo,numlocals * (block_count+1));
706     touched = DMNEW(u1,numlocals);
707     vtype = vartype + numlocals * block_count;
708     vinfo = vartypeinfo + numlocals * block_count;
709     memset(vartype,TYPE_VOID,numlocals * (block_count+1) * sizeof(typeinfo));
710     memset(vartypeinfo,0,numlocals * (block_count+1) * sizeof(typeinfo));
711
712     LOG("Variable buffer initialized.\n");
713
714     /* allocate the buffer for storing JSR target chains */
715     jsrbuffer = DMNEW(jsr_record*,block_count);
716     memset(jsrbuffer,0,block_count * sizeof(jsr_record*));
717     jsrchain = NULL;
718     
719     LOG("jsrbuffer initialized.\n");
720
721     /* allocate the buffer of active exception handlers */
722     handlers = DMNEW(xtable*,method->exceptiontablelength + 1);
723
724     /* initialize the variable types of the first block */
725     /* to the types of the arguments */
726     ttype = vartype;
727     tinfo = vartypeinfo;
728
729     /* if this is an instance method initialize the "this" ref type */
730     if (!(method->flags & ACC_STATIC)) {
731         *ttype++ = TYPE_ADDRESS;
732         if (initmethod)
733             TYPEINFO_INIT_NEWOBJECT(*tinfo,NULL);
734         else
735             TYPEINFO_INIT_CLASSINFO(*tinfo,class);
736         tinfo++;
737     }
738
739     LOG("'this' argument set.\n");
740
741     /* the rest of the arguments and the return type */
742     typeinfo_init_from_method_args(method->descriptor,ttype,tinfo,
743                                    numlocals - (tinfo-vartypeinfo),
744                                    true, /* two word types use two slots */
745                                    &returntype,&returntypeinfo);
746
747     LOG("Arguments set.\n");
748
749     /* initialize the input stack of exception handlers */
750     for (i=0; i<method->exceptiontablelength; ++i) {
751         cls = extable[i].catchtype;
752         if (!cls) cls = class_java_lang_Throwable;
753         LOGSTR1("handler %i: ",i); LOGSTRu(cls->name); LOGNL;
754         TYPEINFO_INIT_CLASSINFO(extable[i].handler->instack->typeinfo,cls);
755     }
756
757     LOG("Exception handler stacks set.\n");
758
759     /* loop while there are still blocks to be checked */
760     do {
761                 TYPECHECK_COUNT(count_iterations);
762
763         repeat = false;
764         
765         b_count = block_count;
766         bptr = block;
767
768         while (--b_count >= 0) {
769             LOGSTR1("---- BLOCK %04d, ",bptr-block);
770             LOGSTR1("blockflags: %d\n",bptr->flags);
771             LOGFLUSH;
772                 
773             if (bptr->flags == BBTYPECHECK_REACHED) {
774                 LOGSTR1("\n---- BLOCK %04d ------------------------------------------------\n",bptr-block);
775                 LOGFLUSH;
776                 
777                 superblockend = false;
778                 bptr->flags = BBFINISHED;
779                 b_index = bptr - block;
780
781                 /* init stack at the start of this block */
782                 curstack = bptr->instack;
783                                         
784                 /* determine the active exception handlers for this block */
785                 /* XXX could use a faster algorithm with sorted lists or
786                  * something? */
787                 len = 0;
788                 for (i=0; i<method->exceptiontablelength; ++i) {
789                     if ((extable[i].start <= bptr) && (extable[i].end > bptr)) {
790                         LOG1("active handler L%03d",extable[i].handler->debug_nr);
791                         handlers[len++] = extable + i;
792                     }
793                 }
794                 handlers[len] = NULL;
795                                         
796                 /* init variable types at the start of this block */
797                 for (i=0; i<numlocals; ++i) {
798                     vtype[i] = vartype[numlocals*b_index + i];
799                     TYPEINFO_COPY(vartypeinfo[numlocals*b_index + i],vinfo[i]);
800
801                     if (handlers[0] &&
802                         vtype[i] == TYPE_ADR && TYPEINFO_IS_NEWOBJECT(vinfo[i]))
803                         panic("Uninitialized object in local variable inside try block");
804                 }
805
806                 /* init JSR target chain */
807                 if ((jsrchain = jsrbuffer[b_index]) != NULL) {
808 #ifdef TYPECHECK_VERBOSE
809                     if (typecheckverbose) {
810                         LOGSTR("jsr chain:");
811                         jsrtemp = jsrchain;
812                         while (jsrtemp) {
813                             LOGSTR1(" L%03d",jsrtemp->target->debug_nr);
814                             jsrtemp = jsrtemp->next;
815                         }
816                         LOGNL;
817                         LOGFLUSH;
818                     }
819 #endif
820
821                     subroutine = jsrbuffer[jsrchain->target - block];
822                     memcpy(touched,jsrchain->touched,sizeof(u1)*numlocals);
823                 }
824                 else
825                     subroutine = NULL;
826 #ifdef TYPECHECK_VERBOSE
827                 if (typecheckverbose) {
828                     if (subroutine) {LOGSTR1("subroutine L%03d\n",subroutine->target->debug_nr);LOGFLUSH;}
829                     typeinfo_print_block(get_logfile(),curstack,numlocals,vtype,vinfo,(jsrchain) ? touched : NULL);
830                     LOGNL; LOGFLUSH;
831                 }
832 #endif
833
834                 /* loop over the instructions */
835                 len = bptr->icount;
836                 iptr = bptr->iinstr;
837                 while (--len >= 0)  {
838                     DOLOG(show_icmd(iptr,false));
839                     LOGNL;
840                     LOGFLUSH;
841                         
842                     opcode = iptr->opc;
843                     dst = iptr->dst;
844                     maythrow = false;
845                                                 
846                     switch (opcode) {
847
848                         /****************************************/
849                         /* STACK MANIPULATIONS                  */
850
851                         /* We just need to copy the typeinfo */
852                         /* for slots containing addresses.   */
853
854                         /* XXX We assume that the destination stack
855                          * slots were continuously allocated in
856                          * memory.  (The current implementation in
857                          * stack.c)
858                          */
859
860                       case ICMD_DUP:
861                           COPYTYPE(curstack,dst);
862                           break;
863                                                           
864                       case ICMD_DUP_X1:
865                           COPYTYPE(curstack,dst);
866                           COPYTYPE(curstack,dst-2);
867                           COPYTYPE(curstack->prev,dst-1);
868                           break;
869                                                           
870                       case ICMD_DUP_X2:
871                           COPYTYPE(curstack,dst);
872                           COPYTYPE(curstack,dst-3);
873                           COPYTYPE(curstack->prev,dst-1);
874                           COPYTYPE(curstack->prev->prev,dst-2);
875                           break;
876                                                           
877                       case ICMD_DUP2:
878                           COPYTYPE(curstack,dst);
879                           COPYTYPE(curstack->prev,dst-1);
880                           break;
881
882                       case ICMD_DUP2_X1:
883                           COPYTYPE(curstack,dst);
884                           COPYTYPE(curstack->prev,dst-1);
885                           COPYTYPE(curstack,dst-3);
886                           COPYTYPE(curstack->prev,dst-4);
887                           COPYTYPE(curstack->prev->prev,dst-2);
888                           break;
889                                                           
890                       case ICMD_DUP2_X2:
891                           COPYTYPE(curstack,dst);
892                           COPYTYPE(curstack->prev,dst-1);
893                           COPYTYPE(curstack,dst-4);
894                           COPYTYPE(curstack->prev,dst-5);
895                           COPYTYPE(curstack->prev->prev,dst-2);
896                           COPYTYPE(curstack->prev->prev->prev,dst-3);
897                           break;
898                                                           
899                       case ICMD_SWAP:
900                           COPYTYPE(curstack,dst-1);
901                           COPYTYPE(curstack->prev,dst);
902                           break;
903
904                           /****************************************/
905                           /* LOADING ADDRESS FROM VARIABLE        */
906
907                       case ICMD_ALOAD:
908                           CHECK_ONEWORD(iptr->op1,TYPE_ADR);
909                           
910                           /* loading a returnAddress is not allowed */
911                           if (TYPEINFO_IS_PRIMITIVE(vinfo[iptr->op1]))
912                               panic("illegal instruction: ALOAD loading returnAddress");
913
914                           TYPEINFO_COPY(vinfo[iptr->op1],dst->typeinfo);
915                           break;
916                                                         
917                           /****************************************/
918                           /* STORING ADDRESS TO VARIABLE          */
919
920                       case ICMD_ASTORE:
921                           if (handlers[0] &&
922                               TYPEINFO_IS_NEWOBJECT(curstack->typeinfo))
923                               panic("Storing uninitialized object in local variable inside try block");
924                           
925                           STORE_ONEWORD(iptr->op1,TYPE_ADDRESS);
926                           TYPEINFO_COPY(curstack->typeinfo,vinfo[iptr->op1]);
927                           break;
928                           
929                           /****************************************/
930                           /* LOADING ADDRESS FROM ARRAY           */
931
932                       case ICMD_AALOAD:
933                           if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(curstack->prev->typeinfo))
934                               panic("illegal instruction: AALOAD on non-reference array");
935
936                           typeinfo_init_component(&curstack->prev->typeinfo,&dst->typeinfo);
937                           maythrow = true;
938                           break;
939                                                           
940                           /****************************************/
941                           /* FIELD ACCESS                         */
942
943                       case ICMD_PUTFIELD:
944                           if (!TYPEINFO_IS_REFERENCE(curstack->prev->typeinfo))
945                               panic("illegal instruction: PUTFIELD on non-reference");
946                           if (TYPEINFO_IS_ARRAY(curstack->prev->typeinfo)) /* XXX arraystub */
947                               panic("illegal instruction: PUTFIELD on array");
948
949                           
950                           /* XXX */
951                           maythrow = true;
952                           break;
953
954                       case ICMD_PUTSTATIC:
955                           /* XXX */
956                           maythrow = true;
957                           break;
958
959                       case ICMD_GETFIELD:
960                           if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
961                               panic("illegal instruction: GETFIELD on non-reference");
962                           if (TYPEINFO_IS_ARRAY(curstack->typeinfo))
963                               panic("illegal instruction: GETFIELD on array");
964                           
965                           {
966                               fieldinfo *fi = (fieldinfo *)(iptr->val.a);
967                               /* XXX check non-static? */
968                               if (dst->type == TYPE_ADR) {
969                                   TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi);
970                               }
971                               else {
972                                   /* XXX check field type? */
973                                   TYPEINFO_INIT_PRIMITIVE(dst->typeinfo);
974                               }
975                           }
976                           maythrow = true;
977                           break;
978
979                       case ICMD_GETSTATIC:
980                           {
981                               fieldinfo *fi = (fieldinfo *)(iptr->val.a);
982                               /* XXX check static? */
983                               if (dst->type == TYPE_ADR) {
984                                   TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi);
985                               }
986                               else {
987                                   /* XXX check field type? */
988                                   TYPEINFO_INIT_PRIMITIVE(dst->typeinfo);
989                               }
990                           }
991                           maythrow = true;
992                           break;
993
994                           /****************************************/
995                           /* PRIMITIVE ARRAY ACCESS               */
996
997                       case ICMD_ARRAYLENGTH:
998                           /* XXX should this also work on arraystubs? */
999                           if (!TYPEINFO_MAYBE_ARRAY(curstack->typeinfo))
1000                               panic("illegal instruction: ARRAYLENGTH on non-array");
1001                           maythrow = true;
1002                           break;
1003                                                           
1004                       case ICMD_BALOAD:
1005                           if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_BOOLEAN)
1006                               && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_BYTE))
1007                               panic("Array type mismatch");
1008                           maythrow = true;
1009                           break;
1010                       case ICMD_CALOAD:
1011                           if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_CHAR))
1012                               panic("Array type mismatch");
1013                           maythrow = true;
1014                           break;
1015                       case ICMD_DALOAD:
1016                           if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_DOUBLE))
1017                               panic("Array type mismatch");
1018                           maythrow = true;
1019                           break;
1020                       case ICMD_FALOAD:
1021                           if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_FLOAT))
1022                               panic("Array type mismatch");
1023                           maythrow = true;
1024                           break;
1025                       case ICMD_IALOAD:
1026                           if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_INT))
1027                               panic("Array type mismatch");
1028                           maythrow = true;
1029                           break;
1030                       case ICMD_SALOAD:
1031                           if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_SHORT))
1032                               panic("Array type mismatch");
1033                           maythrow = true;
1034                           break;
1035                       case ICMD_LALOAD:
1036                           if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_LONG))
1037                               panic("Array type mismatch");
1038                           maythrow = true;
1039                           break;
1040
1041                       case ICMD_BASTORE:
1042                           if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_BOOLEAN)
1043                               && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_BYTE))
1044                               panic("Array type mismatch");
1045                           maythrow = true;
1046                           break;
1047                       case ICMD_CASTORE:
1048                           if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_CHAR))
1049                               panic("Array type mismatch");
1050                           maythrow = true;
1051                           break;
1052                       case ICMD_DASTORE:
1053                           if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_DOUBLE))
1054                               panic("Array type mismatch");
1055                           maythrow = true;
1056                           break;
1057                       case ICMD_FASTORE:
1058                           if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_FLOAT))
1059                               panic("Array type mismatch");
1060                           maythrow = true;
1061                           break;
1062                       case ICMD_IASTORE:
1063                           if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_INT))
1064                               panic("Array type mismatch");
1065                           maythrow = true;
1066                           break;
1067                       case ICMD_SASTORE:
1068                           if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_SHORT))
1069                               panic("Array type mismatch");
1070                           maythrow = true;
1071                           break;
1072                       case ICMD_LASTORE:
1073                           if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_LONG))
1074                               panic("Array type mismatch");
1075                           maythrow = true;
1076                           break;
1077
1078                           /****************************************/
1079                           /* OPERATIONS WITH UNCHECKED INPUT      */
1080
1081                       case ICMD_CHECKCAST:
1082                                                   TYPECHECK_ADR(curstack);
1083                           /* returnAddress is not allowed */
1084                           if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1085                               panic("Illegal instruction: CHECKCAST on non-reference");
1086
1087                           /* XXX check if the cast can be done statically */
1088                           TYPEINFO_INIT_CLASSINFO(dst->typeinfo,(classinfo *)iptr[0].val.a);
1089                           /* XXX */
1090                           maythrow = true;
1091                           break;
1092
1093                       case ICMD_INSTANCEOF:
1094                                                   TYPECHECK_ADR(curstack);
1095                           /* returnAddress is not allowed */
1096                           if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1097                               panic("Illegal instruction: INSTANCEOF on non-reference");
1098                           
1099                           /* XXX optimize statically? */
1100                           break;
1101                           
1102                       case ICMD_ACONST:
1103                           if (iptr->val.a == NULL)
1104                               TYPEINFO_INIT_NULLTYPE(dst->typeinfo);
1105                           else
1106                               /* XXX constants for builtin functions */
1107                               /* string constants */
1108                               TYPEINFO_INIT_CLASSINFO(dst->typeinfo,class_java_lang_String);
1109                           break;
1110
1111                           /****************************************/
1112                           /* BRANCH INSTRUCTIONS                  */
1113
1114                       case ICMD_GOTO:
1115                           superblockend = true;
1116                           /* FALLTHROUGH! */
1117                       case ICMD_IFNULL:
1118                       case ICMD_IFNONNULL:
1119                       case ICMD_IFEQ:
1120                       case ICMD_IFNE:
1121                       case ICMD_IFLT:
1122                       case ICMD_IFGE:
1123                       case ICMD_IFGT:
1124                       case ICMD_IFLE:
1125                       case ICMD_IF_ICMPEQ:
1126                       case ICMD_IF_ICMPNE:
1127                       case ICMD_IF_ICMPLT:
1128                       case ICMD_IF_ICMPGE:
1129                       case ICMD_IF_ICMPGT:
1130                       case ICMD_IF_ICMPLE:
1131                       case ICMD_IF_ACMPEQ:
1132                       case ICMD_IF_ACMPNE:
1133                       case ICMD_IF_LEQ:
1134                       case ICMD_IF_LNE:
1135                       case ICMD_IF_LLT:
1136                       case ICMD_IF_LGE:
1137                       case ICMD_IF_LGT:
1138                       case ICMD_IF_LLE:
1139                       case ICMD_IF_LCMPEQ:
1140                       case ICMD_IF_LCMPNE:
1141                       case ICMD_IF_LCMPLT:
1142                       case ICMD_IF_LCMPGE:
1143                       case ICMD_IF_LCMPGT:
1144                       case ICMD_IF_LCMPLE:
1145                           tbptr = (basicblock *) iptr->target;
1146
1147                           /* propagate stack and variables to the target block */
1148                           TYPECHECK_REACH(REACH_STD);
1149                           /* XXX */
1150                           break;
1151
1152                           /****************************************/
1153                           /* SWITCHES                             */
1154                           
1155                       case ICMD_TABLESWITCH:
1156                           {
1157                               s4 *s4ptr = iptr->val.a;
1158                               s4ptr++; /* skip default */
1159                               i = *s4ptr++; /* low */
1160                               i = *s4ptr++ - i + 2; /* +1 for default target */
1161                           }
1162                           goto switch_instruction_tail;
1163                           
1164                       case ICMD_LOOKUPSWITCH:
1165                           {
1166                               s4 *s4ptr = iptr->val.a;
1167                               s4ptr++; /* skip default */
1168                               i = *s4ptr++ + 1; /* count +1 for default target */
1169                           }
1170                     switch_instruction_tail:
1171                           tptr = (basicblock **)iptr->target;
1172                           
1173                           while (--i >= 0) {
1174                               tbptr = *tptr++;
1175                               LOG2("target %d is block %04d",(tptr-(basicblock **)iptr->target)-1,tbptr-block);
1176                               TYPECHECK_REACH(REACH_STD);
1177                           }
1178                           LOG("switch done");
1179                           superblockend = true;
1180                           break;
1181
1182                           /****************************************/
1183                           /* RETURNS AND THROW                    */
1184
1185                       case ICMD_ATHROW:
1186                           TYPEINFO_INIT_CLASSINFO(tempinfo,class_java_lang_Throwable);
1187                           if (!typeinfo_is_assignable(&curstack->typeinfo,&tempinfo))
1188                               panic("illegal instruction: ATHROW on non-Throwable");
1189                           superblockend = true;
1190                           maythrow = true;
1191                           break;
1192
1193                       case ICMD_ARETURN:
1194                           if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1195                               panic("illegal instruction: ARETURN on non-reference");
1196
1197                           if (returntype != TYPE_ADDRESS
1198                               || !typeinfo_is_assignable(&curstack->typeinfo,&returntypeinfo))
1199                               panic("Return type mismatch");
1200                                                   goto return_tail;
1201                                                   
1202                       case ICMD_IRETURN:
1203                           if (returntype != TYPE_INT) panic("Return type mismatch");
1204                                                   goto return_tail;
1205                                                   
1206                       case ICMD_LRETURN:
1207                           if (returntype != TYPE_LONG) panic("Return type mismatch");
1208                                                   goto return_tail;
1209                                                   
1210                       case ICMD_FRETURN:
1211                           if (returntype != TYPE_FLOAT) panic("Return type mismatch");
1212                                                   goto return_tail;
1213                                                   
1214                       case ICMD_DRETURN:
1215                           if (returntype != TYPE_DOUBLE) panic("Return type mismatch");
1216                                                   goto return_tail;
1217                                                   
1218                       case ICMD_RETURN:
1219                           if (returntype != TYPE_VOID) panic("Return type mismatch");
1220                                           return_tail:
1221                           TYPECHECK_LEAVE;
1222                           superblockend = true;
1223                           maythrow = true;
1224                           break;
1225                                                     
1226                           /****************************************/
1227                           /* SUBROUTINE INSTRUCTIONS              */
1228
1229                       case ICMD_JSR:
1230                           LOG("jsr");
1231
1232                           /* XXX This is a dirty hack. It is needed
1233                            * because of the special handling of ICMD_JSR in stack.c
1234                            */
1235                           dst = (stackptr) iptr->val.a;
1236                           
1237                           /* push return address */
1238                           TYPEINFO_INIT_PRIMITIVE(dst->typeinfo);
1239
1240                           LOG("reaching block...");
1241                           
1242                           /* add the target to the JSR target chain and */
1243                           /* propagate stack and variables to the target block */
1244                           tbptr = (basicblock *) iptr->target;
1245                           TYPECHECK_REACH(REACH_JSR);
1246
1247                           /* set dst to the stack after the subroutine execution */
1248                           /* XXX We assume (as in stack.c) that the
1249                            * subroutine returns the stack as it was
1250                            * before the JSR instruction. Is this
1251                            * correct?
1252                            */
1253                           dst = iptr->dst;
1254
1255                           /* Find the jsr_record of the called subroutine */
1256                           jsrtemp = jsrbuffer[tbptr - block];
1257
1258                           /* Check if we already calculated (at least
1259                            * for one RET) which variables the
1260                            * subroutine touches.
1261                            */
1262                           if (jsrtemp->sbr_touched) {
1263                               /* Calculate the local variables after the subroutine call */
1264                               for (i=0; i<numlocals; ++i)
1265                                   if (jsrtemp->sbr_touched[i] != TOUCHED_NO) {
1266                                       TOUCH_VARIABLE(i);
1267                                       if ((vtype[i] = jsrtemp->sbr_vtype[i]) == TYPE_ADR)
1268                                           TYPEINFO_CLONE(jsrtemp->sbr_vinfo[i],vinfo[i]);
1269                                   }
1270
1271                               /* continue after the JSR call */
1272                               superblockend = false;
1273                           }
1274                           else {
1275                               /* We cannot proceed until the subroutine has been typechecked. */
1276                               /* XXX actually we would not have to check this block again */
1277                               bptr->flags = BBTYPECHECK_REACHED;
1278                               repeat = true;
1279                               superblockend = true;
1280                           }
1281                           /* XXX may throw? I don't think. */
1282                           break;
1283                           
1284                       case ICMD_RET:
1285                           /* check returnAddress variable */
1286                           CHECK_ONEWORD(iptr->op1,TYPE_ADR);
1287                           
1288                           if (!TYPEINFO_IS_PRIMITIVE(vinfo[iptr->op1]))
1289                               panic("illegal instruction: RET using non-returnAddress variable");
1290
1291                           /* check if we are inside a subroutine */
1292                           if (!subroutine)
1293                               panic("RET outside of subroutine");
1294
1295                           /* determine which variables are touched by this subroutine */
1296                           /* and their types */
1297                           if (subroutine->sbr_touched) {
1298                               for (i=0; i<numlocals; ++i)
1299                                   subroutine->sbr_touched[i] |= touched[i];
1300                               ttype = subroutine->sbr_vtype;
1301                               tinfo = subroutine->sbr_vinfo;
1302                               TYPECHECK_MERGEVARS;
1303                           }
1304                           else {
1305                               subroutine->sbr_touched = DMNEW(u1,numlocals);
1306                               memcpy(subroutine->sbr_touched,touched,sizeof(u1)*numlocals);
1307                               subroutine->sbr_vtype = DMNEW(u1,numlocals);
1308                               memcpy(subroutine->sbr_vtype,vtype,sizeof(u1)*numlocals);
1309                               subroutine->sbr_vinfo = DMNEW(typeinfo,numlocals);
1310                               for (i=0; i<numlocals; ++i)
1311                                   if (vtype[i] == TYPE_ADR)
1312                                       TYPEINFO_CLONE(vinfo[i],subroutine->sbr_vinfo[i]);
1313                           }
1314                           /* XXX check if subroutine changed types? */
1315
1316                           LOGSTR("subroutine touches:");
1317                           DOLOG(typeinfo_print_locals(get_logfile(),subroutine->sbr_vtype,subroutine->sbr_vinfo,
1318                                                       subroutine->sbr_touched,numlocals));
1319                           LOGNL; LOGFLUSH;
1320
1321                           /* reach blocks after JSR statements */
1322                           for (i=0; i<block_count; ++i) {
1323                               tbptr = block + i;
1324                               LOG1("block L%03d",tbptr->debug_nr);
1325                               if (tbptr->iinstr[tbptr->icount - 1].opc != ICMD_JSR)
1326                                   continue;
1327                               LOG("ends with JSR");
1328                               if ((basicblock*) tbptr->iinstr[tbptr->icount - 1].target != subroutine->target)
1329                                   continue;
1330                               tbptr++;
1331
1332                               LOG1("RET reaches block %04d",tbptr-block);
1333
1334                               /*TYPECHECK_REACH(REACH_RET);*/
1335                           }
1336                           
1337                           superblockend = true;
1338                           break;
1339                                                           
1340                           /****************************************/
1341                           /* INVOKATIONS                          */
1342
1343                       case ICMD_INVOKEVIRTUAL:
1344                       case ICMD_INVOKESPECIAL:
1345                       case ICMD_INVOKESTATIC:
1346                       case ICMD_INVOKEINTERFACE:
1347                           {
1348                                                           /* XXX check if this opcode may invoke this method */
1349                               /* XXX check access rights */
1350                               
1351                               methodinfo *mi = (methodinfo*) iptr->val.a;
1352                               bool callinginit = (opcode == ICMD_INVOKESPECIAL && mi->name == name_init);
1353                               instruction *ins;
1354                               classinfo *initclass;
1355
1356                               /* XXX for INVOKESPECIAL: check if the invokation is done at all */
1357
1358                               /* fetch parameter types and return type */
1359                               /* XXX might use dst->typeinfo directly if non void */
1360                               i = 0;
1361                               if (opcode != ICMD_INVOKESTATIC) {
1362                                   ptype[0] = TYPE_ADR;
1363                                   TYPEINFO_INIT_CLASSINFO(pinfo[0],mi->class);
1364                                   i++;
1365                               }
1366                               typeinfo_init_from_method_args(mi->descriptor,ptype+i,pinfo+i,
1367                                                              MAXPARAMS-i,false,
1368                                                              &rtype,&rinfo);
1369
1370                               /* check parameter types */
1371                               srcstack = curstack;
1372                               i = mi->paramcount; /* number of parameters including 'this'*/
1373                               while (--i >= 0) {
1374                                   LOG1("param %d",i);
1375                                   if (srcstack->type != ptype[i])
1376                                       panic("Parameter type mismatch in method invocation");
1377                                   if (srcstack->type == TYPE_ADR) {
1378                                       LOGINFO(&(srcstack->typeinfo));
1379                                       LOGINFO(pinfo + i);
1380                                       if (i==0 && callinginit)
1381                                       {
1382                                           /* first argument to <init> method */
1383                                           if (!TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo))
1384                                               panic("Calling <init> on initialized object");
1385                                           
1386                                           /* get the address of the NEW instruction */
1387                                           LOGINFO(&(srcstack->typeinfo));
1388                                           ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(srcstack->typeinfo);
1389                                           initclass = (ins) ? (classinfo*)ins[-1].val.a : method->class;
1390                                           LOGSTR("class: "); LOGSTRu(initclass->name); LOGNL;
1391
1392                                           /* XXX check type */
1393                                       }
1394                                       else {
1395                                           if (!typeinfo_is_assignable(&(srcstack->typeinfo),pinfo+i))
1396                                               panic("Parameter reference type mismatch in method invocation");
1397                                       }
1398                                   }
1399                                   LOG("ok");
1400
1401                                   srcstack = srcstack->prev;
1402                               }
1403
1404                                                           LOG("checking return type");
1405                               if (rtype != TYPE_VOID) {
1406                                   if (rtype != dst->type)
1407                                       panic("Return type mismatch in method invocation");
1408                                   TYPEINFO_COPY(rinfo,dst->typeinfo);
1409                               }
1410
1411                               if (callinginit) {
1412                                                                   LOG("replacing uninitialized object");
1413                                   /* replace uninitialized object type on stack */
1414                                   srcstack = dst;
1415                                   while (srcstack) {
1416                                       if (srcstack->type == TYPE_ADR
1417                                           && TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo)
1418                                           && TYPEINFO_NEWOBJECT_INSTRUCTION(srcstack->typeinfo) == ins)
1419                                       {
1420                                           LOG("replacing uninitialized type on stack");
1421                                           TYPEINFO_INIT_CLASSINFO(srcstack->typeinfo,initclass);
1422                                       }
1423                                       srcstack = srcstack->prev;
1424                                   }
1425                                   /* replace uninitialized object type in locals */
1426                                   for (i=0; i<numlocals; ++i) {
1427                                       if (vtype[i] == TYPE_ADR
1428                                           && TYPEINFO_IS_NEWOBJECT(vinfo[i])
1429                                           && TYPEINFO_NEWOBJECT_INSTRUCTION(vinfo[i]) == ins)
1430                                       {
1431                                           LOG1("replacing uninitialized type in local %d",i);
1432                                           TYPEINFO_INIT_CLASSINFO(vinfo[i],initclass);
1433                                       }
1434                                   }
1435
1436                                   /* initializing the 'this' reference? */
1437                                   if (initmethod && !ins) {
1438                                       /* set our marker variable to type int */
1439                                       LOG("setting <init> marker");
1440                                                                           vtype[numlocals-1] = TYPE_INT;
1441                                   }
1442                               }
1443                           }
1444                           maythrow = true;
1445                           break;
1446                           
1447                       case ICMD_MULTIANEWARRAY:
1448                           /* check the array lengths on the stack */
1449                           i = iptr[0].op1;
1450                           if (i<1) panic("MULTIANEWARRAY with dimensions < 1");
1451                           srcstack = curstack;
1452                           while (i--) {
1453                               if (!srcstack)
1454                                   panic("MULTIANEWARRAY missing array length");
1455                               if (srcstack->type != TYPE_INT)
1456                                   panic("MULTIANEWARRAY using non-int as array length");
1457                               srcstack = srcstack->prev;
1458                           }
1459                           
1460                           /* set the array type of the result */
1461                           TYPEINFO_INIT_CLASSINFO(dst->typeinfo,((vftbl *)iptr[0].val.a)->class);
1462                           maythrow = true;
1463                           break;
1464                           
1465                       case ICMD_BUILTIN3:
1466                           if (ISBUILTIN(asm_builtin_aastore)) {
1467                                                           TYPECHECK_ADR(curstack);
1468                                                           TYPECHECK_INT(curstack->prev);
1469                                                           TYPECHECK_ADR(curstack->prev->prev);
1470                               if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(curstack->prev->prev->typeinfo))
1471                                   panic("illegal instruction: AASTORE to non-reference array");
1472
1473                               /* XXX optimize */
1474                               /*
1475                                 typeinfo_init_component(&curstack->prev->prev->typeinfo,&tempinfo);
1476                                 if (!typeinfo_is_assignable(&curstack->typeinfo,&tempinfo))
1477                                 panic("illegal instruction: AASTORE to incompatible type");
1478                               */
1479                           }
1480                           /* XXX check for missed builtins in debug mode? */
1481                           maythrow = true; /* XXX better safe than sorry */
1482                           break;
1483                           
1484                       case ICMD_BUILTIN2:
1485                           if (
1486 #if defined(__I386__)
1487                               ISBUILTIN(asm_builtin_newarray)
1488 #else
1489                               ISBUILTIN(builtin_newarray)
1490 #endif
1491                               )
1492                           {
1493                                                           TYPECHECK_INT(curstack->prev);
1494                               if (iptr[-1].opc != ICMD_ACONST)
1495                                   panic("illegal instruction: builtin_newarray without classinfo");
1496                               TYPEINFO_INIT_CLASSINFO(dst->typeinfo,((vftbl *)iptr[-1].val.a)->class);
1497                           }
1498                           else if (ISBUILTIN(asm_builtin_checkarraycast)) {
1499                                                           TYPECHECK_ADR(curstack->prev);
1500                               if (iptr[-1].opc != ICMD_ACONST)
1501                                   panic("illegal instruction: asm_builtin_checkarraycast without classinfo");
1502                               TYPEINFO_INIT_CLASSINFO(dst->typeinfo,((vftbl *)iptr[-1].val.a)->class);
1503                           }
1504                           /* XXX check for missed builtins in debug mode? */
1505                           maythrow = true; /* XXX better safe than sorry */
1506                           break;
1507                           
1508                       case ICMD_BUILTIN1:
1509                           if (ISBUILTIN(builtin_new)) {
1510                               if (iptr[-1].opc != ICMD_ACONST)
1511                                   panic("illegal instruction: builtin_new without classinfo");
1512                               TYPEINFO_INIT_NEWOBJECT(dst->typeinfo,iptr);
1513                           }
1514                                                   /* XXX unify the following cases */
1515                           else if (ISBUILTIN(builtin_newarray_boolean)) {
1516                                                           TYPECHECK_INT(curstack);
1517                               TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BOOLEAN);
1518                           }
1519                           else if (ISBUILTIN(builtin_newarray_char)) {
1520                                                           TYPECHECK_INT(curstack);
1521                               TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_CHAR);
1522                           }
1523                           else if (ISBUILTIN(builtin_newarray_float)) {
1524                                                           TYPECHECK_INT(curstack);
1525                               TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_FLOAT);
1526                           }
1527                           else if (ISBUILTIN(builtin_newarray_double)) {
1528                                                           TYPECHECK_INT(curstack);
1529                               TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_DOUBLE);
1530                           }
1531                           else if (ISBUILTIN(builtin_newarray_byte)) {
1532                                                           TYPECHECK_INT(curstack);
1533                               TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BYTE);
1534                           }
1535                           else if (ISBUILTIN(builtin_newarray_short)) {
1536                                                           TYPECHECK_INT(curstack);
1537                               TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_SHORT);
1538                           }
1539                           else if (ISBUILTIN(builtin_newarray_int)) {
1540                                                           TYPECHECK_INT(curstack);
1541                               TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_INT);
1542                           }
1543                           else if (ISBUILTIN(builtin_newarray_long)) {
1544                                                           TYPECHECK_INT(curstack);
1545                               TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_LONG);
1546                           }
1547                           /* XXX check for missed builtins in debug mode? */
1548                           maythrow = true; /* XXX better safe than sorry */
1549                           break;
1550                                                      
1551                           /****************************************/
1552                           /* PRIMITIVE VARIABLE ACCESS            */
1553
1554                       case ICMD_ILOAD: CHECK_ONEWORD(iptr->op1,TYPE_INT); break;
1555                       case ICMD_FLOAD: CHECK_ONEWORD(iptr->op1,TYPE_FLOAT); break;
1556                       case ICMD_IINC:  CHECK_ONEWORD(iptr->op1,TYPE_INT); break;
1557                       case ICMD_LLOAD: CHECK_TWOWORD(iptr->op1,TYPE_LONG); break;
1558                       case ICMD_DLOAD: CHECK_TWOWORD(iptr->op1,TYPE_DOUBLE); break;
1559                           
1560                       case ICMD_FSTORE: STORE_ONEWORD(iptr->op1,TYPE_FLOAT); break;
1561                       case ICMD_ISTORE: STORE_ONEWORD(iptr->op1,TYPE_INT); break;
1562                       case ICMD_LSTORE: STORE_TWOWORD(iptr->op1,TYPE_LONG); break;
1563                       case ICMD_DSTORE: STORE_TWOWORD(iptr->op1,TYPE_DOUBLE); break;
1564                           
1565                           /****************************************/
1566                           /* INSTRUCTIONS WHICH SHOULD HAVE BEEN  */
1567                           /* REPLACED BY BUILTIN CALLS            */
1568
1569                       case ICMD_NEW:
1570                       case ICMD_NEWARRAY:
1571                       case ICMD_ANEWARRAY:
1572                       case ICMD_MONITORENTER:
1573                       case ICMD_MONITOREXIT:
1574                       case ICMD_AASTORE:
1575                           /* XXX only check this in debug mode? */
1576                           LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
1577                                                   LOG("Should have been converted to builtin function call.");
1578                           panic("Internal error: unexpected instruction encountered");
1579                           break;
1580                                                      
1581                           /****************************************/
1582                           /* UNCHECKED OPERATIONS                 */
1583
1584                           /* These ops have no input or output to be checked */
1585                           /* (apart from the checks done in analyse_stack).  */
1586                                                 /* XXX only add cases for them in debug mode? */
1587
1588                       case ICMD_NOP:
1589                       case ICMD_POP:
1590                       case ICMD_POP2:
1591                       case ICMD_READONLY_ARG: /* XXX ? */
1592                       case ICMD_CLEAR_ARGREN: /* XXX ? */
1593                           break;
1594
1595                       case ICMD_CHECKASIZE:
1596                       case ICMD_NULLCHECKPOP:
1597                           maythrow = true;
1598                           break;
1599
1600                           /****************************************/
1601                           /* ARITHMETIC AND CONVERSION            */
1602                           /* (These instructions are typechecked in analyse_stack.) */
1603
1604                           /* The following instructions may throw a runtime exception: */
1605                           
1606                       case ICMD_IDIV:
1607                       case ICMD_IREM:
1608                       case ICMD_LDIV:
1609                       case ICMD_LREM:
1610                           
1611                           maythrow = true;
1612                           break;
1613                           
1614                           /* The following instructions never throw a runtime exception: */
1615                           /* XXX only add cases for them in debug mode? */
1616                           
1617                       case ICMD_ICONST:
1618                       case ICMD_LCONST:
1619                       case ICMD_FCONST:
1620                       case ICMD_DCONST:
1621
1622                       case ICMD_IFEQ_ICONST:
1623                       case ICMD_IFNE_ICONST:
1624                       case ICMD_IFLT_ICONST:
1625                       case ICMD_IFGE_ICONST:
1626                       case ICMD_IFGT_ICONST:
1627                       case ICMD_IFLE_ICONST:
1628                       case ICMD_ELSE_ICONST:
1629
1630                       case ICMD_IADD:
1631                       case ICMD_ISUB:
1632                       case ICMD_IMUL:
1633                       case ICMD_INEG:
1634                       case ICMD_IAND:
1635                       case ICMD_IOR:
1636                       case ICMD_IXOR:
1637                       case ICMD_ISHL:
1638                       case ICMD_ISHR:
1639                       case ICMD_IUSHR:
1640                       case ICMD_LADD:
1641                       case ICMD_LSUB:
1642                       case ICMD_LMUL:
1643                       case ICMD_LNEG:
1644                       case ICMD_LAND:
1645                       case ICMD_LOR:
1646                       case ICMD_LXOR:
1647                       case ICMD_LSHL:
1648                       case ICMD_LSHR:
1649                       case ICMD_LUSHR:
1650                       case ICMD_IREM0X10001:
1651                       case ICMD_LREM0X10001:
1652                       case ICMD_IDIVPOW2:
1653                       case ICMD_LDIVPOW2:
1654                       case ICMD_IADDCONST:
1655                       case ICMD_ISUBCONST:
1656                       case ICMD_IMULCONST:
1657                       case ICMD_IANDCONST:
1658                       case ICMD_IORCONST:
1659                       case ICMD_IXORCONST:
1660                       case ICMD_ISHLCONST:
1661                       case ICMD_ISHRCONST:
1662                       case ICMD_IUSHRCONST:
1663                       case ICMD_IREMPOW2:
1664                       case ICMD_LADDCONST:
1665                       case ICMD_LSUBCONST:
1666                       case ICMD_LMULCONST:
1667                       case ICMD_LANDCONST:
1668                       case ICMD_LORCONST:
1669                       case ICMD_LXORCONST:
1670                       case ICMD_LSHLCONST:
1671                       case ICMD_LSHRCONST:
1672                       case ICMD_LUSHRCONST:
1673                       case ICMD_LREMPOW2:
1674                           
1675                       case ICMD_I2L:
1676                       case ICMD_I2F:
1677                       case ICMD_I2D:
1678                       case ICMD_L2I:
1679                       case ICMD_L2F:
1680                       case ICMD_L2D:
1681                       case ICMD_F2I:
1682                       case ICMD_F2L:
1683                       case ICMD_F2D:
1684                       case ICMD_D2I:
1685                       case ICMD_D2L:
1686                       case ICMD_D2F:
1687                       case ICMD_INT2BYTE:
1688                       case ICMD_INT2CHAR:
1689                       case ICMD_INT2SHORT:
1690
1691                       case ICMD_LCMP:
1692                       case ICMD_LCMPCONST:
1693                       case ICMD_FCMPL:
1694                       case ICMD_FCMPG:
1695                       case ICMD_DCMPL:
1696                       case ICMD_DCMPG:
1697                           
1698                       case ICMD_FADD:
1699                       case ICMD_DADD:
1700                       case ICMD_FSUB:
1701                       case ICMD_DSUB:
1702                       case ICMD_FMUL:
1703                       case ICMD_DMUL:
1704                       case ICMD_FDIV:
1705                       case ICMD_DDIV:
1706                       case ICMD_FREM:
1707                       case ICMD_DREM:
1708                       case ICMD_FNEG:
1709                       case ICMD_DNEG:
1710
1711                           break;
1712                           
1713                           /****************************************/
1714
1715                       default:
1716                           LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
1717                           panic("Missing ICMD code during typecheck");
1718                     }
1719
1720                     /* the output of this instruction becomes the current stack */
1721                     curstack = dst;
1722                     
1723                     /* reach exception handlers for this instruction */
1724                     if (maythrow) {
1725                         LOG("reaching exception handlers");
1726                         i = 0;
1727                         while (handlers[i]) {
1728                             tbptr = handlers[i]->handler;
1729                             TYPECHECK_REACH(REACH_THROW); /* XXX jsr chain? */
1730                             i++;
1731                         }
1732                     }
1733
1734                     /*
1735                       DOLOG(typeinfo_print_block(get_logfile(),curstack,numlocals,vtype,vinfo,(jsrchain) ? touched : NULL));
1736                       LOGNL; LOGFLUSH;
1737                     */
1738                     
1739                     iptr++;
1740                 } /* while instructions */
1741
1742                 LOG("instructions done");
1743                 LOGSTR("RESULT=> ");
1744                 DOLOG(typeinfo_print_block(get_logfile(),curstack,numlocals,vtype,vinfo,(jsrchain) ? touched : NULL));
1745                 LOGNL; LOGFLUSH;
1746                 
1747                 /* propagate stack and variables to the following block */
1748                 if (!superblockend) {
1749                     LOG("reaching following block");
1750                     tbptr = bptr + 1;
1751                     while (tbptr->flags == BBDELETED) {
1752                         tbptr++;
1753 #ifdef TYPECHECK_DEBUG
1754                         if ((tbptr-block) >= block_count)
1755                             panic("Control flow falls off the last block");
1756 #endif
1757                     }
1758                     TYPECHECK_REACH(REACH_STD);
1759                 }
1760                 
1761             } /* if block has to be checked */
1762             bptr++;
1763         } /* while blocks */
1764         
1765         LOGIF(repeat,"repeat=true");
1766     } while (repeat);
1767
1768 #ifdef TYPECHECK_STATISTICS
1769         dolog("Typechecker did %4d iterations",count_iterations);
1770 #endif
1771
1772 #ifdef TYPECHECK_DEBUG
1773         for (i=0; i<block_count; ++i) {
1774                 if (block[i].flags != BBDELETED
1775                         && block[i].flags != BBUNDEF
1776                         && block[i].flags != BBFINISHED)
1777                 {
1778                         LOG2("block L%03d has invalid flags after typecheck: %d",
1779                                  block[i].debug_nr,block[i].flags);
1780                         panic("Invalid block flags after typecheck");
1781                 }
1782         }
1783 #endif
1784
1785     LOGimp("exiting typecheck");
1786 }
1787
1788 #undef COPYTYPE
1789
1790 #endif /* CACAO_TYPECHECK */
1791
1792 /*
1793  * These are local overrides for various environment variables in Emacs.
1794  * Please do not remove this and leave it at the end of the file, where
1795  * Emacs will automagically detect them.
1796  * ---------------------------------------------------------------------
1797  * Local variables:
1798  * mode: c
1799  * indent-tabs-mode: t
1800  * c-basic-offset: 4
1801  * tab-width: 4
1802  * End:
1803  */