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