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