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