implemented subroutine verification (Coglio's method) + several verifier fixes
[cacao.git] / src / vm / jit / verify / typecheck.c
1 /* jit/typecheck.c - typechecking (part of bytecode verification)
2
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4    R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5    M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6    P. Tomsich, J. Wenninger
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Edwin Steiner
28
29    $Id: typecheck.c 868 2004-01-10 20:12:10Z 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 static
151 void
152 typestack_print(FILE *file,stackptr stack)
153 {
154     while (stack) {
155         typeinfo_print_stacktype(file,stack->type,&stack->typeinfo);
156         stack = stack->prev;
157         if (stack) fprintf(file," ");
158     }
159 }
160
161 static
162 void
163 typestate_print(FILE *file,stackptr instack,typevector *localset,int size)
164 {
165     fprintf(file,"Stack: ");
166     typestack_print(file,instack);
167     fprintf(file," Locals:");
168     typevectorset_print(file,localset,size);
169 }
170
171
172 #if 0
173 static
174 void
175 typeinfo_print_blocks(FILE *file,int vnum,u1 *vtype,typeinfo *vinfo)
176 {
177     int bi;
178     /*    int j;*/
179
180     for (bi=0; bi<block_count; ++bi) {
181         fprintf(file,"%04d: (%3d) ",bi,block[bi].flags);
182         typeinfo_print_block(file,block[bi].instack,
183                              vnum,vtype+vnum*bi,vinfo+vnum*bi,NULL);
184         fprintf(file,"\n");
185
186 /*         for (j=0; j<block[bi].icount; ++j) { */
187 /*             fprintf(file,"\t%s\n",icmd_names[block[bi].iinstr[j].opc]); */
188 /*         } */
189
190         show_icmd_block(block+bi);
191     }
192 }
193 #endif
194
195 #endif
196
197 /****************************************************************************/
198 /* TYPESTACK FUNCTIONS                                                      */
199 /****************************************************************************/
200
201 #define TYPESTACK_IS_RETURNADDRESS(sptr) \
202             TYPE_IS_RETURNADDRESS((sptr)->type,(sptr)->typeinfo)
203
204 #define TYPESTACK_IS_REFERENCE(sptr) \
205             TYPE_IS_REFERENCE((sptr)->type,(sptr)->typeinfo)
206
207 #define TYPESTACK_RETURNADDRESSSET(sptr) \
208             ((typeinfo_retaddr_set*)TYPEINFO_RETURNADDRESS((sptr)->typeinfo))
209
210 #define RETURNADDRESSSET_SEEK(set,pos) \
211             do {int i; for (i=pos;i--;) set=set->alt;} while(0)
212
213 static void
214 typestack_copy(stackptr dst,stackptr y,typevector *selected)
215 {
216         typevector *sel;
217         typeinfo_retaddr_set *sety;
218         typeinfo_retaddr_set *new;
219         typeinfo_retaddr_set **next;
220         int k;
221         
222         for (;dst; dst=dst->prev, y=y->prev) {
223                 if (!y) panic("Stack depth mismatch");
224                 if (dst->type != y->type)
225                         panic("Stack type mismatch");
226                 LOG3("copy %p -> %p (type %d)",y,dst,dst->type);
227                 if (dst->type == TYPE_ADDRESS) {
228                         if (TYPEINFO_IS_PRIMITIVE(y->typeinfo)) {
229                                 /* We copy the returnAddresses from the selected
230                                  * states only. */
231
232                                 LOG("copying returnAddress");
233                                 sety = TYPESTACK_RETURNADDRESSSET(y);
234                                 next = &new;
235                                 for (k=0,sel=selected; sel; sel=sel->alt) {
236                                         LOG1("selected k=%d",sel->k);
237                                         while (k<sel->k) {
238                                                 sety = sety->alt;
239                                                 k++;
240                                         }
241                                         *next = DNEW(typeinfo_retaddr_set);
242                                         (*next)->addr = sety->addr;
243                                         next = &((*next)->alt);
244                                 }
245                                 *next = NULL;
246                                 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,new);
247                         }
248                         else {
249                                 TYPEINFO_CLONE(y->typeinfo,dst->typeinfo);
250                         }
251                 }
252         }
253         if (y) panic("Stack depth mismatch");
254 }
255
256 static void
257 typestack_put_retaddr(stackptr dst,void *retaddr,typevector *loc)
258 {
259 #ifdef TYPECHECK_DEBUG
260         if (dst->type != TYPE_ADDRESS)
261                 panic("Internal error: Storing returnAddress in non-address slot");
262 #endif
263
264         
265         TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,NULL);
266         for (;loc; loc=loc->alt) {
267                 typeinfo_retaddr_set *set = DNEW(typeinfo_retaddr_set);
268                 set->addr = retaddr;
269                 set->alt = TYPESTACK_RETURNADDRESSSET(dst);
270                 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,set);
271         }
272 }
273
274 static bool
275 typestack_canmerge(stackptr a,stackptr b)
276 {
277         for (; a; a = a->prev, b = b->prev) {
278                 if (!b) return false;
279                 if (a->type != b->type) return false;
280                 if (a->type == TYPE_ADDRESS) {
281                         if (((TYPEINFO_IS_PRIMITIVE(a->typeinfo)) ? 1 : 0)
282                                 ^
283                                 ((TYPEINFO_IS_PRIMITIVE(b->typeinfo)) ? 1 : 0))
284                                 return false;
285                 }
286         }
287         if (b) return false;
288         return true;
289 }
290
291 static void
292 typestack_collapse(stackptr dst)
293 {
294         for (; dst; dst = dst->prev) {
295                 if (TYPESTACK_IS_RETURNADDRESS(dst))
296                         TYPESTACK_RETURNADDRESSSET(dst)->alt = NULL;
297         }
298 }
299
300 /* 'dst' and 'y' are assumed to have passed typestack_canmerge! */
301 static bool
302 typestack_merge(stackptr dst,stackptr y)
303 {
304         bool changed = false;
305         for (; dst; dst = dst->prev, y=y->prev) {
306                 if (TYPESTACK_IS_REFERENCE(dst))
307                         changed |= typeinfo_merge(&(dst->typeinfo),&(y->typeinfo));
308         }
309         return changed;
310 }
311
312 static void
313 typestack_add(stackptr dst,stackptr y,int ky)
314 {
315         typeinfo_retaddr_set *setd;
316         typeinfo_retaddr_set *sety;
317         
318         for (; dst; dst = dst->prev, y=y->prev) {
319                 if (TYPESTACK_IS_RETURNADDRESS(dst)) {
320                         setd = TYPESTACK_RETURNADDRESSSET(dst);
321                         sety = TYPESTACK_RETURNADDRESSSET(y);
322                         RETURNADDRESSSET_SEEK(sety,ky);
323                         while (setd->alt)
324                                 setd=setd->alt;
325                         setd->alt = DNEW(typeinfo_retaddr_set);
326                         setd->alt->addr = sety->addr;
327                         setd->alt->alt = NULL;
328                 }
329         }
330 }
331
332 /* 'a' and 'b' are assumed to have passed typestack_canmerge! */
333 static bool
334 typestack_separable_with(stackptr a,stackptr b,int kb)
335 {
336         typeinfo_retaddr_set *seta;
337         typeinfo_retaddr_set *setb;
338         
339         for (; a; a = a->prev, b = b->prev) {
340 #ifdef TYPECHECK_DEBUG
341                 if (!b) panic("Internal error: typestack_separable_from: different depth");
342 #endif
343                 if (TYPESTACK_IS_RETURNADDRESS(a)) {
344 #ifdef TYPECHECK_DEBUG
345                         if (!TYPESTACK_IS_RETURNADDRESS(b))
346                                 panic("Internal error: typestack_separable_from: unmergable stacks");
347 #endif
348                         seta = TYPESTACK_RETURNADDRESSSET(a);
349                         setb = TYPESTACK_RETURNADDRESSSET(b);
350                         RETURNADDRESSSET_SEEK(setb,kb);
351
352                         for (;seta;seta=seta->alt)
353                                 if (seta->addr != setb->addr) return true;
354                 }
355         }
356 #ifdef TYPECHECK_DEBUG
357         if (b) panic("Internal error: typestack_separable_from: different depth");
358 #endif
359         return false;
360 }
361
362 /* 'a' and 'b' are assumed to have passed typestack_canmerge! */
363 static bool
364 typestack_separable_from(stackptr a,int ka,stackptr b,int kb)
365 {
366         typeinfo_retaddr_set *seta;
367         typeinfo_retaddr_set *setb;
368         int i;
369
370         for (; a; a = a->prev, b = b->prev) {
371 #ifdef TYPECHECK_DEBUG
372                 if (!b) panic("Internal error: typestack_separable_from: different depth");
373 #endif
374                 if (TYPESTACK_IS_RETURNADDRESS(a)) {
375 #ifdef TYPECHECK_DEBUG
376                         if (!TYPESTACK_IS_RETURNADDRESS(b))
377                                 panic("Internal error: typestack_separable_from: unmergable stacks");
378 #endif
379                         seta = TYPESTACK_RETURNADDRESSSET(a);
380                         setb = TYPESTACK_RETURNADDRESSSET(b);
381                         RETURNADDRESSSET_SEEK(seta,ka);
382                         RETURNADDRESSSET_SEEK(setb,kb);
383
384                         if (seta->addr != setb->addr) return true;
385                 }
386         }
387 #ifdef TYPECHECK_DEBUG
388         if (b) panic("Internal error: typestack_separable_from: different depth");
389 #endif
390         return false;
391 }
392
393 /****************************************************************************/
394 /* TYPESTATE FUNCTIONS                                                      */
395 /****************************************************************************/
396
397 static bool
398 typestate_merge(stackptr deststack,typevector *destloc,
399                                 stackptr ystack,typevector *yloc,
400                                 /*                              int retindex,void *retaddr, */
401                                 int locsize)
402 {
403         typevector *dvec,*yvec;
404         int kd,ky;
405         bool changed = false;
406         
407 #ifdef TYPECHECK_DEBUG
408         /* Do some sanity checks */
409         /*
410           if (retindex < -1 || retindex >= locsize || (retindex >= 0 && !retaddr))
411           panic("Internal error: typestate_merge: invalid arguments");
412         */
413 #endif
414
415         LOG("merge:");
416         LOGSTR("dstack: "); DOLOG(typestack_print(get_logfile(),deststack)); LOGNL;
417         LOGSTR("ystack: "); DOLOG(typestack_print(get_logfile(),ystack)); LOGNL;
418         LOGSTR("dloc  : "); DOLOG(typevectorset_print(get_logfile(),destloc,locsize)); LOGNL;
419         LOGSTR("yloc  : "); DOLOG(typevectorset_print(get_logfile(),yloc,locsize)); LOGNL;
420
421         /* Check if the stack types of deststack and ystack match */
422
423         /* XXX move this check into typestack_merge? */
424         if (!typestack_canmerge(deststack,ystack))
425                 panic("Stack depth or stack type mismatch");
426
427         /* The stack is always merged. If there are returnAddresses on
428          * the stack they are ignored in this step. */
429
430         changed |= typestack_merge(deststack,ystack);
431
432         for (yvec=yloc; yvec; yvec=yvec->alt) {
433                 ky = yvec->k;
434
435                 /* If retindex >= 0 we select only those states (ystack,yvec)
436                  * with returnAddress retaddr in variable no. retindex. */
437
438                 /*
439                   if (retindex >= 0) {
440                   if (!TYPEDESC_IS_RETURNADDRESS(yvec->td[retindex]))
441                   panic("Illegal instruction: RET on non-returnAddress");
442                   if (TYPEINFO_RETURNADDRESS(yvec->td[retindex].info)
443                   != retaddr)
444                   continue;
445                   }
446                 */
447
448                 /* Check if the typestates (deststack,destloc) will be
449                  * separable when (ystack,yvec) is added. */
450
451                 if (!typestack_separable_with(deststack,ystack,ky)
452                         && !typevectorset_separable_with(destloc,yvec,locsize))
453                 {
454                         /* No, the resulting set won't be separable, thus we
455                          * may merge all states in (deststack,destloc) and
456                          * (ystack,yvec). */
457
458                         typestack_collapse(deststack);
459                         typevectorset_collapse(destloc,locsize);
460                         typevector_merge(destloc,yvec,locsize);
461                 }
462                 else {
463                         /* Yes, the resulting set will be separable. Thus we check
464                          * if we may merge (ystack,yvec) with a single state in
465                          * (deststack,destloc). */
466                 
467                         for (dvec=destloc,kd=0; dvec; dvec=dvec->alt, kd++) {
468                                 if (!typestack_separable_from(ystack,ky,deststack,kd)
469                                         && !typevector_separable_from(yvec,dvec,locsize))
470                                 {
471                                         /* The typestate (ystack,yvec) is not separable from
472                                          * (deststack,dvec) by any returnAddress. Thus we may
473                                          * merge the states. */
474                                         
475                                         changed |= typevector_merge(dvec,yvec,locsize);
476                                         
477                                         goto merged;
478                                 }
479                         }
480
481                         /* The typestate (ystack,yvec) is separable from all typestates
482                          * (deststack,destloc). Thus we must add this state to the
483                          * result set. */
484
485                         typestack_add(deststack,ystack,ky);
486                         typevectorset_add(destloc,yvec,locsize);
487                         changed = true;
488                 }
489                    
490         merged:
491                 
492         }
493         
494         LOG("result:");
495         LOGSTR("dstack: "); DOLOG(typestack_print(get_logfile(),deststack)); LOGNL;
496         LOGSTR("dloc  : "); DOLOG(typevectorset_print(get_logfile(),destloc,locsize)); LOGNL;
497         
498         return changed;
499 }
500
501 /* Globals used:
502  *     block
503  */
504 static bool
505 typestate_reach(void *localbuf,
506                                 basicblock *current,
507                                 basicblock *destblock,
508                                 stackptr ystack,typevector *yloc,
509                                 int locsize)
510 {
511         typevector *yvec;
512         typevector *destloc;
513         int destidx;
514         bool repeat = false;
515         bool changed = false;
516         
517         destidx = destblock - block;
518         destloc = MGET_TYPEVECTOR(localbuf,destidx,locsize);
519
520         if (destblock->flags == BBTYPECHECK_UNDEF) {
521                 /* The destblock has never been reached before */
522
523                 LOG1("block (index %04d) reached first time",destidx);
524                 
525                 typestack_copy(destblock->instack,ystack,yloc);
526                 COPY_TYPEVECTORSET(yloc,destloc,locsize);
527                 changed = true;
528         }
529         else {
530                 /* The destblock has already been reached before */
531                 
532                 LOG1("block (index %04d) reached before",destidx);
533                 
534                 changed = typestate_merge(destblock->instack,destloc,
535                                                                   ystack,yloc,locsize);
536         }
537
538         if (changed) {
539                 LOG("changed!");
540                 destblock->flags = BBTYPECHECK_REACHED;
541                 if (destblock <= current) {repeat = true; LOG("REPEAT!");}
542         }
543         return repeat;
544 }
545
546 /* Globals used:
547  *     see typestate_reach
548  */
549 static bool
550 typestate_ret(void *localbuf,
551                           basicblock *current,
552                           stackptr ystack,typevector *yloc,
553                           int retindex,int locsize)
554 {
555         typevector *yvec;
556         typevector *selected;
557         basicblock *destblock;
558         bool repeat = false;
559
560         for (yvec=yloc; yvec; ) {
561                 if (!TYPEDESC_IS_RETURNADDRESS(yvec->td[retindex]))
562                         panic("Illegal instruction: RET on non-returnAddress");
563
564                 destblock = (basicblock*) TYPEINFO_RETURNADDRESS(yvec->td[retindex].info);
565
566                 selected = typevectorset_select(&yvec,retindex,destblock);
567                 
568                 repeat |= typestate_reach(localbuf,current,destblock,
569                                                                   ystack,selected,locsize);
570         }
571         return repeat;
572 }
573
574 static bool
575 typestate_jsr(void *localbuf,
576                           basicblock *current,basicblock *destblock,
577                           stackptr ystack,typevector *yloc,
578                           int locsize)
579 {
580         typestack_put_retaddr(ystack,current+1,yloc);
581         return typestate_reach(localbuf,current,destblock,ystack,yloc,locsize);
582 }
583
584 /****************************************************************************/
585 /* HELPER FUNCTIONS                                                         */
586 /****************************************************************************/
587
588 /* If a field is checked, definingclass == implementingclass */
589 static bool
590 is_accessible(int flags,classinfo *definingclass,classinfo *implementingclass,
591                           typeinfo *instance)
592 {
593         /* check access rights */
594         if (class != definingclass) {
595                 switch (flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED)) {
596                   case ACC_PUBLIC:
597                           break;
598                           
599                           /* In the cases below, definingclass cannot be an interface */
600                           
601                   case 0:
602                           /* XXX check package access */
603                           break;
604                   case ACC_PROTECTED:
605                           /* XXX check package access and superclass access */
606                           break;
607                   case ACC_PRIVATE:
608                           if (definingclass != class) {
609                                   LOG("private access");
610                                   return false;
611                           }
612                           break;
613                           /* XXX check package access */
614                   default:
615                           panic("Invalid access flags");
616                 }
617         }
618
619         if (instance) {
620                 if ((flags & ACC_STATIC) != 0) {
621                         LOG("accessing STATIC member with instance");
622                         return false;
623                 }
624                 
625                 if (implementingclass
626                         && !TYPEINFO_IS_NULLTYPE(*instance)
627                         && !TYPEINFO_IS_NEWOBJECT(*instance))
628                 {
629                         typeinfo tempinfo;
630                         
631                         if (((flags & ACC_PROTECTED) != 0)
632                                 && builtin_isanysubclass(class,implementingclass))
633                         {
634                                 /* For protected access of super class members
635                                  * the instance must be a subclass of or the same
636                                  * as the current class. */
637
638                                 /* XXX maybe we only are allowed to do this, if we
639                                  * don't have package access? */
640                                 /* implementingclass = class; */ /* XXX does not work */
641                         }
642                         
643                         /* XXX use classinfo directly? */
644                         TYPEINFO_INIT_CLASSINFO(tempinfo,implementingclass);
645                         if (!typeinfo_is_assignable(instance,&tempinfo)) {
646                                 LOG("instance not assignable");
647                                 LOGINFO(instance);
648                                 LOGINFO(&tempinfo);
649                                 return false;
650                         }
651                 }
652         }
653         else {
654                 if ((flags & ACC_STATIC) == 0) {
655                         LOG("accessing non-STATIC member without instance");
656                         return false;
657                 }
658         }
659         
660         return true;
661 }
662
663 /****************************************************************************/
664 /* STATISTICS                                                               */
665 /****************************************************************************/
666
667 #ifdef TYPECHECK_DEBUG
668 /*#define TYPECHECK_STATISTICS*/
669 #endif
670
671 #ifdef TYPECHECK_STATISTICS
672 #define TYPECHECK_COUNT(cnt)  (cnt)++
673 #else
674 #define TYPECHECK_COUNT(cnt)
675 #endif
676
677 /****************************************************************************/
678 /* INTERNAL DATA STRUCTURES                                                 */
679 /****************************************************************************/
680
681 typedef struct jsr_record jsr_record;
682
683 /*
684  * For each basic block we store the chain of JSR instructions which
685  * were used to reach the block (usually zero or one). For more
686  * details on verifying JSR and RET instructions see the Java VM
687  * Specification.
688  *
689  * CAUTION: The fields starting with sbr_ are only valid for the
690  * jsr_record of the first block of the subroutine.
691  */
692 struct jsr_record {
693     basicblock  *target;      /* target of the JSR instruction (first block of subroutine) */
694     jsr_record  *next;        /* for chaining in nested try ... finally */ /* XXX make it sbr_next? */
695     u1          *sbr_touched; /* specifies which variables the subroutine touches */
696     u1          *sbr_vtype;   /* Types of local variables after RET */
697     typeinfo    *sbr_vinfo;   /* Types of local variables after RET */
698         instruction *sbr_ret;     /* RET instruction of the subroutine */
699     u1           touched[1];  /* touched flags for local variables */
700 };
701
702 /****************************************************************************/
703 /* MACROS USED INTERNALLY IN typecheck()                                    */
704 /****************************************************************************/
705
706 #define TOUCH_VARIABLE(num)                                                                             \
707         do {if (jsrchain) touched[num] = TOUCHED_YES;} while (0)
708 #define TOUCH_TWOWORD(num)                                                                              \
709         do {TOUCH_VARIABLE(num);TOUCH_VARIABLE((num)+1);} while (0)
710
711 #define INDEX_ONEWORD(num)                                                                              \
712         do { if((num)<0 || (num)>=validlocals)                                          \
713                         panic("Invalid local variable index"); } while (0)
714 #define INDEX_TWOWORD(num)                                                                              \
715         do { if((num)<0 || ((num)+1)>=validlocals)                                      \
716                         panic("Invalid local variable index"); } while (0)
717
718 #define SET_VARIABLE(num,type)                                                                  \
719         do {vtype[num] = (type);                                                                        \
720                 if ((num)>0 && IS_2_WORD_TYPE(vtype[(num)-1])) {                \
721                         vtype[(num)-1] = TYPE_VOID;                                                     \
722                         TOUCH_VARIABLE((num)-1);                                                        \
723                 }                                                                                                               \
724                 TOUCH_VARIABLE(num);} while(0)
725
726 #define STORE_ONEWORD(num,type)                                                                 \
727         do {INDEX_ONEWORD(num);                                                                         \
728                 typevectorset_store(localset,num,type,NULL);} while(0)
729
730 #define STORE_TWOWORD(num,type)                                                                 \
731         do {INDEX_TWOWORD(num);                                                                         \
732                 typevectorset_store_twoword(localset,num,type);} while(0)
733
734 #define CHECK_ONEWORD(num,type)                                                                                 \
735         do {INDEX_ONEWORD(num);                                                                                         \
736                 if (!typevectorset_checktype(localset,num,type))                \
737             panic("Variable type mismatch");                            \
738                 } while(0)
739
740 #define CHECK_TWOWORD(num,type)                                                                                 \
741         do {INDEX_TWOWORD(num);                                                                                         \
742                 if (!typevectorset_checktype(localset,num,type))                \
743             panic("Variable type mismatch");                            \
744                 } while(0)
745
746 /* XXX maybe it's faster to copy always */
747 #define COPYTYPE(source,dest)   \
748             {if ((source)->type == TYPE_ADR) \
749                  TYPEINFO_COPY((source)->typeinfo,(dest)->typeinfo);}
750
751 #define ISBUILTIN(v)   (iptr->val.a == (functionptr)(v))
752
753 #define TYPECHECK_STACK(sp,tp)                                                                                  \
754         do { if ((sp)->type != (tp))                                                                            \
755                         panic("Wrong data type on stack"); } while(0)
756
757 #define TYPECHECK_ADR(sp)  TYPECHECK_STACK(sp,TYPE_ADR)
758 #define TYPECHECK_INT(sp)  TYPECHECK_STACK(sp,TYPE_INT)
759 #define TYPECHECK_LNG(sp)  TYPECHECK_STACK(sp,TYPE_LNG)
760 #define TYPECHECK_FLT(sp)  TYPECHECK_STACK(sp,TYPE_FLT)
761 #define TYPECHECK_DBL(sp)  TYPECHECK_STACK(sp,TYPE_DBL)
762
763 #define TYPECHECK_ARGS1(t1)                                                                 \
764         do {TYPECHECK_STACK(curstack,t1);} while (0)
765 #define TYPECHECK_ARGS2(t1,t2)                                                      \
766         do {TYPECHECK_ARGS1(t1);                                                                        \
767                 TYPECHECK_STACK(curstack->prev,t2);} while (0)
768 #define TYPECHECK_ARGS3(t1,t2,t3)                                                               \
769         do {TYPECHECK_ARGS2(t1,t2);                                                                     \
770                 TYPECHECK_STACK(curstack->prev->prev,t3);} while (0)
771
772 /* TYPECHECK_COPYVARS: copy the types and typeinfos of the current local
773  *     variables to the local variables of the target block.
774  * Input:
775  *     vtype......current local variable types
776  *     vinfo......current local variable typeinfos
777  *     ttype......local variable types of target block
778  *     tinfo......local variable typeinfos of target block
779  *     numlocals..number of local variables
780  * Used:
781  *     macro_i
782  */
783 #define TYPECHECK_COPYVARS                                      \
784     do {                                                        \
785     LOG("TYPECHECK_COPYVARS");                                  \
786     for (macro_i=0; macro_i<numlocals; ++macro_i) {             \
787         if ((ttype[macro_i] = vtype[macro_i]) == TYPE_ADR)      \
788             TYPEINFO_CLONE(vinfo[macro_i],tinfo[macro_i]);      \
789     } } while(0)
790
791 /* TYPECHECK_MERGEVARS: merge the local variables of the target block
792  *     with the current local variables.
793  * Input:
794  *     vtype......current local variable types
795  *     vinfo......current local variable typeinfos
796  *     ttype......local variable types of target block
797  *     tinfo......local variable typeinfos of target block
798  *     numlocals..number of local variables
799  * Ouput:
800  *     changed....set to true if any typeinfo has changed
801  * Used:
802  *     macro_i
803  */
804 #define TYPECHECK_MERGEVARS                                             \
805     do {                                                                \
806     LOG("TYPECHECK_MERGEVARS");                                         \
807     for (macro_i=0; macro_i<numlocals; ++macro_i) {                     \
808         if ((ttype[macro_i] != TYPE_VOID) && (vtype[macro_i] != ttype[macro_i])) { \
809             LOG3("var %d: type %d + type %d = void",macro_i,ttype[macro_i],vtype[macro_i]); \
810             ttype[macro_i] = TYPE_VOID;                                 \
811             changed = true;                                             \
812         } else if (ttype[macro_i] == TYPE_ADR) {                        \
813             if ( ((TYPEINFO_IS_PRIMITIVE(tinfo[macro_i])) ? 1 : 0)      \
814                  ^                                                      \
815                  ((TYPEINFO_IS_PRIMITIVE(vinfo[macro_i])) ? 1 : 0)) {   \
816                 LOG1("var %d: primitive + reference merge",macro_i);    \
817                 ttype[macro_i] = TYPE_VOID;                             \
818                 changed = true;                                         \
819             }                                                           \
820             else {                                                      \
821                 LOG1("var %d:",macro_i);                                \
822                 LOGINFO(tinfo+macro_i);                                 \
823                 LOGINFO(vinfo+macro_i);                                 \
824                 changed |= typeinfo_merge(tinfo+macro_i,vinfo+macro_i); \
825                 LOGINFO(tinfo+macro_i);                                 \
826                 LOGIF(changed,"vars have changed");                     \
827             }                                                           \
828         };                                                              \
829     } } while (0)
830
831 /* TYPECHECK_MERGEJSR:
832  *
833  * Input:
834  * Ouput:
835  *     tbptr......target block
836  *     changed....set to true if any typeinfo has changed
837  *     numlocals..number of local variables
838  *     touched....current touched flags of local variables
839  * Used:
840  *     macro_i, jsrtemp, jsrtemp2
841  */
842 #define TYPECHECK_MERGEJSR                                              \
843     do {                                                                \
844         LOG("TYPECHECK_MERGEJSR");                                      \
845     jsrtemp = jsrbuffer[tbptr-block];                                   \
846     jsrtemp2 = jsrchain;                                                \
847     while (jsrtemp || jsrtemp2) {                                       \
848         if (!jsrtemp || !jsrtemp2)                                      \
849             panic("Merging JSR subroutines of different depth");        \
850         if (jsrtemp->target != jsrtemp2->target)                        \
851             panic("Merging different JSR subroutines");                 \
852         jsrtemp = jsrtemp->next;                                        \
853         jsrtemp2 = jsrtemp2->next;                                      \
854     }                                                                   \
855     jsrtemp = jsrbuffer[tbptr-block];                                   \
856     if (jsrtemp)                                                        \
857         for (macro_i=0; macro_i<numlocals; ++macro_i) {                 \
858             jsrtemp->touched[i] |= touched[i];                          \
859     } } while (0)
860
861 /* TYPECHECK_COPYSTACK: copy the typeinfos of the current stack to
862  *     the input stack of the target block.
863  * Input:
864  *     srcstack...current stack
865  *     dststack...input stack of target block
866  */
867 #define TYPECHECK_COPYSTACK                                             \
868     do {                                                                \
869     LOG("TYPECHECK_COPYSTACK");                                         \
870     while (srcstack) {                                                  \
871         LOG1("copy %d",srcstack->type);                                 \
872         if (!dststack) panic("Stack depth mismatch");                   \
873         if (srcstack->type != dststack->type)                           \
874             panic("Type mismatch on stack");                            \
875         if (srcstack->type == TYPE_ADR) {                               \
876             TYPEINFO_CLONE(srcstack->typeinfo,dststack->typeinfo);      \
877         }                                                               \
878         dststack = dststack->prev;                                      \
879         srcstack = srcstack->prev;                                      \
880     }                                                                   \
881     if (dststack) panic("Stack depth mismatch");                        \
882     } while (0)
883
884 /* TYPECHECK_MERGESTACK: merge the input stack of the target block
885  *     with the current stack.
886  * Input:
887  *     srcstack...current stack
888  *     dststack...input stack of target block
889  * Ouput:
890  *     changed....set to true if any typeinfo has changed
891  */
892 #define TYPECHECK_MERGESTACK                                            \
893     do {                                                                \
894     LOG("TYPECHECK_MERGESTACK");                                        \
895     while (srcstack) {                                                  \
896         if (!dststack) panic("Stack depth mismatch");                   \
897         if (srcstack->type != dststack->type)                           \
898             panic("Type mismatch on stack");                            \
899         if (srcstack->type == TYPE_ADR) {                               \
900             LOGINFO(&dststack->typeinfo);                               \
901             LOGINFO(&srcstack->typeinfo);  LOGFLUSH;                    \
902             changed |= typeinfo_merge(&dststack->typeinfo,              \
903                                       &srcstack->typeinfo);             \
904             LOGINFO(&dststack->typeinfo);                               \
905             LOG((changed)?"CHANGED!\n":"not changed.\n");               \
906         }                                                               \
907         dststack = dststack->prev;                                      \
908         srcstack = srcstack->prev;                                      \
909     }                                                                   \
910     if (dststack) panic("Stack depth mismatch");                        \
911     } while(0)
912
913
914 /* TYPECHECK_CHECK_JSR_CHAIN: checks if the target block is reached by
915  *     the same JSR targets on all control paths.
916  *
917  * Input:
918  *     tbptr......target block
919  *     jsrchain...current JSR target chain
920  *     jsrbuffer..JSR target chain for each basic block
921  * Output:
922  *     panic if the JSR target chains don't match
923  * Used:
924  *     jsrtemp, jsrtemp2
925  */
926 #define TYPECHECK_CHECK_JSR_CHAIN                                       \
927     do {                                                                \
928     jsrtemp = jsrbuffer[tbptr-block];                                   \
929     if (!jsrtemp) panic("non-subroutine called by JSR");                \
930     if (jsrtemp->target != tbptr)                                       \
931         panic("Merging different JSR subroutines");                     \
932     jsrtemp = jsrtemp->next;                                            \
933     jsrtemp2 = jsrchain;                                                \
934     while (jsrtemp || jsrtemp2) {                                       \
935         if (!jsrtemp || !jsrtemp2)                                      \
936             panic("Merging JSR subroutines of different depth");        \
937         if (jsrtemp->target != jsrtemp2->target)                        \
938             panic("Merging different JSR subroutines");                 \
939         jsrtemp = jsrtemp->next;                                        \
940         jsrtemp2 = jsrtemp2->next;                                      \
941     } } while (0)
942
943 /* TYPECHECK_ADD_JSR: add a JSR target to the current JSR target chain
944  *     and store the resulting chain in the target block.
945  *
946  * Input:
947  *     jsrchain...current JSR target chain
948  *     tbptr.....the basic block targeted by the JSR
949  *     numlocals..number of local variables
950  *     jsrbuffer..JSR target chain for each basic block
951  * Used:
952  *     jsrtemp
953  */
954 #define TYPECHECK_ADD_JSR                                                                                                                               \
955     do {                                                                                                                                                                \
956     LOG1("adding JSR to block %04d",(tbptr)-block);                                                                             \
957     jsrtemp = jsrchain;                                                                                                                                 \
958     while (jsrtemp) {                                                                                                                                   \
959             if (jsrtemp->target == tbptr)                                                                                                       \
960                     panic("recursive JSR call");                                                                                                \
961         jsrtemp = jsrtemp->next;                                                                                                                \
962     }                                                                                                                                                                   \
963     jsrtemp = (jsr_record *) dump_alloc(sizeof(jsr_record)+(numlocals-1)*sizeof(u1));   \
964     jsrtemp->target = (tbptr);                                                                                                                  \
965     jsrtemp->next = jsrchain;                                                                                                                   \
966     jsrtemp->sbr_touched = NULL;                                                                                                                \
967     memset(&jsrtemp->touched,TOUCHED_NO,sizeof(u1)*numlocals);                                                  \
968     jsrbuffer[tbptr-block] = jsrtemp;                                                                                                   \
969     } while (0)
970
971 /* TYPECHECK_COPYJSR: copy the current JSR chain to the target block.
972  *
973  * Input:
974  *     chain......current JSR target chain
975  *     tbptr.....the basic block targeted by the JSR
976  *     numlocals..number of local variables
977  *     jsrbuffer..JSR target chain for each basic block
978  *     touched....current touched flags of local variables
979  * Used:
980  *     jsrtemp
981  */
982 #define TYPECHECK_COPYJSR(chain)                                        \
983     do {                                                                \
984         LOG("TYPECHECK_COPYJSR");                                       \
985         if (chain) {                                                    \
986             jsrtemp = (jsr_record *) dump_alloc(sizeof(jsr_record)+(numlocals-1)*sizeof(u1)); \
987             jsrtemp->target = (chain)->target;                          \
988             jsrtemp->next = (chain)->next;                              \
989             jsrtemp->sbr_touched = NULL;                                \
990             memcpy(&jsrtemp->touched,touched,sizeof(u1)*numlocals);     \
991             jsrbuffer[tbptr-block] = jsrtemp;                           \
992         }                                                               \
993         else                                                            \
994             jsrbuffer[tbptr-block] = NULL;                              \
995     } while (0)
996
997 /* TYPECHECK_BRANCH_BACKWARDS: executed when control flow moves
998  *     backwards. Checks if there are uninitialized objects on the
999  *     stack or in local variables.
1000  * Input:
1001  *     dst........current output stack pointer (not needed for REACH_THROW)
1002  *     vtype......current local variable types
1003  *     vinfo......current local variable typeinfos
1004  * Used:
1005  *     srcstack, macro_i
1006  */
1007 #define TYPECHECK_BRANCH_BACKWARDS                                      \
1008     do {                                                                \
1009         LOG("BACKWARDS!");                                              \
1010         srcstack = dst;                                                 \
1011         while (srcstack) {                                              \
1012             if (srcstack->type == TYPE_ADR &&                           \
1013                 TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo))              \
1014                 panic("Branching backwards with uninitialized object on stack"); \
1015             srcstack = srcstack->prev;                                  \
1016         }                                                               \
1017         for (macro_i=0; macro_i<numlocals; ++macro_i)                   \
1018             if (localset->td[macro_i].type == TYPE_ADR &&               \
1019                 TYPEINFO_IS_NEWOBJECT(localset->td[macro_i].info))      \
1020                 panic("Branching backwards with uninitialized object in local variable"); \
1021     } while(0)
1022
1023 /* XXX convert this into a function */
1024 /* TYPECHECK_REACH: executed, when the target block (tbptr) can be reached
1025  *     from the current block (bptr). The types of local variables and
1026  *     stack slots are propagated to the target block.
1027  * Input:
1028  *     bptr.......current block
1029  *     tbptr......target block
1030  *     dst........current output stack pointer (not needed for REACH_THROW)
1031  *     numlocals..number of local variables
1032  *     vtype......current local variable types
1033  *     vinfo......current local variable typeinfos
1034  *     jsrchain...current JSR target chain
1035  *     jsrbuffer..JSR target chain for each basic block
1036  *     way........in which way the block is reached (REACH_ constant)
1037  *     touched....current touched flags of local variables
1038  * Output:
1039  *     repeat.....changed to true if a block before the current
1040  *                block has changed
1041  * Used:
1042  *     ttype, tinfo, srcstack, dststack, changed, macro_i
1043  */
1044 #define TYPECHECK_REACH(way)                                            \
1045     do {                                                                \
1046     LOG2("reaching block %04d (%d)",tbptr-block,way);                   \
1047     if (tbptr <= bptr)                                                  \
1048         TYPECHECK_BRANCH_BACKWARDS;                                     \
1049     repeat |= typestate_reach(localbuf,bptr,tbptr,dst,                  \
1050                                                           localset,numlocals);                      \
1051     LOG("done.");                                                       \
1052     } while (0)
1053
1054 /* TYPECHECK_LEAVE: executed when the method is exited non-abruptly
1055  * Input:
1056  *     class........class of the current method
1057  *     numlocals....number of local variables
1058  *     vtype........current local variable types
1059  *     vinfo........current local variable typeinfos
1060  *     initmethod...true if this is an <init> method
1061  */
1062 #define TYPECHECK_LEAVE                                                 \
1063     do {                                                                \
1064         if (initmethod && class != class_java_lang_Object) {            \
1065             /* check the marker variable */                             \
1066             LOG("Checking <init> marker");                              \
1067             if (!typevectorset_checktype(localset,numlocals-1,TYPE_INT))\
1068                 panic("<init> method does not initialize 'this'");      \
1069         }                                                               \
1070     } while (0)
1071
1072 /****************************************************************************/
1073 /* typecheck()                                                              */
1074 /****************************************************************************/
1075
1076 #define MAXPARAMS 255
1077
1078 /* typecheck is called directly after analyse_stack */
1079 void
1080 typecheck()
1081 {
1082     int b_count, b_index;
1083     stackptr curstack;      /* input stack top for current instruction */
1084     stackptr srcstack;         /* source stack for copying and merging */
1085     stackptr dststack;         /* target stack for copying and merging */
1086     int opcode;                                      /* current opcode */
1087     int macro_i, i;                              /* temporary counters */
1088     int len;                        /* for counting instructions, etc. */
1089     bool superblockend;        /* true if no fallthrough to next block */
1090     bool repeat;            /* if true, blocks are iterated over again */
1091     bool changed;                                    /* used in macros */
1092     instruction *iptr;               /* pointer to current instruction */
1093     basicblock *bptr;                /* pointer to current basic block */
1094     basicblock *tbptr;                   /* temporary for target block */
1095     int numlocals;                        /* number of local variables */
1096         int validlocals;         /* number of valid local variable indices */
1097
1098         void *localbuf;       /* local variable types for each block start */
1099         typevector *localset;        /* typevector set for local variables */
1100         typevector *lset;                             /* temporary pointer */
1101         typedescriptor *td;                           /* temporary pointer */
1102
1103     typeinfo tempinfo;                                    /* temporary */
1104
1105         typedescriptor returntype;        /* return type of current method */
1106         
1107     u1 *ptype;                     /* parameter types of called method */
1108     typeinfo *pinfo;           /* parameter typeinfos of called method */
1109     int rtype;                         /* return type of called method */
1110     typeinfo rinfo;       /* typeinfo for return type of called method */
1111     stackptr dst;               /* output stack of current instruction */
1112     basicblock **tptr;    /* pointer into target list of switch instr. */
1113     jsr_record **jsrbuffer;   /* JSR target chain for each basic block */
1114     jsr_record *jsrchain;               /* JSR chain for current block */
1115     jsr_record *jsrtemp,*jsrtemp2;              /* temporary variables */
1116     jsr_record *subroutine;    /* jsr_record of the current subroutine */
1117     u1 *touched;                  /* touched flags for local variables */
1118     xtable **handlers;                    /* active exception handlers */
1119     classinfo *cls;                                       /* temporary */
1120     bool maythrow;               /* true if this instruction may throw */
1121     utf *name_init;                                        /* "<init>" */
1122     bool initmethod;             /* true if this is an "<init>" method */
1123         builtin_descriptor *builtindesc;
1124
1125 #ifdef TYPECHECK_STATISTICS
1126         int count_iterations = 0;
1127 #endif
1128
1129     LOGSTR("\n==============================================================================\n");
1130     DOLOG(show_icmd_method());
1131     LOGSTR("\n==============================================================================\n");
1132     LOGimpSTR("Entering typecheck: ");
1133     LOGimpSTRu(method->name);
1134     LOGimpSTR("    ");
1135     LOGimpSTRu(method->descriptor);
1136     LOGimpSTR("    (class ");
1137     LOGimpSTRu(method->class->name);
1138     LOGimpSTR(")\n");
1139
1140     name_init = utf_new_char("<init>");
1141     initmethod = (method->name == name_init);
1142
1143     ptype = DMNEW(u1,MAXPARAMS);
1144     pinfo = DMNEW(typeinfo,MAXPARAMS);
1145     
1146     LOG("Buffer allocated.\n");
1147
1148     /* reset all BBFINISHED blocks to BBTYPECHECK_UNDEF. */
1149     b_count = block_count;
1150     bptr = block;
1151     while (--b_count >= 0) {
1152 #ifdef TYPECHECK_DEBUG
1153         if (bptr->flags != BBFINISHED && bptr->flags != BBDELETED
1154             && bptr->flags != BBUNDEF)
1155         {
1156             show_icmd_method();
1157             LOGSTR1("block flags: %d\n",bptr->flags); LOGFLUSH;
1158             panic("Internal error: Unexpected block flags in typecheck()");
1159         }
1160 #endif
1161         if (bptr->flags >= BBFINISHED) {
1162             bptr->flags = BBTYPECHECK_UNDEF;
1163         }
1164         bptr++;
1165     }
1166
1167     /* The first block is always reached */
1168     if (block_count && block[0].flags == BBTYPECHECK_UNDEF)
1169         block[0].flags = BBTYPECHECK_REACHED;
1170
1171     LOG("Blocks reset.\n");
1172
1173     /* number of local variables */
1174     
1175     /* In <init> methods we use an extra local variable to signal if
1176      * the 'this' reference has been initialized. */
1177     numlocals = maxlocals;
1178         validlocals = numlocals;
1179     if (initmethod) numlocals++;
1180
1181     /* allocate the buffers for local variables */
1182         localbuf = DMNEW_TYPEVECTOR(block_count+1, numlocals);
1183         localset = MGET_TYPEVECTOR(localbuf,block_count,numlocals);
1184         memset(localbuf,0,(block_count+1) * TYPEVECTOR_SIZE(numlocals));
1185
1186     LOG("Variable buffer allocated.\n");
1187
1188     /* allocate the buffer for storing JSR target chains */
1189     jsrbuffer = DMNEW(jsr_record*,block_count);
1190     memset(jsrbuffer,0,block_count * sizeof(jsr_record*));
1191     jsrchain = NULL;
1192     
1193     LOG("jsrbuffer initialized.\n");
1194
1195     /* allocate the buffer of active exception handlers */
1196     handlers = DMNEW(xtable*,method->exceptiontablelength + 1);
1197
1198     /* initialize the variable types of the first block */
1199     /* to the types of the arguments */
1200         lset = MGET_TYPEVECTOR(localbuf,0,numlocals);
1201         td = lset->td;
1202         i = numlocals;
1203
1204     /* if this is an instance method initialize the "this" ref type */
1205     if (!(method->flags & ACC_STATIC)) {
1206         td->type = TYPE_ADDRESS;
1207         if (initmethod)
1208             TYPEINFO_INIT_NEWOBJECT(td->info,NULL);
1209         else
1210             TYPEINFO_INIT_CLASSINFO(td->info,class);
1211         td++;
1212                 i--;
1213     }
1214
1215     LOG("'this' argument set.\n");
1216
1217     /* the rest of the arguments and the return type */
1218     i = typedescriptors_init_from_method_args(td,method->descriptor,
1219                                                                                           i,
1220                                                                                           true, /* two word types use two slots */
1221                                                                                           &returntype);
1222         td += i;
1223         i = numlocals - (td - lset->td);
1224         while (i--) {
1225                 td->type = TYPE_VOID;
1226                 td++;
1227         }
1228
1229     LOG("Arguments set.\n");
1230
1231     /* initialize the input stack of exception handlers */
1232     for (i=0; i<method->exceptiontablelength; ++i) {
1233         cls = extable[i].catchtype;
1234         if (!cls) cls = class_java_lang_Throwable;
1235         LOGSTR1("handler %i: ",i); LOGSTRu(cls->name); LOGNL;
1236         TYPEINFO_INIT_CLASSINFO(extable[i].handler->instack->typeinfo,cls);
1237     }
1238
1239     LOG("Exception handler stacks set.\n");
1240
1241     /* loop while there are still blocks to be checked */
1242     do {
1243                 TYPECHECK_COUNT(count_iterations);
1244
1245         repeat = false;
1246         
1247         b_count = block_count;
1248         bptr = block;
1249
1250         while (--b_count >= 0) {
1251             LOGSTR1("---- BLOCK %04d, ",bptr-block);
1252             LOGSTR1("blockflags: %d\n",bptr->flags);
1253             LOGFLUSH;
1254                 
1255             if (bptr->flags == BBTYPECHECK_REACHED) {
1256                 LOGSTR1("\n---- BLOCK %04d ------------------------------------------------\n",bptr-block);
1257                 LOGFLUSH;
1258                 
1259                 superblockend = false;
1260                 bptr->flags = BBFINISHED;
1261                 b_index = bptr - block;
1262
1263                 /* init stack at the start of this block */
1264                 curstack = bptr->instack;
1265                                         
1266                 /* determine the active exception handlers for this block */
1267                 /* XXX could use a faster algorithm with sorted lists or
1268                  * something? */
1269                 len = 0;
1270                 for (i=0; i<method->exceptiontablelength; ++i) {
1271                     if ((extable[i].start <= bptr) && (extable[i].end > bptr)) {
1272                         LOG1("active handler L%03d",extable[i].handler->debug_nr);
1273                         handlers[len++] = extable + i;
1274                     }
1275                 }
1276                 handlers[len] = NULL;
1277                                         
1278                 /* init variable types at the start of this block */
1279                                 COPY_TYPEVECTORSET(MGET_TYPEVECTOR(localbuf,b_index,numlocals),
1280                                                                    localset,numlocals);
1281                                 if (handlers[0])
1282                                         for (i=0; i<numlocals; ++i)
1283                                                 if (localset->td[i].type == TYPE_ADR
1284                                                         && TYPEINFO_IS_NEWOBJECT(localset->td[i].info))
1285                                                         panic("Uninitialized object in local variable inside try block");
1286
1287                 /* init JSR target chain */
1288                 if ((jsrchain = jsrbuffer[b_index]) != NULL) {
1289 #ifdef TYPECHECK_VERBOSE
1290                     if (typecheckverbose) {
1291                         LOGSTR("jsr chain:");
1292                         jsrtemp = jsrchain;
1293                         while (jsrtemp) {
1294                             LOGSTR1(" L%03d",jsrtemp->target->debug_nr);
1295                             jsrtemp = jsrtemp->next;
1296                         }
1297                         LOGNL;
1298                         LOGFLUSH;
1299                     }
1300 #endif
1301
1302                     subroutine = jsrbuffer[jsrchain->target - block];
1303                     memcpy(touched,jsrchain->touched,sizeof(u1)*numlocals);
1304                 }
1305                 else
1306                     subroutine = NULL;
1307 #ifdef TYPECHECK_VERBOSE
1308                 if (typecheckverbose) {
1309                     if (subroutine) {LOGSTR1("subroutine L%03d\n",subroutine->target->debug_nr);LOGFLUSH;}
1310                     typestate_print(get_logfile(),curstack,localset,numlocals);
1311                     LOGNL; LOGFLUSH;
1312                 }
1313 #endif
1314
1315                 /* loop over the instructions */
1316                 len = bptr->icount;
1317                 iptr = bptr->iinstr;
1318                 while (--len >= 0)  {
1319                     DOLOG(show_icmd(iptr,false));
1320                     LOGNL;
1321                     LOGFLUSH;
1322                         
1323                     opcode = iptr->opc;
1324                     dst = iptr->dst;
1325                     maythrow = false;
1326                                                 
1327                     switch (opcode) {
1328
1329                         /****************************************/
1330                         /* STACK MANIPULATIONS                  */
1331
1332                         /* We just need to copy the typeinfo */
1333                         /* for slots containing addresses.   */
1334
1335                         /* XXX We assume that the destination stack
1336                          * slots were continuously allocated in
1337                          * memory.  (The current implementation in
1338                          * stack.c)
1339                          */
1340
1341                       case ICMD_DUP:
1342                           COPYTYPE(curstack,dst);
1343                           break;
1344                                                           
1345                       case ICMD_DUP_X1:
1346                           COPYTYPE(curstack,dst);
1347                           COPYTYPE(curstack,dst-2);
1348                           COPYTYPE(curstack->prev,dst-1);
1349                           break;
1350                                                           
1351                       case ICMD_DUP_X2:
1352                           COPYTYPE(curstack,dst);
1353                           COPYTYPE(curstack,dst-3);
1354                           COPYTYPE(curstack->prev,dst-1);
1355                           COPYTYPE(curstack->prev->prev,dst-2);
1356                           break;
1357                                                           
1358                       case ICMD_DUP2:
1359                           COPYTYPE(curstack,dst);
1360                           COPYTYPE(curstack->prev,dst-1);
1361                           break;
1362
1363                       case ICMD_DUP2_X1:
1364                           COPYTYPE(curstack,dst);
1365                           COPYTYPE(curstack->prev,dst-1);
1366                           COPYTYPE(curstack,dst-3);
1367                           COPYTYPE(curstack->prev,dst-4);
1368                           COPYTYPE(curstack->prev->prev,dst-2);
1369                           break;
1370                                                           
1371                       case ICMD_DUP2_X2:
1372                           COPYTYPE(curstack,dst);
1373                           COPYTYPE(curstack->prev,dst-1);
1374                           COPYTYPE(curstack,dst-4);
1375                           COPYTYPE(curstack->prev,dst-5);
1376                           COPYTYPE(curstack->prev->prev,dst-2);
1377                           COPYTYPE(curstack->prev->prev->prev,dst-3);
1378                           break;
1379                                                           
1380                       case ICMD_SWAP:
1381                           COPYTYPE(curstack,dst-1);
1382                           COPYTYPE(curstack->prev,dst);
1383                           break;
1384
1385                           /****************************************/
1386                           /* PRIMITIVE VARIABLE ACCESS            */
1387
1388                       case ICMD_ILOAD: CHECK_ONEWORD(iptr->op1,TYPE_INT); break;
1389                       case ICMD_FLOAD: CHECK_ONEWORD(iptr->op1,TYPE_FLOAT); break;
1390                       case ICMD_IINC:  CHECK_ONEWORD(iptr->op1,TYPE_INT); break;
1391                       case ICMD_LLOAD: CHECK_TWOWORD(iptr->op1,TYPE_LONG); break;
1392                       case ICMD_DLOAD: CHECK_TWOWORD(iptr->op1,TYPE_DOUBLE); break;
1393                           
1394                       case ICMD_FSTORE: STORE_ONEWORD(iptr->op1,TYPE_FLOAT); break;
1395                       case ICMD_ISTORE: STORE_ONEWORD(iptr->op1,TYPE_INT); break;
1396                       case ICMD_LSTORE: STORE_TWOWORD(iptr->op1,TYPE_LONG); break;
1397                       case ICMD_DSTORE: STORE_TWOWORD(iptr->op1,TYPE_DOUBLE); break;
1398                           
1399                           /****************************************/
1400                           /* LOADING ADDRESS FROM VARIABLE        */
1401
1402                       case ICMD_ALOAD:
1403                                                   INDEX_ONEWORD(iptr->op1);
1404                           
1405                           /* loading a returnAddress is not allowed */
1406                           if (!typevectorset_checkreference(localset,iptr->op1))
1407                               panic("illegal instruction: ALOAD loading non-reference");
1408
1409                                                   typevectorset_copymergedtype(localset,iptr->op1,&(dst->typeinfo));
1410                           break;
1411                                                         
1412                           /****************************************/
1413                           /* STORING ADDRESS TO VARIABLE          */
1414
1415                       case ICMD_ASTORE:
1416                           if (handlers[0] &&
1417                               TYPEINFO_IS_NEWOBJECT(curstack->typeinfo))
1418                               panic("Storing uninitialized object in local variable inside try block");
1419
1420                                                   INDEX_ONEWORD(iptr->op1);
1421                                                   if (TYPESTACK_IS_RETURNADDRESS(curstack))
1422                                                           typevectorset_store_retaddr(localset,iptr->op1,&(curstack->typeinfo));
1423                                                   else
1424                                                           typevectorset_store(localset,iptr->op1,TYPE_ADDRESS,
1425                                                                                                   &(curstack->typeinfo));
1426                           break;
1427                           
1428                           /****************************************/
1429                           /* LOADING ADDRESS FROM ARRAY           */
1430
1431                       case ICMD_AALOAD:
1432                           if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(curstack->prev->typeinfo))
1433                               panic("illegal instruction: AALOAD on non-reference array");
1434
1435                           typeinfo_init_component(&curstack->prev->typeinfo,&dst->typeinfo);
1436                           maythrow = true;
1437                           break;
1438                                                           
1439                           /****************************************/
1440                           /* FIELD ACCESS                         */
1441
1442                       case ICMD_PUTFIELD:
1443                           if (!TYPEINFO_IS_REFERENCE(curstack->prev->typeinfo))
1444                               panic("illegal instruction: PUTFIELD on non-reference");
1445                           if (TYPEINFO_IS_ARRAY(curstack->prev->typeinfo)) /* XXX arraystub */
1446                               panic("illegal instruction: PUTFIELD on array");
1447
1448                           /* check if the value is assignable to the field */
1449                                                   {
1450                                                           fieldinfo *fi = (fieldinfo*) iptr[0].val.a;
1451
1452                                                           if (TYPEINFO_IS_NEWOBJECT(curstack->prev->typeinfo)) {
1453                                                                   if (initmethod
1454                                                                           && !TYPEINFO_NEWOBJECT_INSTRUCTION(curstack->prev->typeinfo))
1455                                                                   {
1456                                                                           /* uninitialized "this" instance */
1457                                                                           if (fi->class != class || (fi->flags & ACC_STATIC) != 0)
1458                                                                                   panic("Setting unaccessible field in uninitialized object");
1459                                                                   }
1460                                                                   else {
1461                                                                           panic("PUTFIELD on uninitialized object");
1462                                                                   }
1463                                                           }
1464                                                           else {
1465                                                                   if (!is_accessible(fi->flags,fi->class,fi->class,
1466                                                                                                          &(curstack->prev->typeinfo)))
1467                                                                           panic("PUTFIELD: field is not accessible");
1468                                                           }
1469
1470                                                           /* XXX ---> unify with ICMD_PUTSTATIC? */
1471                                                           
1472                                                           if (curstack->type != fi->type)
1473                                                                   panic("PUTFIELD type mismatch");
1474                                                           if (fi->type == TYPE_ADR) {
1475                                                                   TYPEINFO_INIT_FROM_FIELDINFO(rinfo,fi);
1476                                                                   if (!typeinfo_is_assignable(&(curstack->typeinfo),
1477                                                                                                                           &rinfo))
1478                                                                           panic("PUTFIELD reference type not assignable");
1479                                                           }
1480                                                   }
1481                           maythrow = true;
1482                           break;
1483
1484                       case ICMD_PUTSTATIC:
1485                           /* check if the value is assignable to the field */
1486                                                   {
1487                                                           fieldinfo *fi = (fieldinfo*) iptr[0].val.a;
1488
1489                                                           if (!is_accessible(fi->flags,fi->class,fi->class,NULL))
1490                                                                   panic("PUTSTATIC: field is not accessible");
1491
1492                                                           if (curstack->type != fi->type)
1493                                                                   panic("PUTSTATIC type mismatch");
1494                                                           if (fi->type == TYPE_ADR) {
1495                                                                   TYPEINFO_INIT_FROM_FIELDINFO(rinfo,fi);
1496                                                                   if (!typeinfo_is_assignable(&(curstack->typeinfo),
1497                                                                                                                           &rinfo))
1498                                                                           panic("PUTSTATIC reference type not assignable");
1499                                                           }
1500                                                   }
1501                           maythrow = true;
1502                           break;
1503
1504                       case ICMD_GETFIELD:
1505                           if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1506                               panic("illegal instruction: GETFIELD on non-reference");
1507                           if (TYPEINFO_IS_ARRAY(curstack->typeinfo))
1508                               panic("illegal instruction: GETFIELD on array");
1509                           
1510                           {
1511                               fieldinfo *fi = (fieldinfo *)(iptr->val.a);
1512
1513                                                           if (!is_accessible(fi->flags,fi->class,fi->class,
1514                                                                                                  &(curstack->typeinfo)))
1515                                                                   panic("GETFIELD: field is not accessible");
1516
1517                               if (dst->type == TYPE_ADR) {
1518                                   TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi);
1519                               }
1520                               else {
1521                                   /* XXX check field type? */
1522                                   TYPEINFO_INIT_PRIMITIVE(dst->typeinfo);
1523                               }
1524                           }
1525                           maythrow = true;
1526                           break;
1527
1528                       case ICMD_GETSTATIC:
1529                           {
1530                               fieldinfo *fi = (fieldinfo *)(iptr->val.a);
1531                                                           
1532                                                           if (!is_accessible(fi->flags,fi->class,fi->class,NULL))
1533                                                                   panic("GETSTATIC: field is not accessible");
1534
1535                               if (dst->type == TYPE_ADR) {
1536                                   TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi);
1537                               }
1538                               else {
1539                                   /* XXX check field type? */
1540                                   TYPEINFO_INIT_PRIMITIVE(dst->typeinfo);
1541                               }
1542                           }
1543                           maythrow = true;
1544                           break;
1545
1546                           /****************************************/
1547                           /* PRIMITIVE ARRAY ACCESS               */
1548
1549                       case ICMD_ARRAYLENGTH:
1550                           /* XXX should this also work on arraystubs? */
1551                           if (!TYPEINFO_MAYBE_ARRAY(curstack->typeinfo))
1552                               panic("illegal instruction: ARRAYLENGTH on non-array");
1553                           maythrow = true;
1554                           break;
1555
1556                                                   /* XXX unify cases? */
1557                       case ICMD_BALOAD:
1558                           if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_BOOLEAN)
1559                               && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_BYTE))
1560                               panic("Array type mismatch");
1561                           maythrow = true;
1562                           break;
1563                       case ICMD_CALOAD:
1564                           if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_CHAR))
1565                               panic("Array type mismatch");
1566                           maythrow = true;
1567                           break;
1568                       case ICMD_DALOAD:
1569                           if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_DOUBLE))
1570                               panic("Array type mismatch");
1571                           maythrow = true;
1572                           break;
1573                       case ICMD_FALOAD:
1574                           if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_FLOAT))
1575                               panic("Array type mismatch");
1576                           maythrow = true;
1577                           break;
1578                       case ICMD_IALOAD:
1579                           if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_INT))
1580                               panic("Array type mismatch");
1581                           maythrow = true;
1582                           break;
1583                       case ICMD_SALOAD:
1584                           if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_SHORT))
1585                               panic("Array type mismatch");
1586                           maythrow = true;
1587                           break;
1588                       case ICMD_LALOAD:
1589                           if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_LONG))
1590                               panic("Array type mismatch");
1591                           maythrow = true;
1592                           break;
1593
1594                       case ICMD_BASTORE:
1595                           if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_BOOLEAN)
1596                               && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_BYTE))
1597                               panic("Array type mismatch");
1598                           maythrow = true;
1599                           break;
1600                       case ICMD_CASTORE:
1601                           if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_CHAR))
1602                               panic("Array type mismatch");
1603                           maythrow = true;
1604                           break;
1605                       case ICMD_DASTORE:
1606                           if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_DOUBLE))
1607                               panic("Array type mismatch");
1608                           maythrow = true;
1609                           break;
1610                       case ICMD_FASTORE:
1611                           if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_FLOAT))
1612                               panic("Array type mismatch");
1613                           maythrow = true;
1614                           break;
1615                       case ICMD_IASTORE:
1616                           if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_INT))
1617                               panic("Array type mismatch");
1618                           maythrow = true;
1619                           break;
1620                       case ICMD_SASTORE:
1621                           if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_SHORT))
1622                               panic("Array type mismatch");
1623                           maythrow = true;
1624                           break;
1625                       case ICMD_LASTORE:
1626                           if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_LONG))
1627                               panic("Array type mismatch");
1628                           maythrow = true;
1629                           break;
1630
1631                           /****************************************/
1632                           /* ADDRESS CONSTANTS                    */
1633
1634                       case ICMD_ACONST:
1635                           if (iptr->val.a == NULL)
1636                               TYPEINFO_INIT_NULLTYPE(dst->typeinfo);
1637                           else
1638                               /* XXX constants for builtin functions */
1639                               /* string constants */
1640                               TYPEINFO_INIT_CLASSINFO(dst->typeinfo,class_java_lang_String);
1641                           break;
1642
1643                           /****************************************/
1644                           /* CHECKCAST AND INSTANCEOF             */
1645
1646                       case ICMD_CHECKCAST:
1647                                                   TYPECHECK_ADR(curstack);
1648                           /* returnAddress is not allowed */
1649                           if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1650                               panic("Illegal instruction: CHECKCAST on non-reference");
1651
1652                           /* XXX check if the cast can be done statically */
1653                           TYPEINFO_INIT_CLASSINFO(dst->typeinfo,(classinfo *)iptr[0].val.a);
1654                           /* XXX */
1655                           maythrow = true;
1656                           break;
1657
1658                       case ICMD_INSTANCEOF:
1659                                                   TYPECHECK_ADR(curstack);
1660                           /* returnAddress is not allowed */
1661                           if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1662                               panic("Illegal instruction: INSTANCEOF on non-reference");
1663                           
1664                           /* XXX optimize statically? */
1665                           break;
1666                           
1667                           /****************************************/
1668                           /* BRANCH INSTRUCTIONS                  */
1669
1670                       case ICMD_GOTO:
1671                           superblockend = true;
1672                           /* FALLTHROUGH! */
1673                       case ICMD_IFNULL:
1674                       case ICMD_IFNONNULL:
1675                       case ICMD_IFEQ:
1676                       case ICMD_IFNE:
1677                       case ICMD_IFLT:
1678                       case ICMD_IFGE:
1679                       case ICMD_IFGT:
1680                       case ICMD_IFLE:
1681                       case ICMD_IF_ICMPEQ:
1682                       case ICMD_IF_ICMPNE:
1683                       case ICMD_IF_ICMPLT:
1684                       case ICMD_IF_ICMPGE:
1685                       case ICMD_IF_ICMPGT:
1686                       case ICMD_IF_ICMPLE:
1687                       case ICMD_IF_ACMPEQ:
1688                       case ICMD_IF_ACMPNE:
1689                       case ICMD_IF_LEQ:
1690                       case ICMD_IF_LNE:
1691                       case ICMD_IF_LLT:
1692                       case ICMD_IF_LGE:
1693                       case ICMD_IF_LGT:
1694                       case ICMD_IF_LLE:
1695                       case ICMD_IF_LCMPEQ:
1696                       case ICMD_IF_LCMPNE:
1697                       case ICMD_IF_LCMPLT:
1698                       case ICMD_IF_LCMPGE:
1699                       case ICMD_IF_LCMPGT:
1700                       case ICMD_IF_LCMPLE:
1701                           tbptr = (basicblock *) iptr->target;
1702
1703                           /* propagate stack and variables to the target block */
1704                           TYPECHECK_REACH(REACH_STD);
1705                           /* XXX */
1706                           break;
1707
1708                           /****************************************/
1709                           /* SWITCHES                             */
1710                           
1711                       case ICMD_TABLESWITCH:
1712                           {
1713                               s4 *s4ptr = iptr->val.a;
1714                               s4ptr++;              /* skip default */
1715                               i = *s4ptr++;         /* low */
1716                               i = *s4ptr++ - i + 2; /* +1 for default target */
1717                           }
1718                           goto switch_instruction_tail;
1719                           
1720                       case ICMD_LOOKUPSWITCH:
1721                           {
1722                               s4 *s4ptr = iptr->val.a;
1723                               s4ptr++;              /* skip default */
1724                               i = *s4ptr++ + 1;     /* count +1 for default */
1725                           }
1726                     switch_instruction_tail:
1727                           tptr = (basicblock **)iptr->target;
1728                           
1729                           while (--i >= 0) {
1730                               tbptr = *tptr++;
1731                               LOG2("target %d is block %04d",(tptr-(basicblock **)iptr->target)-1,tbptr-block);
1732                               TYPECHECK_REACH(REACH_STD);
1733                           }
1734                           LOG("switch done");
1735                           superblockend = true;
1736                           break;
1737
1738                           /****************************************/
1739                           /* RETURNS AND THROW                    */
1740
1741                       case ICMD_ATHROW:
1742                           TYPEINFO_INIT_CLASSINFO(tempinfo,class_java_lang_Throwable);
1743                           if (!typeinfo_is_assignable(&curstack->typeinfo,&tempinfo))
1744                               panic("illegal instruction: ATHROW on non-Throwable");
1745                           superblockend = true;
1746                           maythrow = true;
1747                           break;
1748
1749                       case ICMD_ARETURN:
1750                           if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1751                               panic("illegal instruction: ARETURN on non-reference");
1752
1753                           if (returntype.type != TYPE_ADDRESS
1754                               || !typeinfo_is_assignable(&curstack->typeinfo,&(returntype.info)))
1755                               panic("Return type mismatch");
1756                                                   goto return_tail;
1757                                                   
1758                       case ICMD_IRETURN:
1759                           if (returntype.type != TYPE_INT) panic("Return type mismatch");
1760                                                   goto return_tail;
1761                                                   
1762                       case ICMD_LRETURN:
1763                           if (returntype.type != TYPE_LONG) panic("Return type mismatch");
1764                                                   goto return_tail;
1765                                                   
1766                       case ICMD_FRETURN:
1767                           if (returntype.type != TYPE_FLOAT) panic("Return type mismatch");
1768                                                   goto return_tail;
1769                                                   
1770                       case ICMD_DRETURN:
1771                           if (returntype.type != TYPE_DOUBLE) panic("Return type mismatch");
1772                                                   goto return_tail;
1773                                                   
1774                       case ICMD_RETURN:
1775                           if (returntype.type != TYPE_VOID) panic("Return type mismatch");
1776                                           return_tail:
1777                           TYPECHECK_LEAVE;
1778                           superblockend = true;
1779                           maythrow = true;
1780                           break;
1781                                                     
1782                           /****************************************/
1783                           /* SUBROUTINE INSTRUCTIONS              */
1784
1785                       case ICMD_JSR:
1786                           LOG("jsr");
1787
1788                           /* XXX This is a dirty hack. It is needed
1789                            * because of the special handling of ICMD_JSR in stack.c
1790                            */
1791                           dst = (stackptr) iptr->val.a;
1792                           
1793                           tbptr = (basicblock *) iptr->target;
1794                                                   repeat |= typestate_jsr(localbuf,bptr,tbptr,dst,localset,numlocals);
1795 #if 0
1796                           TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,tbptr);
1797
1798                           LOG("reaching block...");
1799                           
1800                           /* add the target to the JSR target chain and */
1801                           /* propagate stack and variables to the target block */
1802                           TYPECHECK_REACH(REACH_JSR);
1803
1804                           /* set dst to the stack after the subroutine execution */
1805                           /* XXX We assume (as in stack.c) that the
1806                            * subroutine returns the stack as it was
1807                            * before the JSR instruction. Is this
1808                            * correct?
1809                            */
1810                           dst = iptr->dst;
1811
1812                           /* Find the jsr_record of the called subroutine */
1813                           jsrtemp = jsrbuffer[tbptr - block];
1814
1815                           /* Check if we already calculated (at least
1816                            * for one RET) which variables the
1817                            * subroutine touches.
1818                            */
1819                           if (jsrtemp->sbr_touched) {
1820                               /* Calculate the local variables after the subroutine call */
1821                               for (i=0; i<numlocals; ++i)
1822                                   if (jsrtemp->sbr_touched[i] != TOUCHED_NO) {
1823                                       TOUCH_VARIABLE(i);
1824                                       if ((vtype[i] = jsrtemp->sbr_vtype[i]) == TYPE_ADR)
1825                                           TYPEINFO_CLONE(jsrtemp->sbr_vinfo[i],vinfo[i]);
1826                                   }
1827
1828                               /* continue after the JSR call */
1829                               superblockend = false;
1830                           }
1831                           else {
1832                               /* We cannot proceed until the subroutine has been typechecked. */
1833                               /* XXX actually we would not have to check this block again */
1834                               bptr->flags = BBTYPECHECK_REACHED;
1835                               repeat = true;
1836                               superblockend = true;
1837                           }
1838 #endif
1839                           /* XXX may throw? I don't think so. */
1840                                                   superblockend = true;
1841                           break;
1842                           
1843                       case ICMD_RET:
1844                           /* check returnAddress variable */
1845                           INDEX_ONEWORD(iptr->op1);
1846                                                   if (!typevectorset_checkretaddr(localset,iptr->op1))
1847                               panic("illegal instruction: RET using non-returnAddress variable");
1848
1849                                                   repeat |= typestate_ret(localbuf,bptr,curstack,
1850                                                                                                   localset,iptr->op1,numlocals);
1851
1852 #if 0
1853                           /* check if we are inside a subroutine */
1854                           if (!subroutine)
1855                               panic("RET outside of subroutine");
1856
1857                                                   /* check if the right returnAddress is used (XXX is this too strict?) */
1858                                                   if ((basicblock*)TYPEINFO_RETURNADDRESS(vinfo[iptr->op1])
1859                                                           != subroutine->target)
1860                                                           panic("RET uses returnAddress of another subroutine");
1861
1862                           /* determine which variables are touched by this subroutine */
1863                           /* and their types */
1864                           if (subroutine->sbr_touched) {
1865                                                           /* We have reached a RET in this subroutine before. */
1866                                                           
1867                                                           /* Check if there is more than one RET instruction
1868                                                            * returning from this subroutine. */
1869                                                           if (subroutine->sbr_ret != iptr)
1870                                                                   panic("JSR subroutine has more than one RET instruction");
1871
1872                                                           /* Merge the array of touched locals and their types */
1873                               for (i=0; i<numlocals; ++i)
1874                                   subroutine->sbr_touched[i] |= touched[i];
1875                               ttype = subroutine->sbr_vtype;
1876                               tinfo = subroutine->sbr_vinfo;
1877                               TYPECHECK_MERGEVARS;
1878                                                           /* XXX check if subroutine changed types? */
1879                           }
1880                           else {
1881                                                           /* This is the first time we reach a RET in this subroutine */
1882                                                           subroutine->sbr_ret = iptr;
1883                               subroutine->sbr_touched = DMNEW(u1,numlocals);
1884                               memcpy(subroutine->sbr_touched,touched,sizeof(u1)*numlocals);
1885                               subroutine->sbr_vtype = DMNEW(u1,numlocals);
1886                               memcpy(subroutine->sbr_vtype,vtype,sizeof(u1)*numlocals);
1887                               subroutine->sbr_vinfo = DMNEW(typeinfo,numlocals);
1888                               for (i=0; i<numlocals; ++i)
1889                                   if (vtype[i] == TYPE_ADR)
1890                                       TYPEINFO_CLONE(vinfo[i],subroutine->sbr_vinfo[i]);
1891                           }
1892
1893                           LOGSTR("subroutine touches:");
1894                           DOLOG(typeinfo_print_locals(get_logfile(),subroutine->sbr_vtype,subroutine->sbr_vinfo,
1895                                                       subroutine->sbr_touched,numlocals));
1896                           LOGNL; LOGFLUSH;
1897
1898                           /* XXX reach blocks after JSR statements */
1899                           for (i=0; i<block_count; ++i) {
1900                               tbptr = block + i;
1901                               LOG1("block L%03d",tbptr->debug_nr);
1902                               if (tbptr->iinstr[tbptr->icount - 1].opc != ICMD_JSR)
1903                                   continue;
1904                               LOG("ends with JSR");
1905                               if ((basicblock*) tbptr->iinstr[tbptr->icount - 1].target != subroutine->target)
1906                                   continue;
1907                               tbptr++;
1908
1909                               LOG1("RET reaches block L%03d",tbptr->debug_nr);
1910
1911                               /*TYPECHECK_REACH(REACH_RET);*/
1912                           }
1913 #endif
1914                           
1915                           superblockend = true;
1916                           break;
1917                                                           
1918                           /****************************************/
1919                           /* INVOKATIONS                          */
1920
1921                       case ICMD_INVOKEVIRTUAL:
1922                       case ICMD_INVOKESPECIAL:
1923                       case ICMD_INVOKESTATIC:
1924                       case ICMD_INVOKEINTERFACE:
1925                           {
1926                               methodinfo *mi = (methodinfo*) iptr->val.a;
1927                                                           bool specialmethod = (mi->name->text[0] == '<');
1928                               bool callinginit = (opcode == ICMD_INVOKESPECIAL && mi->name == name_init);
1929                               instruction *ins;
1930                               classinfo *initclass;
1931
1932                                                           if (specialmethod && !callinginit)
1933                                                                   panic("Invalid invocation of special method");
1934
1935                                                           if (opcode == ICMD_INVOKESPECIAL) {
1936                                                                   /* XXX for INVOKESPECIAL: check if the invokation is done at all */
1937                                                                   
1938                                                                   /* (If callinginit the class is checked later.) */
1939                                                                   if (!callinginit) { 
1940                                                                           if (!builtin_isanysubclass(class,mi->class)) 
1941                                                                                   panic("Illegal instruction: INVOKESPECIAL calling non-superclass method"); 
1942                                                                   } 
1943                                                           }
1944
1945                               /* fetch parameter types and return type */
1946                               /* XXX might use dst->typeinfo directly if non void */
1947                               i = 0;
1948                               if (opcode != ICMD_INVOKESTATIC) {
1949                                   ptype[0] = TYPE_ADR;
1950                                   TYPEINFO_INIT_CLASSINFO(pinfo[0],mi->class);
1951                                   i++;
1952                               }
1953                               typeinfo_init_from_method_args(mi->descriptor,ptype+i,pinfo+i,
1954                                                              MAXPARAMS-i,false,
1955                                                              &rtype,&rinfo);
1956
1957                               /* check parameter types */
1958                               srcstack = curstack;
1959                               i = mi->paramcount; /* number of parameters including 'this'*/
1960                               while (--i >= 0) {
1961                                   LOG1("param %d",i);
1962                                   if (srcstack->type != ptype[i])
1963                                       panic("Parameter type mismatch in method invocation");
1964                                   if (srcstack->type == TYPE_ADR) {
1965                                       LOGINFO(&(srcstack->typeinfo));
1966                                       LOGINFO(pinfo + i);
1967                                       if (i==0 && callinginit)
1968                                       {
1969                                                                                   /* typeinfo tempinfo; */
1970                                                                                   
1971                                           /* first argument to <init> method */
1972                                           if (!TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo))
1973                                               panic("Calling <init> on initialized object");
1974                                           
1975                                           /* get the address of the NEW instruction */
1976                                           LOGINFO(&(srcstack->typeinfo));
1977                                           ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(srcstack->typeinfo);
1978                                           initclass = (ins) ? (classinfo*)ins[-1].val.a : method->class;
1979                                           LOGSTR("class: "); LOGSTRu(initclass->name); LOGNL;
1980
1981                                                                                   /* check type */
1982                                                                                   /* (This is checked below.) */
1983 /*                                                                                TYPEINFO_INIT_CLASSINFO(tempinfo,initclass); */
1984 /*                                           if (!typeinfo_is_assignable(&tempinfo,pinfo+0)) */
1985 /*                                               panic("Parameter reference type mismatch in <init> invocation"); */
1986                                       }
1987                                       else {
1988                                           if (!typeinfo_is_assignable(&(srcstack->typeinfo),pinfo+i))
1989                                               panic("Parameter reference type mismatch in method invocation");
1990                                       }
1991                                   }
1992                                   LOG("ok");
1993
1994                                   if (i) srcstack = srcstack->prev;
1995                               }
1996
1997                                                           /* XXX We should resolve the method and pass its
1998                                                            * class as implementingclass to is_accessible. */
1999                                                           if (!is_accessible(mi->flags,mi->class,NULL,
2000                                                                                                  (opcode == ICMD_INVOKESTATIC) ? NULL
2001                                                                                                  : &(srcstack->typeinfo)))
2002                                                                   panic("Invoking unaccessible method");
2003
2004                                                           LOG("checking return type");
2005                               if (rtype != TYPE_VOID) {
2006                                   if (rtype != dst->type)
2007                                       panic("Return type mismatch in method invocation");
2008                                   TYPEINFO_COPY(rinfo,dst->typeinfo);
2009                               }
2010
2011                               if (callinginit) {
2012                                                                   LOG("replacing uninitialized object");
2013                                   /* replace uninitialized object type on stack */
2014                                   srcstack = dst;
2015                                   while (srcstack) {
2016                                       if (srcstack->type == TYPE_ADR
2017                                           && TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo)
2018                                           && TYPEINFO_NEWOBJECT_INSTRUCTION(srcstack->typeinfo) == ins)
2019                                       {
2020                                           LOG("replacing uninitialized type on stack");
2021                                           TYPEINFO_INIT_CLASSINFO(srcstack->typeinfo,initclass);
2022                                       }
2023                                       srcstack = srcstack->prev;
2024                                   }
2025                                   /* replace uninitialized object type in locals */
2026                                                                   typevectorset_init_object(localset,ins,initclass,numlocals);
2027
2028                                   /* initializing the 'this' reference? */
2029                                   if (!ins) {
2030 #ifdef TYPECHECK_DEBUG
2031                                                                           if (!initmethod)
2032                                                                                   panic("Internal error: calling <init> on this in non-<init> method.");
2033 #endif
2034                                                                           /* must be <init> of current class or direct superclass */
2035                                                                           if (mi->class != class && mi->class != class->super)
2036                                                                                   panic("<init> calling <init> of the wrong class");
2037                                                                           
2038                                       /* set our marker variable to type int */
2039                                       LOG("setting <init> marker");
2040                                                                           typevectorset_store(localset,numlocals-1,TYPE_INT,NULL);
2041                                   }
2042                                                                   else {
2043                                                                           /* initializing an instance created with NEW */
2044                                                                           /* XXX is this strictness ok? */
2045                                                                           if (mi->class != initclass)
2046                                                                                   panic("Calling <init> method of the wrong class");
2047                                                                   }
2048                               }
2049                           }
2050                           maythrow = true;
2051                           break;
2052                           
2053                       case ICMD_MULTIANEWARRAY:
2054                                                   {
2055                                                           vftbl *arrayvftbl;
2056                                                           arraydescriptor *desc;
2057                                                           
2058                                                           /* check the array lengths on the stack */
2059                                                           i = iptr[0].op1;
2060                                                           if (i<1) panic("MULTIANEWARRAY with dimensions < 1");
2061                                                           srcstack = curstack;
2062                                                           while (i--) {
2063                                                                   if (!srcstack)
2064                                                                           panic("MULTIANEWARRAY missing array length");
2065                                                                   if (srcstack->type != TYPE_INT)
2066                                                                           panic("MULTIANEWARRAY using non-int as array length");
2067                                                                   srcstack = srcstack->prev;
2068                                                           }
2069                                                           
2070                                                           /* check array descriptor */
2071                                                           arrayvftbl = (vftbl*) iptr[0].val.a;
2072                                                           if (!arrayvftbl)
2073                                                                   panic("MULTIANEWARRAY with unlinked class");
2074                                                           if ((desc = arrayvftbl->arraydesc) == NULL)
2075                                                                   panic("MULTIANEWARRAY with non-array class");
2076                                                           if (desc->dimension < iptr[0].op1)
2077                                                                   panic("MULTIANEWARRAY dimension to high");
2078                                                           
2079                                                           /* set the array type of the result */
2080                                                           TYPEINFO_INIT_CLASSINFO(dst->typeinfo,arrayvftbl->class);
2081                                                   }
2082                           maythrow = true;
2083                           break;
2084                           
2085                       case ICMD_BUILTIN3:
2086                           if (ISBUILTIN(BUILTIN_aastore)) {
2087                                                           TYPECHECK_ADR(curstack);
2088                                                           TYPECHECK_INT(curstack->prev);
2089                                                           TYPECHECK_ADR(curstack->prev->prev);
2090                               if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(curstack->prev->prev->typeinfo))
2091                                   panic("illegal instruction: AASTORE to non-reference array");
2092
2093                               /* XXX optimize */
2094                               /*
2095                                 typeinfo_init_component(&curstack->prev->prev->typeinfo,&tempinfo);
2096                                 if (!typeinfo_is_assignable(&curstack->typeinfo,&tempinfo))
2097                                 panic("illegal instruction: AASTORE to incompatible type");
2098                               */
2099                           }
2100                                                   else {
2101                                                           /* XXX put these checks in a function */
2102                                                           builtindesc = builtin_desc;
2103                                                           while (builtindesc->opcode && builtindesc->builtin
2104                                                                          != (functionptr) iptr->val.a) builtindesc++;
2105                                                           if (!builtindesc->opcode) {
2106                                                                   dolog("Builtin not in table: %s",icmd_builtin_name((functionptr) iptr->val.a));
2107                                                                   panic("Internal error: builtin not found in table");
2108                                                           }
2109                                                           TYPECHECK_ARGS3(builtindesc->type_s3,builtindesc->type_s2,builtindesc->type_s1);
2110                                                   }
2111                           maythrow = true; /* XXX better safe than sorry */
2112                           break;
2113                           
2114                       case ICMD_BUILTIN2:
2115                           if (ISBUILTIN(BUILTIN_newarray))
2116                           {
2117                                                           vftbl *vft;
2118                                                           TYPECHECK_INT(curstack->prev);
2119                               if (iptr[-1].opc != ICMD_ACONST)
2120                                   panic("illegal instruction: builtin_newarray without classinfo");
2121                                                           vft = (vftbl *)iptr[-1].val.a;
2122                                                           if (!vft)
2123                                                                   panic("ANEWARRAY with unlinked class");
2124                                                           if (!vft->arraydesc)
2125                                                                   panic("ANEWARRAY with non-array class");
2126                               TYPEINFO_INIT_CLASSINFO(dst->typeinfo,vft->class);
2127                           }
2128                           else if (ISBUILTIN(BUILTIN_arrayinstanceof))
2129                           {
2130                                                           vftbl *vft;
2131                                                           TYPECHECK_ADR(curstack->prev);
2132                               if (iptr[-1].opc != ICMD_ACONST)
2133                                   panic("illegal instruction: builtin_arrayinstanceof without classinfo");
2134                                                           vft = (vftbl *)iptr[-1].val.a;
2135                                                           if (!vft)
2136                                                                   panic("INSTANCEOF with unlinked class");
2137                                                           if (!vft->arraydesc)
2138                                                                   panic("internal error: builtin_arrayinstanceof with non-array class");
2139                                                   }
2140                           else if (ISBUILTIN(BUILTIN_checkarraycast)) {
2141                                                           vftbl *vft;
2142                                                           TYPECHECK_ADR(curstack->prev);
2143                               if (iptr[-1].opc != ICMD_ACONST)
2144                                   panic("illegal instruction: BUILTIN_checkarraycast without classinfo");
2145                                                           vft = (vftbl *)iptr[-1].val.a;
2146                                                           if (!vft)
2147                                                                   panic("CHECKCAST with unlinked class");
2148                                                           if (!vft->arraydesc)
2149                                                                   panic("internal error: builtin_checkarraycast with non-array class");
2150                               TYPEINFO_INIT_CLASSINFO(dst->typeinfo,vft->class);
2151                           }
2152                                                   else {
2153                                                           builtindesc = builtin_desc;
2154                                                           while (builtindesc->opcode && builtindesc->builtin
2155                                                                          != (functionptr) iptr->val.a) builtindesc++;
2156                                                           if (!builtindesc->opcode) {
2157                                                                   dolog("Builtin not in table: %s",icmd_builtin_name((functionptr) iptr->val.a));
2158                                                                   panic("Internal error: builtin not found in table");
2159                                                           }
2160                                                           TYPECHECK_ARGS2(builtindesc->type_s2,builtindesc->type_s1);
2161                                                   }
2162                           maythrow = true; /* XXX better safe than sorry */
2163                           break;
2164                           
2165                       case ICMD_BUILTIN1:
2166                           if (ISBUILTIN(BUILTIN_new)) {
2167                                                           
2168                               if (iptr[-1].opc != ICMD_ACONST)
2169                                   panic("illegal instruction: builtin_new without classinfo");
2170                                                           cls = (classinfo *) iptr[-1].val.a;
2171                                                           if (!cls->linked)
2172                                                                   panic("Internal error: NEW with unlinked class");
2173                                                           /* The following check also forbids array classes and interfaces: */
2174                                                           if ((cls->flags & ACC_ABSTRACT) != 0)
2175                                                                   panic("Invalid instruction: NEW creating instance of abstract class");
2176                               TYPEINFO_INIT_NEWOBJECT(dst->typeinfo,iptr);
2177                           }
2178                                                   /* XXX unify the following cases? */
2179                           else if (ISBUILTIN(BUILTIN_newarray_boolean)) {
2180                                                           TYPECHECK_INT(curstack);
2181                               TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BOOLEAN);
2182                           }
2183                           else if (ISBUILTIN(BUILTIN_newarray_char)) {
2184                                                           TYPECHECK_INT(curstack);
2185                               TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_CHAR);
2186                           }
2187                           else if (ISBUILTIN(BUILTIN_newarray_float)) {
2188                                                           TYPECHECK_INT(curstack);
2189                               TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_FLOAT);
2190                           }
2191                           else if (ISBUILTIN(BUILTIN_newarray_double)) {
2192                                                           TYPECHECK_INT(curstack);
2193                               TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_DOUBLE);
2194                           }
2195                           else if (ISBUILTIN(BUILTIN_newarray_byte)) {
2196                                                           TYPECHECK_INT(curstack);
2197                               TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BYTE);
2198                           }
2199                           else if (ISBUILTIN(BUILTIN_newarray_short)) {
2200                                                           TYPECHECK_INT(curstack);
2201                               TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_SHORT);
2202                           }
2203                           else if (ISBUILTIN(BUILTIN_newarray_int)) {
2204                                                           TYPECHECK_INT(curstack);
2205                               TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_INT);
2206                           }
2207                           else if (ISBUILTIN(BUILTIN_newarray_long)) {
2208                                                           TYPECHECK_INT(curstack);
2209                               TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_LONG);
2210                           }
2211                                                   else {
2212                                                           builtindesc = builtin_desc;
2213                                                           while (builtindesc->opcode && builtindesc->builtin
2214                                                                          != (functionptr) iptr->val.a) builtindesc++;
2215                                                           if (!builtindesc->opcode) {
2216                                                                   dolog("Builtin not in table: %s",icmd_builtin_name((functionptr) iptr->val.a));
2217                                                                   panic("Internal error: builtin not found in table");
2218                                                           }
2219                                                           TYPECHECK_ARGS1(builtindesc->type_s1);
2220                                                   }
2221                           maythrow = true; /* XXX better safe than sorry */
2222                           break;
2223                                                      
2224                           /****************************************/
2225                           /* UNCHECKED OPERATIONS                 */
2226
2227                           /* These ops have no input or output to be checked */
2228                           /* (apart from the checks done in analyse_stack).  */
2229                                                 /* XXX only add cases for them in debug mode? */
2230
2231                       case ICMD_NOP:
2232                       case ICMD_POP:
2233                       case ICMD_POP2:
2234                           break;
2235
2236                           /****************************************/
2237                           /* SIMPLE EXCEPTION THROWING TESTS      */
2238
2239                       case ICMD_CHECKASIZE:
2240                                                   /* The argument to CHECKASIZE is typechecked by
2241                                                    * typechecking the array creation instructions. */
2242
2243                                                   /* FALLTHROUGH! */
2244                       case ICMD_NULLCHECKPOP:
2245                                                   /* NULLCHECKPOP just requires that the stack top
2246                                                    * is an address. This is checked in stack.c */
2247                                                   
2248                           maythrow = true;
2249                           break;
2250
2251                           /****************************************/
2252                           /* INSTRUCTIONS WHICH SHOULD HAVE BEEN  */
2253                           /* REPLACED BY OTHER OPCODES            */
2254
2255                       case ICMD_NEW:
2256                       case ICMD_NEWARRAY:
2257                       case ICMD_ANEWARRAY:
2258                       case ICMD_MONITORENTER:
2259                       case ICMD_MONITOREXIT:
2260                       case ICMD_AASTORE:
2261                           /* XXX only check this in debug mode? */
2262                           LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
2263                                                   LOG("Should have been converted to builtin function call.");
2264                           panic("Internal error: unexpected instruction encountered");
2265                           break;
2266                                                      
2267                       case ICMD_READONLY_ARG:
2268                       case ICMD_CLEAR_ARGREN:
2269                           /* XXX only check this in debug mode? */
2270                           LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
2271                                                   LOG("Should have been replaced in stack.c.");
2272                           panic("Internal error: unexpected pseudo instruction encountered");
2273                           break;
2274                                                   
2275                           /****************************************/
2276                           /* ARITHMETIC AND CONVERSION            */
2277
2278                                                   /*********************************************
2279                                                    * Instructions below...
2280                                                    *     *) don't operate on local variables,
2281                                                    *     *) don't operate on references,
2282                                                    *     *) don't operate on returnAddresses.
2283                                                    *
2284                                                    * (These instructions are typechecked in
2285                                                    *  analyse_stack.)
2286                                                    ********************************************/
2287
2288                           /* Instructions which may throw a runtime exception: */
2289                           
2290                       case ICMD_IDIV:
2291                       case ICMD_IREM:
2292                       case ICMD_LDIV:
2293                       case ICMD_LREM:
2294                           
2295                           maythrow = true;
2296                           break;
2297                           
2298                           /* Instructions which never throw a runtime exception: */
2299                           /* XXX only add cases for them in debug mode? */
2300                           
2301                       case ICMD_ICONST:
2302                       case ICMD_LCONST:
2303                       case ICMD_FCONST:
2304                       case ICMD_DCONST:
2305
2306                       case ICMD_IFEQ_ICONST:
2307                       case ICMD_IFNE_ICONST:
2308                       case ICMD_IFLT_ICONST:
2309                       case ICMD_IFGE_ICONST:
2310                       case ICMD_IFGT_ICONST:
2311                       case ICMD_IFLE_ICONST:
2312                       case ICMD_ELSE_ICONST:
2313
2314                       case ICMD_IADD:
2315                       case ICMD_ISUB:
2316                       case ICMD_IMUL:
2317                       case ICMD_INEG:
2318                       case ICMD_IAND:
2319                       case ICMD_IOR:
2320                       case ICMD_IXOR:
2321                       case ICMD_ISHL:
2322                       case ICMD_ISHR:
2323                       case ICMD_IUSHR:
2324                       case ICMD_LADD:
2325                       case ICMD_LSUB:
2326                       case ICMD_LMUL:
2327                       case ICMD_LNEG:
2328                       case ICMD_LAND:
2329                       case ICMD_LOR:
2330                       case ICMD_LXOR:
2331                       case ICMD_LSHL:
2332                       case ICMD_LSHR:
2333                       case ICMD_LUSHR:
2334                       case ICMD_IREM0X10001:
2335                       case ICMD_LREM0X10001:
2336                       case ICMD_IDIVPOW2:
2337                       case ICMD_LDIVPOW2:
2338                       case ICMD_IADDCONST:
2339                       case ICMD_ISUBCONST:
2340                       case ICMD_IMULCONST:
2341                       case ICMD_IANDCONST:
2342                       case ICMD_IORCONST:
2343                       case ICMD_IXORCONST:
2344                       case ICMD_ISHLCONST:
2345                       case ICMD_ISHRCONST:
2346                       case ICMD_IUSHRCONST:
2347                       case ICMD_IREMPOW2:
2348                       case ICMD_LADDCONST:
2349                       case ICMD_LSUBCONST:
2350                       case ICMD_LMULCONST:
2351                       case ICMD_LANDCONST:
2352                       case ICMD_LORCONST:
2353                       case ICMD_LXORCONST:
2354                       case ICMD_LSHLCONST:
2355                       case ICMD_LSHRCONST:
2356                       case ICMD_LUSHRCONST:
2357                       case ICMD_LREMPOW2:
2358                           
2359                       case ICMD_I2L:
2360                       case ICMD_I2F:
2361                       case ICMD_I2D:
2362                       case ICMD_L2I:
2363                       case ICMD_L2F:
2364                       case ICMD_L2D:
2365                       case ICMD_F2I:
2366                       case ICMD_F2L:
2367                       case ICMD_F2D:
2368                       case ICMD_D2I:
2369                       case ICMD_D2L:
2370                       case ICMD_D2F:
2371                       case ICMD_INT2BYTE:
2372                       case ICMD_INT2CHAR:
2373                       case ICMD_INT2SHORT:
2374
2375                       case ICMD_LCMP:
2376                       case ICMD_LCMPCONST:
2377                       case ICMD_FCMPL:
2378                       case ICMD_FCMPG:
2379                       case ICMD_DCMPL:
2380                       case ICMD_DCMPG:
2381                           
2382                       case ICMD_FADD:
2383                       case ICMD_DADD:
2384                       case ICMD_FSUB:
2385                       case ICMD_DSUB:
2386                       case ICMD_FMUL:
2387                       case ICMD_DMUL:
2388                       case ICMD_FDIV:
2389                       case ICMD_DDIV:
2390                       case ICMD_FREM:
2391                       case ICMD_DREM:
2392                       case ICMD_FNEG:
2393                       case ICMD_DNEG:
2394
2395                           break;
2396                           
2397                           /****************************************/
2398
2399                       default:
2400                           LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
2401                           panic("Missing ICMD code during typecheck");
2402                                         }
2403
2404                     /* the output of this instruction becomes the current stack */
2405                     curstack = dst;
2406                     
2407                     /* reach exception handlers for this instruction */
2408                     if (maythrow) {
2409                         LOG("reaching exception handlers");
2410                         i = 0;
2411                         while (handlers[i]) {
2412                             tbptr = handlers[i]->handler;
2413                                                         repeat |= typestate_reach(localbuf,bptr,tbptr,
2414                                                                                                           tbptr->instack,localset,numlocals);
2415                             i++;
2416                         }
2417                     }
2418
2419                     /*
2420                       DOLOG(typeinfo_print_block(get_logfile(),curstack,numlocals,vtype,vinfo,(jsrchain) ? touched : NULL));
2421                       LOGNL; LOGFLUSH;
2422                     */
2423                     
2424                     iptr++;
2425                 } /* while instructions */
2426
2427                 LOG("instructions done");
2428                 LOGSTR("RESULT=> ");
2429                 DOLOG(typestate_print(get_logfile(),curstack,localset,numlocals));
2430                 LOGNL; LOGFLUSH;
2431                 
2432                 /* propagate stack and variables to the following block */
2433                 if (!superblockend) {
2434                     LOG("reaching following block");
2435                     tbptr = bptr + 1;
2436                     while (tbptr->flags == BBDELETED) {
2437                         tbptr++;
2438 #ifdef TYPECHECK_DEBUG
2439                         if ((tbptr-block) >= block_count)
2440                             panic("Control flow falls off the last block");
2441 #endif
2442                     }
2443                     TYPECHECK_REACH(REACH_STD);
2444                 }
2445                 
2446             } /* if block has to be checked */
2447             bptr++;
2448         } /* while blocks */
2449         
2450         LOGIF(repeat,"repeat=true");
2451     } while (repeat);
2452
2453 #ifdef TYPECHECK_STATISTICS
2454         dolog("Typechecker did %4d iterations",count_iterations);
2455 #endif
2456
2457 #ifdef TYPECHECK_DEBUG
2458         for (i=0; i<block_count; ++i) {
2459                 if (block[i].flags != BBDELETED
2460                         && block[i].flags != BBUNDEF
2461                         && block[i].flags != BBFINISHED
2462                         && block[i].flags != BBTYPECHECK_UNDEF) /* typecheck may never reach
2463                                                                                                          * some exception handlers,
2464                                                                                                          * that's ok. */
2465                 {
2466                         LOG2("block L%03d has invalid flags after typecheck: %d",
2467                                  block[i].debug_nr,block[i].flags);
2468                         panic("Invalid block flags after typecheck");
2469                 }
2470         }
2471 #endif
2472         
2473         /* Reset blocks we never reached */
2474         for (i=0; i<block_count; ++i) {
2475                 if (block[i].flags == BBTYPECHECK_UNDEF)
2476                         block[i].flags = BBFINISHED;
2477         }
2478                 
2479     LOGimp("exiting typecheck");
2480 }
2481
2482 #undef COPYTYPE
2483
2484 #endif /* CACAO_TYPECHECK */
2485
2486 /*
2487  * These are local overrides for various environment variables in Emacs.
2488  * Please do not remove this and leave it at the end of the file, where
2489  * Emacs will automagically detect them.
2490  * ---------------------------------------------------------------------
2491  * Local variables:
2492  * mode: c
2493  * indent-tabs-mode: t
2494  * c-basic-offset: 4
2495  * tab-width: 4
2496  * End:
2497  */