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