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