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