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