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