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