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