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