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