1 /* jit/typecheck.c - typechecking (part of bytecode verification)
3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5 M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6 P. Tomsich, J. Wenninger
8 This file is part of CACAO.
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.
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.
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
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Edwin Steiner
29 $Id: typecheck.c 1510 2004-11-17 11:33:44Z twisti $
33 #include "global.h" /* must be here because of CACAO_TYPECHECK */
35 #ifdef CACAO_TYPECHECK
45 #include "jit/stack.h"
46 #include "toolbox/logging.h"
47 #include "toolbox/memory.h"
50 /****************************************************************************/
52 /****************************************************************************/
54 #ifdef TYPECHECK_VERBOSE_OPT
55 bool typecheckverbose = false;
56 #define DOLOG(action) do { if (typecheckverbose) {action;} } while(0)
61 #ifdef TYPECHECK_VERBOSE
62 #define TYPECHECK_VERBOSE_IMPORTANT
63 #define LOG(str) DOLOG(log_text(str))
64 #define LOG1(str,a) DOLOG(dolog(str,a))
65 #define LOG2(str,a,b) DOLOG(dolog(str,a,b))
66 #define LOG3(str,a,b,c) DOLOG(dolog(str,a,b,c))
67 #define LOGIF(cond,str) DOLOG(do {if (cond) log_text(str);} while(0))
68 #define LOGINFO(info) DOLOG(do {typeinfo_print_short(get_logfile(),(info));log_plain("\n");} while(0))
69 #define LOGFLUSH DOLOG(fflush(get_logfile()))
70 #define LOGNL DOLOG(log_plain("\n"))
71 #define LOGSTR(str) DOLOG(log_plain(str))
72 #define LOGSTR1(str,a) DOLOG(dolog_plain(str,a))
73 #define LOGSTR2(str,a,b) DOLOG(dolog_plain(str,a,b))
74 #define LOGSTR3(str,a,b,c) DOLOG(dolog_plain(str,a,b,c))
75 #define LOGSTRu(utf) DOLOG(log_plain_utf(utf))
80 #define LOG3(str,a,b,c)
81 #define LOGIF(cond,str)
86 #define LOGSTR1(str,a)
87 #define LOGSTR2(str,a,b)
88 #define LOGSTR3(str,a,b,c)
92 #ifdef TYPECHECK_VERBOSE_IMPORTANT
93 #define LOGimp(str) DOLOG(log_text(str))
94 #define LOGimpSTR(str) DOLOG(log_plain(str))
95 #define LOGimpSTRu(utf) DOLOG(log_plain_utf(utf))
98 #define LOGimpSTR(str)
99 #define LOGimpSTRu(utf)
102 #if defined(TYPECHECK_VERBOSE) || defined(TYPECHECK_VERBOSE_IMPORTANT)
108 typestack_print(FILE *file,stackptr stack)
111 typeinfo_print_stacktype(file,stack->type,&stack->typeinfo);
113 if (stack) fprintf(file," ");
119 typestate_print(FILE *file,stackptr instack,typevector *localset,int size)
121 fprintf(file,"Stack: ");
122 typestack_print(file,instack);
123 fprintf(file," Locals:");
124 typevectorset_print(file,localset,size);
129 /****************************************************************************/
131 /****************************************************************************/
133 #ifdef TYPECHECK_DEBUG
134 /*#define TYPECHECK_STATISTICS*/
137 #ifdef TYPECHECK_STATISTICS
138 #define STAT_ITERATIONS 10
139 #define STAT_BLOCKS 10
140 #define STAT_LOCALS 16
142 static int stat_typechecked = 0;
143 static int stat_typechecked_jsr = 0;
144 static int stat_iterations[STAT_ITERATIONS+1] = { 0 };
145 static int stat_reached = 0;
146 static int stat_copied = 0;
147 static int stat_merged = 0;
148 static int stat_merging_changed = 0;
149 static int stat_backwards = 0;
150 static int stat_blocks[STAT_BLOCKS+1] = { 0 };
151 static int stat_locals[STAT_LOCALS+1] = { 0 };
152 static int stat_ins = 0;
153 static int stat_ins_field = 0;
154 static int stat_ins_invoke = 0;
155 static int stat_ins_primload = 0;
156 static int stat_ins_aload = 0;
157 static int stat_ins_builtin = 0;
158 static int stat_ins_builtin_gen = 0;
159 static int stat_ins_branch = 0;
160 static int stat_ins_switch = 0;
161 static int stat_ins_unchecked = 0;
162 static int stat_handlers_reached = 0;
163 static int stat_savedstack = 0;
165 #define TYPECHECK_COUNT(cnt) (cnt)++
166 #define TYPECHECK_COUNTIF(cond,cnt) do{if(cond) (cnt)++;} while(0)
167 #define TYPECHECK_COUNT_FREQ(array,val,limit) \
169 if ((val) < (limit)) (array)[val]++; \
170 else (array)[limit]++; \
173 static void print_freq(FILE *file,int *array,int limit)
176 for (i=0; i<limit; ++i)
177 fprintf(file," %3d: %8d\n",i,array[i]);
178 fprintf(file," =>%3d: %8d\n",limit,array[limit]);
181 void typecheck_print_statistics(FILE *file) {
182 fprintf(file,"typechecked methods: %8d\n",stat_typechecked);
183 fprintf(file,"methods with JSR : %8d\n",stat_typechecked_jsr);
184 fprintf(file,"reached blocks : %8d\n",stat_reached);
185 fprintf(file,"copied states : %8d\n",stat_copied);
186 fprintf(file,"merged states : %8d\n",stat_merged);
187 fprintf(file,"merging changed : %8d\n",stat_merging_changed);
188 fprintf(file,"backwards branches : %8d\n",stat_backwards);
189 fprintf(file,"handlers reached : %8d\n",stat_handlers_reached);
190 fprintf(file,"saved stack (times): %8d\n",stat_savedstack);
191 fprintf(file,"instructions : %8d\n",stat_ins);
192 fprintf(file," field access : %8d\n",stat_ins_field);
193 fprintf(file," invocations : %8d\n",stat_ins_invoke);
194 fprintf(file," load primitive : %8d\n",stat_ins_primload);
195 fprintf(file," load address : %8d\n",stat_ins_aload);
196 fprintf(file," builtins : %8d\n",stat_ins_builtin);
197 fprintf(file," generic : %8d\n",stat_ins_builtin_gen);
198 fprintf(file," unchecked : %8d\n",stat_ins_unchecked);
199 fprintf(file," branches : %8d\n",stat_ins_branch);
200 fprintf(file," switches : %8d\n",stat_ins_switch);
201 fprintf(file,"iterations used:\n");
202 print_freq(file,stat_iterations,STAT_ITERATIONS);
203 fprintf(file,"basic blocks per method / 10:\n");
204 print_freq(file,stat_blocks,STAT_BLOCKS);
205 fprintf(file,"locals:\n");
206 print_freq(file,stat_locals,STAT_LOCALS);
211 #define TYPECHECK_COUNT(cnt)
212 #define TYPECHECK_COUNTIF(cond,cnt)
213 #define TYPECHECK_COUNT_FREQ(array,val,limit)
216 /****************************************************************************/
217 /* TYPESTACK FUNCTIONS */
218 /****************************************************************************/
220 #define TYPESTACK_IS_RETURNADDRESS(sptr) \
221 TYPE_IS_RETURNADDRESS((sptr)->type,(sptr)->typeinfo)
223 #define TYPESTACK_IS_REFERENCE(sptr) \
224 TYPE_IS_REFERENCE((sptr)->type,(sptr)->typeinfo)
226 #define TYPESTACK_RETURNADDRESSSET(sptr) \
227 ((typeinfo_retaddr_set*)TYPEINFO_RETURNADDRESS((sptr)->typeinfo))
229 #define RETURNADDRESSSET_SEEK(set,pos) \
230 do {int i; for (i=pos;i--;) set=set->alt;} while(0)
232 #define TYPESTACK_COPY(sp,copy) \
233 do {for(; sp; sp=sp->prev, copy=copy->prev) { \
234 copy->type = sp->type; \
235 TYPEINFO_COPY(sp->typeinfo,copy->typeinfo); \
239 typestack_copy(stackptr dst,stackptr y,typevector *selected)
242 typeinfo_retaddr_set *sety;
243 typeinfo_retaddr_set *new;
244 typeinfo_retaddr_set **next;
247 for (;dst; dst=dst->prev, y=y->prev) {
248 if (!y) panic("Stack depth mismatch 1");
249 if (dst->type != y->type)
250 panic("Stack type mismatch 1");
251 LOG3("copy %p -> %p (type %d)",y,dst,dst->type);
252 if (dst->type == TYPE_ADDRESS) {
253 if (TYPEINFO_IS_PRIMITIVE(y->typeinfo)) {
254 /* We copy the returnAddresses from the selected
257 LOG("copying returnAddress");
258 sety = TYPESTACK_RETURNADDRESSSET(y);
260 for (k=0,sel=selected; sel; sel=sel->alt) {
261 LOG1("selected k=%d",sel->k);
266 *next = DNEW(typeinfo_retaddr_set);
267 (*next)->addr = sety->addr;
268 next = &((*next)->alt);
271 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,new);
274 TYPEINFO_CLONE(y->typeinfo,dst->typeinfo);
278 if (y) panic("Stack depth mismatch 2");
282 typestack_put_retaddr(stackptr dst,void *retaddr,typevector *loc)
284 #ifdef TYPECHECK_DEBUG
285 if (dst->type != TYPE_ADDRESS)
286 panic("Internal error: Storing returnAddress in non-address slot");
289 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,NULL);
290 for (;loc; loc=loc->alt) {
291 typeinfo_retaddr_set *set = DNEW(typeinfo_retaddr_set);
293 set->alt = TYPESTACK_RETURNADDRESSSET(dst);
294 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,set);
299 typestack_collapse(stackptr dst)
301 for (; dst; dst = dst->prev) {
302 if (TYPESTACK_IS_RETURNADDRESS(dst))
303 TYPESTACK_RETURNADDRESSSET(dst)->alt = NULL;
308 typestack_merge(stackptr dst,stackptr y)
310 bool changed = false;
311 for (; dst; dst = dst->prev, y=y->prev) {
313 panic("Stack depth mismatch 3");
314 if (dst->type != y->type) panic("Stack type mismatch 2");
315 if (dst->type == TYPE_ADDRESS) {
316 if (TYPEINFO_IS_PRIMITIVE(dst->typeinfo)) {
317 /* dst has returnAddress type */
318 if (!TYPEINFO_IS_PRIMITIVE(y->typeinfo))
319 panic("Merging returnAddress with reference");
322 /* dst has reference type */
323 if (TYPEINFO_IS_PRIMITIVE(y->typeinfo))
324 panic("Merging reference with returnAddress");
325 changed |= typeinfo_merge(&(dst->typeinfo),&(y->typeinfo));
329 if (y) panic("Stack depth mismatch 4");
334 typestack_add(stackptr dst,stackptr y,int ky)
336 typeinfo_retaddr_set *setd;
337 typeinfo_retaddr_set *sety;
339 for (; dst; dst = dst->prev, y=y->prev) {
340 if (TYPESTACK_IS_RETURNADDRESS(dst)) {
341 setd = TYPESTACK_RETURNADDRESSSET(dst);
342 sety = TYPESTACK_RETURNADDRESSSET(y);
343 RETURNADDRESSSET_SEEK(sety,ky);
346 setd->alt = DNEW(typeinfo_retaddr_set);
347 setd->alt->addr = sety->addr;
348 setd->alt->alt = NULL;
353 /* 'a' and 'b' are assumed to have passed typestack_canmerge! */
355 typestack_separable_with(stackptr a,stackptr b,int kb)
357 typeinfo_retaddr_set *seta;
358 typeinfo_retaddr_set *setb;
360 for (; a; a = a->prev, b = b->prev) {
361 #ifdef TYPECHECK_DEBUG
362 if (!b) panic("Internal error: typestack_separable_from: different depth");
364 if (TYPESTACK_IS_RETURNADDRESS(a)) {
365 #ifdef TYPECHECK_DEBUG
366 if (!TYPESTACK_IS_RETURNADDRESS(b))
367 panic("Internal error: typestack_separable_from: unmergable stacks");
369 seta = TYPESTACK_RETURNADDRESSSET(a);
370 setb = TYPESTACK_RETURNADDRESSSET(b);
371 RETURNADDRESSSET_SEEK(setb,kb);
373 for (;seta;seta=seta->alt)
374 if (seta->addr != setb->addr) return true;
377 #ifdef TYPECHECK_DEBUG
378 if (b) panic("Internal error: typestack_separable_from: different depth");
383 /* 'a' and 'b' are assumed to have passed typestack_canmerge! */
385 typestack_separable_from(stackptr a,int ka,stackptr b,int kb)
387 typeinfo_retaddr_set *seta;
388 typeinfo_retaddr_set *setb;
390 for (; a; a = a->prev, b = b->prev) {
391 #ifdef TYPECHECK_DEBUG
392 if (!b) panic("Internal error: typestack_separable_from: different depth");
394 if (TYPESTACK_IS_RETURNADDRESS(a)) {
395 #ifdef TYPECHECK_DEBUG
396 if (!TYPESTACK_IS_RETURNADDRESS(b))
397 panic("Internal error: typestack_separable_from: unmergable stacks");
399 seta = TYPESTACK_RETURNADDRESSSET(a);
400 setb = TYPESTACK_RETURNADDRESSSET(b);
401 RETURNADDRESSSET_SEEK(seta,ka);
402 RETURNADDRESSSET_SEEK(setb,kb);
404 if (seta->addr != setb->addr) return true;
407 #ifdef TYPECHECK_DEBUG
408 if (b) panic("Internal error: typestack_separable_from: different depth");
413 /****************************************************************************/
414 /* TYPESTATE FUNCTIONS */
415 /****************************************************************************/
418 typestate_merge(stackptr deststack,typevector *destloc,
419 stackptr ystack,typevector *yloc,
420 int locsize,bool jsrencountered)
422 typevector *dvec,*yvec;
424 bool changed = false;
427 LOGSTR("dstack: "); DOLOG(typestack_print(get_logfile(),deststack)); LOGNL;
428 LOGSTR("ystack: "); DOLOG(typestack_print(get_logfile(),ystack)); LOGNL;
429 LOGSTR("dloc : "); DOLOG(typevectorset_print(get_logfile(),destloc,locsize)); LOGNL;
430 LOGSTR("yloc : "); DOLOG(typevectorset_print(get_logfile(),yloc,locsize)); LOGNL;
433 /* The stack is always merged. If there are returnAddresses on
434 * the stack they are ignored in this step. */
436 changed |= typestack_merge(deststack,ystack);
439 return typevector_merge(destloc,yloc,locsize);
441 for (yvec=yloc; yvec; yvec=yvec->alt) {
444 /* Check if the typestates (deststack,destloc) will be
445 * separable when (ystack,yvec) is added. */
447 if (!typestack_separable_with(deststack,ystack,ky)
448 && !typevectorset_separable_with(destloc,yvec,locsize))
450 /* No, the resulting set won't be separable, thus we
451 * may merge all states in (deststack,destloc) and
454 typestack_collapse(deststack);
455 typevectorset_collapse(destloc,locsize);
456 typevector_merge(destloc,yvec,locsize);
459 /* Yes, the resulting set will be separable. Thus we check
460 * if we may merge (ystack,yvec) with a single state in
461 * (deststack,destloc). */
463 for (dvec=destloc,kd=0; dvec; dvec=dvec->alt, kd++) {
464 if (!typestack_separable_from(ystack,ky,deststack,kd)
465 && !typevector_separable_from(yvec,dvec,locsize))
467 /* The typestate (ystack,yvec) is not separable from
468 * (deststack,dvec) by any returnAddress. Thus we may
469 * merge the states. */
471 changed |= typevector_merge(dvec,yvec,locsize);
477 /* The typestate (ystack,yvec) is separable from all typestates
478 * (deststack,destloc). Thus we must add this state to the
481 typestack_add(deststack,ystack,ky);
482 typevectorset_add(destloc,yvec,locsize);
491 LOGSTR("dstack: "); DOLOG(typestack_print(get_logfile(),deststack)); LOGNL;
492 LOGSTR("dloc : "); DOLOG(typevectorset_print(get_logfile(),destloc,locsize)); LOGNL;
500 typestate_reach(codegendata *cd, registerdata *rd,void *localbuf,
502 basicblock *destblock,
503 stackptr ystack,typevector *yloc,
504 int locsize,bool jsrencountered)
508 bool changed = false;
510 LOG1("reaching block L%03d",destblock->debug_nr);
511 TYPECHECK_COUNT(stat_reached);
513 destidx = destblock - cd->method->basicblocks;
514 destloc = MGET_TYPEVECTOR(localbuf,destidx,locsize);
516 /* When branching backwards we have to check for uninitialized objects */
518 if (destblock <= current) {
521 #warning FIXME FOR INLINING
523 TYPECHECK_COUNT(stat_backwards);
525 for (sp = ystack; sp; sp=sp->prev)
526 if (sp->type == TYPE_ADR &&
527 TYPEINFO_IS_NEWOBJECT(sp->typeinfo)) {
528 show_icmd_method(cd->method,cd,rd);
529 printf("current: %ld, dest: %ld\n",current->debug_nr,destblock->debug_nr);
530 panic("Branching backwards with uninitialized object on stack");
533 for (i=0; i<locsize; ++i)
534 if (yloc->td[i].type == TYPE_ADR &&
535 TYPEINFO_IS_NEWOBJECT(yloc->td[i].info))
536 panic("Branching backwards with uninitialized object in local variable");
540 if (destblock->flags == BBTYPECHECK_UNDEF) {
541 /* The destblock has never been reached before */
543 TYPECHECK_COUNT(stat_copied);
544 LOG1("block (index %04d) reached first time",destidx);
546 typestack_copy(destblock->instack,ystack,yloc);
547 COPY_TYPEVECTORSET(yloc,destloc,locsize);
551 /* The destblock has already been reached before */
553 TYPECHECK_COUNT(stat_merged);
554 LOG1("block (index %04d) reached before",destidx);
556 changed = typestate_merge(destblock->instack,destloc,
559 TYPECHECK_COUNTIF(changed,stat_merging_changed);
564 destblock->flags = BBTYPECHECK_REACHED;
565 if (destblock <= current) {LOG("REPEAT!"); return true;}
572 typestate_ret(codegendata *cd,registerdata *rd, void *localbuf,
574 stackptr ystack,typevector *yloc,
575 int retindex,int locsize)
578 typevector *selected;
579 basicblock *destblock;
582 for (yvec=yloc; yvec; ) {
583 if (!TYPEDESC_IS_RETURNADDRESS(yvec->td[retindex]))
584 panic("Illegal instruction: RET on non-returnAddress");
586 destblock = (basicblock*) TYPEINFO_RETURNADDRESS(yvec->td[retindex].info);
588 selected = typevectorset_select(&yvec,retindex,destblock);
590 repeat |= typestate_reach(cd, rd, localbuf,current,destblock,
591 ystack,selected,locsize,true);
596 /****************************************************************************/
597 /* HELPER FUNCTIONS */
598 /****************************************************************************/
600 /* If a field is checked, definingclass == implementingclass */
602 is_accessible(int flags,classinfo *definingclass,classinfo *implementingclass, classinfo *methodclass,
605 /* check access rights */
606 if (methodclass != definingclass) {
607 switch (flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED)) {
611 /* In the cases below, definingclass cannot be an interface */
614 if (definingclass->packagename != methodclass->packagename)
618 if (definingclass->packagename != methodclass->packagename) {
619 if (!builtin_isanysubclass(methodclass,implementingclass))
622 /* For protected access of super class members in another
623 * package the instance must be a subclass of or the same
624 * as the current class. */
625 LOG("protected access into other package");
626 implementingclass = methodclass;
630 if (definingclass != methodclass) {
631 LOG("private access");
636 panic("Invalid access flags");
641 if ((flags & ACC_STATIC) != 0) {
642 LOG("accessing STATIC member with instance");
646 if (implementingclass
647 && !TYPEINFO_IS_NULLTYPE(*instance)
648 && !TYPEINFO_IS_NEWOBJECT(*instance))
650 if (!typeinfo_is_assignable_to_classinfo(instance,
653 LOG("instance not assignable");
655 LOGSTRu(implementingclass->name); LOGNL; LOGFLUSH;
661 if ((flags & ACC_STATIC) == 0) {
662 LOG("accessing non-STATIC member without instance");
670 /****************************************************************************/
671 /* MACROS FOR LOCAL VARIABLE CHECKING */
672 /****************************************************************************/
674 #define INDEX_ONEWORD(num) \
675 do { if((num)<0 || (num)>=validlocals) \
676 panic("Invalid local variable index"); } while (0)
677 #define INDEX_TWOWORD(num) \
678 do { if((num)<0 || ((num)+1)>=validlocals) \
679 panic("Invalid local variable index"); } while (0)
681 #define STORE_ONEWORD(num,type) \
682 do {typevectorset_store(localset,num,type,NULL);} while(0)
684 #define STORE_TWOWORD(num,type) \
685 do {typevectorset_store_twoword(localset,num,type);} while(0)
688 #define WORDCHECKFAULT \
690 show_icmd_method(m, cd, rd); \
691 dolog("localset->td index: %ld\ninstruction belongs to:%s.%s, outermethod:%s.%s\n", \
692 iptr->op1,iptr->method->class->name->text, \
693 iptr->method->name->text,m->class->name->text,m->name->text); \
694 show_icmd(iptr++, false); \
695 show_icmd(iptr, false); \
699 #define CHECK_ONEWORD(num,tp) \
700 do {TYPECHECK_COUNT(stat_ins_primload); \
701 if (jsrencountered) { \
702 if (!typevectorset_checktype(localset,num,tp)) { \
704 panic("Variable type mismatch"); \
708 if (localset->td[num].type != tp) { \
709 panic("Variable type mismatch"); \
715 #define CHECK_TWOWORD(num,type) \
716 do {TYPECHECK_COUNT(stat_ins_primload); \
717 if (!typevectorset_checktype(localset,num,type)) { \
719 panic("Variable type mismatch"); \
723 /****************************************************************************/
724 /* MACROS FOR STACK TYPE CHECKING */
725 /****************************************************************************/
727 /* These macros are for basic typechecks which were not done in stack.c */
729 #define TYPECHECK_STACK(sp,tp) \
730 do { if ((sp)->type != (tp)) \
731 panic("Wrong data type on stack"); } while(0)
733 #define TYPECHECK_ADR(sp) TYPECHECK_STACK(sp,TYPE_ADR)
734 #define TYPECHECK_INT(sp) TYPECHECK_STACK(sp,TYPE_INT)
735 #define TYPECHECK_LNG(sp) TYPECHECK_STACK(sp,TYPE_LNG)
736 #define TYPECHECK_FLT(sp) TYPECHECK_STACK(sp,TYPE_FLT)
737 #define TYPECHECK_DBL(sp) TYPECHECK_STACK(sp,TYPE_DBL)
739 #define TYPECHECK_ARGS1(t1) \
740 do {TYPECHECK_STACK(curstack,t1);} while (0)
741 #define TYPECHECK_ARGS2(t1,t2) \
742 do {TYPECHECK_ARGS1(t1); \
743 TYPECHECK_STACK(curstack->prev,t2);} while (0)
744 #define TYPECHECK_ARGS3(t1,t2,t3) \
745 do {TYPECHECK_ARGS2(t1,t2); \
746 TYPECHECK_STACK(curstack->prev->prev,t3);} while (0)
748 /****************************************************************************/
750 /****************************************************************************/
752 #define COPYTYPE(source,dest) \
753 {if ((source)->type == TYPE_ADR) \
754 TYPEINFO_COPY((source)->typeinfo,(dest)->typeinfo);}
756 #define ISBUILTIN(v) (iptr->val.fp == (functionptr) (v))
758 /* TYPECHECK_REACH: executed, when the target block (tbptr) can be reached
759 * from the current block (bptr). The types of local variables and
760 * stack slots are propagated to the target block.
762 * bptr.......current block
763 * tbptr......target block
764 * dst........current output stack pointer
765 * numlocals..number of local variables
766 * localset...current local variable vectorset
767 * localbuf...local variable vectorset buffer
768 * jsrencountered...true if a JSR has been seen
770 * repeat.....changed to true if a block before the current
773 #define TYPECHECK_REACH \
775 repeat |= typestate_reach(cd,rd, localbuf,bptr,tbptr,dst, \
776 localset,numlocals,jsrencountered); \
780 /* TYPECHECK_LEAVE: executed when the method is exited non-abruptly
782 * class........class of the current method
783 * numlocals....number of local variables
784 * localset.....current local variable vectorset
785 * initmethod...true if this is an <init> method
787 #define TYPECHECK_LEAVE \
789 if (initmethod && m->class != class_java_lang_Object) { \
790 /* check the marker variable */ \
791 LOG("Checking <init> marker"); \
792 if (!typevectorset_checktype(localset,numlocals-1,TYPE_INT))\
793 panic("<init> method does not initialize 'this'"); \
797 /****************************************************************************/
799 /****************************************************************************/
801 #define MAXPARAMS 255
803 /* typecheck is called directly after analyse_stack */
805 methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd)
807 int b_count, b_index;
808 stackptr curstack; /* input stack top for current instruction */
809 stackptr srcstack; /* source stack for copying and merging */
810 int opcode; /* current opcode */
811 int i; /* temporary counter */
812 int len; /* for counting instructions, etc. */
813 bool superblockend; /* true if no fallthrough to next block */
814 bool repeat; /* if true, blocks are iterated over again */
815 instruction *iptr; /* pointer to current instruction */
816 basicblock *bptr; /* pointer to current basic block */
817 basicblock *tbptr; /* temporary for target block */
819 int numlocals; /* number of local variables */
820 int validlocals; /* number of valid local variable indices */
821 void *localbuf; /* local variable types for each block start */
822 typevector *localset; /* typevector set for local variables */
823 typevector *lset; /* temporary pointer */
824 typedescriptor *td; /* temporary pointer */
826 stackptr savedstackbuf = NULL; /* buffer for saving the stack */
827 stackptr savedstack = NULL; /* saved instack of current block */
829 stackelement excstack; /* instack for exception handlers */
831 typedescriptor returntype; /* return type of current method */
832 u1 *ptype; /* parameter types of called method */
833 typeinfo *pinfo; /* parameter typeinfos of called method */
834 int rtype; /* return type of called method */
835 typeinfo rinfo; /* typeinfo for return type of called method */
837 stackptr dst; /* output stack of current instruction */
838 basicblock **tptr; /* pointer into target list of switch instr. */
839 exceptiontable **handlers; /* active exception handlers */
840 classinfo *cls; /* temporary */
841 bool maythrow; /* true if this instruction may throw */
842 static utf *name_init; /* "<init>" */
843 bool initmethod; /* true if this is an "<init>" method */
844 builtin_descriptor *builtindesc; /* temp. descriptor of builtin */
845 bool jsrencountered = false; /* true if we there was a JSR */
849 #ifdef TYPECHECK_STATISTICS
850 int count_iterations = 0;
851 TYPECHECK_COUNT(stat_typechecked);
852 TYPECHECK_COUNT_FREQ(stat_locals,m->codegendata->maxlocals,STAT_LOCALS);
853 TYPECHECK_COUNT_FREQ(stat_blocks,m->basicblockcount/10,STAT_BLOCKS);
856 LOGSTR("\n==============================================================================\n");
857 DOLOG(show_icmd_method());
858 LOGSTR("\n==============================================================================\n");
859 LOGimpSTR("Entering typecheck: ");
860 LOGimpSTRu(method->name);
862 LOGimpSTRu(method->descriptor);
863 LOGimpSTR(" (class ");
864 LOGimpSTRu(method->class->name);
869 name_init = utf_new_char("<init>");
870 initmethod = (m->name == name_init);
872 /* Allocate buffer for method arguments */
874 ptype = DMNEW(u1,MAXPARAMS);
875 pinfo = DMNEW(typeinfo,MAXPARAMS);
877 LOG("Buffer allocated.\n");
879 /* reset all BBFINISHED blocks to BBTYPECHECK_UNDEF. */
880 b_count = m->basicblockcount;
881 bptr = m->basicblocks;
882 while (--b_count >= 0) {
883 #ifdef TYPECHECK_DEBUG
884 if (bptr->flags != BBFINISHED && bptr->flags != BBDELETED
885 && bptr->flags != BBUNDEF)
888 LOGSTR1("block flags: %d\n",bptr->flags); LOGFLUSH;
889 panic("Internal error: Unexpected block flags in typecheck()");
892 if (bptr->flags >= BBFINISHED) {
893 bptr->flags = BBTYPECHECK_UNDEF;
898 /* The first block is always reached */
899 if (m->basicblockcount && m->basicblocks[0].flags == BBTYPECHECK_UNDEF)
900 m->basicblocks[0].flags = BBTYPECHECK_REACHED;
902 LOG("Blocks reset.\n");
904 /* number of local variables */
906 /* In <init> methods we use an extra local variable to signal if
907 * the 'this' reference has been initialized. */
908 numlocals = cd->maxlocals;
909 validlocals = numlocals;
910 if (initmethod) numlocals++;
912 /* allocate the buffers for local variables */
913 localbuf = DMNEW_TYPEVECTOR(m->basicblockcount+1, numlocals);
914 localset = MGET_TYPEVECTOR(localbuf,m->basicblockcount,numlocals);
916 LOG("Variable buffer allocated.\n");
918 /* allocate the buffer of active exception handlers */
919 handlers = DMNEW(exceptiontable*, cd->exceptiontablelength + 1);
921 /* initialize the variable types of the first block */
922 /* to the types of the arguments */
923 lset = MGET_TYPEVECTOR(localbuf,0,numlocals);
929 /* if this is an instance method initialize the "this" ref type */
930 if (!(m->flags & ACC_STATIC)) {
932 panic("Not enough local variables for method arguments");
933 td->type = TYPE_ADDRESS;
935 TYPEINFO_INIT_NEWOBJECT(td->info,NULL);
937 TYPEINFO_INIT_CLASSINFO(td->info, m->class);
942 LOG("'this' argument set.\n");
944 /* the rest of the arguments and the return type */
945 i = typedescriptors_init_from_method_args(td, m->descriptor,
947 true, /* two word types use two slots */
950 i = numlocals - (td - lset->td);
952 td->type = TYPE_VOID;
956 LOG("Arguments set.\n");
958 /* initialize the input stack of exception handlers */
959 excstack.prev = NULL;
960 excstack.type = TYPE_ADR;
961 TYPEINFO_INIT_CLASSINFO(excstack.typeinfo,
962 class_java_lang_Throwable); /* changed later */
964 LOG("Exception handler stacks set.\n");
966 /* loop while there are still blocks to be checked */
968 TYPECHECK_COUNT(count_iterations);
972 b_count = m->basicblockcount;
973 bptr = m->basicblocks;
975 while (--b_count >= 0) {
976 LOGSTR1("---- BLOCK %04d, ",bptr-block);
977 LOGSTR1("blockflags: %d\n",bptr->flags);
980 if (bptr->flags == BBTYPECHECK_REACHED) {
981 LOGSTR1("\n---- BLOCK %04d ------------------------------------------------\n",bptr-block);
984 superblockend = false;
985 bptr->flags = BBFINISHED;
986 b_index = bptr - m->basicblocks;
988 /* init stack at the start of this block */
989 curstack = bptr->instack;
991 /* determine the active exception handlers for this block */
992 /* XXX could use a faster algorithm with sorted lists or
995 for (i = 0; i < cd->exceptiontablelength; ++i) {
996 if ((cd->exceptiontable[i].start <= bptr) && (cd->exceptiontable[i].end > bptr)) {
997 LOG1("active handler L%03d", cd->exceptiontable[i].handler->debug_nr);
998 handlers[len++] = cd->exceptiontable + i;
1001 handlers[len] = NULL;
1003 /* init variable types at the start of this block */
1004 COPY_TYPEVECTORSET(MGET_TYPEVECTOR(localbuf,b_index,numlocals),
1005 localset,numlocals);
1006 #if defined(__GNUC__)
1007 #warning FIXME FOR INLINING
1011 for (i=0; i<numlocals; ++i)
1012 if (localset->td[i].type == TYPE_ADR
1013 && TYPEINFO_IS_NEWOBJECT(localset->td[i].info)) {
1014 show_icmd_method(m, cd, rd);
1015 printf("Uninitialized variale:%ld, block:%ld\n",i,bptr->debug_nr);
1016 panic("Uninitialized object in local variable inside try block");
1019 DOLOG(typestate_print(get_logfile(),curstack,localset,numlocals));
1022 /* loop over the instructions */
1024 iptr = bptr->iinstr;
1025 while (--len >= 0) {
1026 TYPECHECK_COUNT(stat_ins);
1027 DOLOG(show_icmd(iptr,false)); LOGNL; LOGFLUSH;
1030 myclass = iptr->method->class;
1036 /****************************************/
1037 /* STACK MANIPULATIONS */
1039 /* We just need to copy the typeinfo */
1040 /* for slots containing addresses. */
1042 /* XXX We assume that the destination stack
1043 * slots were continuously allocated in
1044 * memory. (The current implementation in
1049 COPYTYPE(curstack,dst);
1053 COPYTYPE(curstack,dst);
1054 COPYTYPE(curstack,dst-2);
1055 COPYTYPE(curstack->prev,dst-1);
1059 COPYTYPE(curstack,dst);
1060 COPYTYPE(curstack,dst-3);
1061 COPYTYPE(curstack->prev,dst-1);
1062 COPYTYPE(curstack->prev->prev,dst-2);
1066 COPYTYPE(curstack,dst);
1067 COPYTYPE(curstack->prev,dst-1);
1071 COPYTYPE(curstack,dst);
1072 COPYTYPE(curstack->prev,dst-1);
1073 COPYTYPE(curstack,dst-3);
1074 COPYTYPE(curstack->prev,dst-4);
1075 COPYTYPE(curstack->prev->prev,dst-2);
1079 COPYTYPE(curstack,dst);
1080 COPYTYPE(curstack->prev,dst-1);
1081 COPYTYPE(curstack,dst-4);
1082 COPYTYPE(curstack->prev,dst-5);
1083 COPYTYPE(curstack->prev->prev,dst-2);
1084 COPYTYPE(curstack->prev->prev->prev,dst-3);
1088 COPYTYPE(curstack,dst-1);
1089 COPYTYPE(curstack->prev,dst);
1092 /****************************************/
1102 /* PRIMITIVE VARIABLE ACCESS */
1104 case ICMD_ILOAD: CHECK_ONEWORD(iptr->op1,TYPE_INT); break;
1105 case ICMD_FLOAD: CHECK_ONEWORD(iptr->op1,TYPE_FLOAT); break;
1106 case ICMD_IINC: CHECK_ONEWORD(iptr->op1,TYPE_INT); break;
1107 case ICMD_LLOAD: CHECK_TWOWORD(iptr->op1,TYPE_LONG); break;
1108 case ICMD_DLOAD: CHECK_TWOWORD(iptr->op1,TYPE_DOUBLE); break;
1110 case ICMD_FSTORE: STORE_ONEWORD(iptr->op1,TYPE_FLOAT); break;
1111 case ICMD_ISTORE: STORE_ONEWORD(iptr->op1,TYPE_INT); break;
1112 case ICMD_LSTORE: STORE_TWOWORD(iptr->op1,TYPE_LONG); break;
1113 case ICMD_DSTORE: STORE_TWOWORD(iptr->op1,TYPE_DOUBLE); break;
1115 /****************************************/
1116 /* LOADING ADDRESS FROM VARIABLE */
1119 TYPECHECK_COUNT(stat_ins_aload);
1121 /* loading a returnAddress is not allowed */
1122 if (jsrencountered) {
1123 if (!typevectorset_checkreference(localset,iptr->op1))
1124 panic("illegal instruction: ALOAD loading non-reference");
1126 typevectorset_copymergedtype(localset,iptr->op1,&(dst->typeinfo));
1129 if (!TYPEDESC_IS_REFERENCE(localset->td[iptr->op1])) {
1130 show_icmd_method(m, cd, rd);
1131 dolog("localset->td index: %ld\ninstruction belongs to:%s.%s, outermethod:%s.%s\n",
1132 iptr->op1,iptr->method->class->name->text,
1133 iptr->method->name->text,m->class->name->text,m->name->text);
1134 show_icmd(iptr, false);
1135 panic("illegal instruction: ALOAD loading non-reference");
1137 TYPEINFO_COPY(localset->td[iptr->op1].info,dst->typeinfo);
1141 /****************************************/
1142 /* STORING ADDRESS TO VARIABLE */
1146 TYPEINFO_IS_NEWOBJECT(curstack->typeinfo))
1147 panic("Storing uninitialized object in local variable inside try block");
1149 if (TYPESTACK_IS_RETURNADDRESS(curstack))
1150 typevectorset_store_retaddr(localset,iptr->op1,&(curstack->typeinfo));
1152 typevectorset_store(localset,iptr->op1,TYPE_ADDRESS,
1153 &(curstack->typeinfo));
1156 /****************************************/
1157 /* LOADING ADDRESS FROM ARRAY */
1160 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(curstack->prev->typeinfo))
1161 panic("illegal instruction: AALOAD on non-reference array");
1163 typeinfo_init_component(&curstack->prev->typeinfo,&dst->typeinfo);
1167 /****************************************/
1171 TYPECHECK_COUNT(stat_ins_field);
1172 if (!TYPEINFO_IS_REFERENCE(curstack->prev->typeinfo))
1173 panic("illegal instruction: PUTFIELD on non-reference");
1174 if (TYPEINFO_IS_ARRAY(curstack->prev->typeinfo))
1175 panic("illegal instruction: PUTFIELD on array");
1177 /* check if the value is assignable to the field */
1179 fieldinfo *fi = (fieldinfo*) iptr[0].val.a;
1181 if (TYPEINFO_IS_NEWOBJECT(curstack->prev->typeinfo)) {
1183 && !TYPEINFO_NEWOBJECT_INSTRUCTION(curstack->prev->typeinfo))
1185 /* uninitialized "this" instance */
1186 if (fi->class != m->class || (fi->flags & ACC_STATIC) != 0)
1187 panic("Setting unaccessible field in uninitialized object");
1190 panic("PUTFIELD on uninitialized object");
1194 if (!is_accessible(fi->flags,fi->class,fi->class, myclass,
1195 &(curstack->prev->typeinfo)))
1196 panic("PUTFIELD: field is not accessible");
1199 if (curstack->type != fi->type)
1200 panic("PUTFIELD type mismatch");
1201 if (fi->type == TYPE_ADR) {
1202 TYPEINFO_INIT_FROM_FIELDINFO(rinfo,fi);
1203 if (!typeinfo_is_assignable(&(curstack->typeinfo),
1205 panic("PUTFIELD reference type not assignable");
1211 case ICMD_PUTSTATIC:
1212 TYPECHECK_COUNT(stat_ins_field);
1213 /* check if the value is assignable to the field */
1215 fieldinfo *fi = (fieldinfo*) iptr[0].val.a;
1217 if (!is_accessible(fi->flags,fi->class,fi->class,myclass,NULL))
1218 panic("PUTSTATIC: field is not accessible");
1220 if (curstack->type != fi->type)
1221 panic("PUTSTATIC type mismatch");
1222 if (fi->type == TYPE_ADR) {
1223 TYPEINFO_INIT_FROM_FIELDINFO(rinfo,fi);
1224 if (!typeinfo_is_assignable(&(curstack->typeinfo),
1226 panic("PUTSTATIC reference type not assignable");
1233 TYPECHECK_COUNT(stat_ins_field);
1234 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1235 panic("illegal instruction: GETFIELD on non-reference");
1236 if (TYPEINFO_IS_ARRAY(curstack->typeinfo))
1237 panic("illegal instruction: GETFIELD on array");
1240 fieldinfo *fi = (fieldinfo *)(iptr->val.a);
1242 if (!is_accessible(fi->flags,fi->class,fi->class,myclass,
1243 &(curstack->typeinfo)))
1244 panic("GETFIELD: field is not accessible");
1246 if (dst->type == TYPE_ADR) {
1247 TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi);
1253 case ICMD_GETSTATIC:
1254 TYPECHECK_COUNT(stat_ins_field);
1256 fieldinfo *fi = (fieldinfo *)(iptr->val.a);
1258 if (!is_accessible(fi->flags,fi->class,fi->class,myclass,NULL)) {
1259 printf("---------\n");
1260 utf_display(fi->class->name);
1262 utf_display(myclass->name);
1266 panic("GETSTATIC: field is not accessible");
1269 if (dst->type == TYPE_ADR) {
1270 TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi);
1276 /****************************************/
1277 /* PRIMITIVE ARRAY ACCESS */
1279 case ICMD_ARRAYLENGTH:
1280 if (!TYPEINFO_MAYBE_ARRAY(curstack->typeinfo)
1281 && curstack->typeinfo.typeclass != pseudo_class_Arraystub)
1282 panic("illegal instruction: ARRAYLENGTH on non-array");
1287 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_BOOLEAN)
1288 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_BYTE))
1289 panic("Array type mismatch");
1293 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_CHAR))
1294 panic("Array type mismatch");
1298 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_DOUBLE))
1299 panic("Array type mismatch");
1303 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_FLOAT))
1304 panic("Array type mismatch");
1308 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_INT))
1309 panic("Array type mismatch");
1313 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_SHORT))
1314 panic("Array type mismatch");
1318 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_LONG))
1319 panic("Array type mismatch");
1324 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_BOOLEAN)
1325 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_BYTE))
1326 panic("Array type mismatch");
1330 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_CHAR))
1331 panic("Array type mismatch");
1335 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_DOUBLE))
1336 panic("Array type mismatch");
1340 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_FLOAT))
1341 panic("Array type mismatch");
1345 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_INT))
1346 panic("Array type mismatch");
1350 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_SHORT))
1351 panic("Array type mismatch");
1355 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_LONG))
1356 panic("Array type mismatch");
1360 case ICMD_IASTORECONST:
1361 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo, ARRAYTYPE_INT))
1362 panic("Array type mismatch");
1366 case ICMD_LASTORECONST:
1367 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo, ARRAYTYPE_LONG))
1368 panic("Array type mismatch");
1372 case ICMD_BASTORECONST:
1373 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo, ARRAYTYPE_BOOLEAN)
1374 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo, ARRAYTYPE_BYTE))
1375 panic("Array type mismatch");
1379 case ICMD_CASTORECONST:
1380 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo, ARRAYTYPE_CHAR))
1381 panic("Array type mismatch");
1385 case ICMD_SASTORECONST:
1386 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo, ARRAYTYPE_SHORT))
1387 panic("Array type mismatch");
1392 /****************************************/
1393 /* ADDRESS CONSTANTS */
1396 if (iptr->val.a == NULL)
1397 TYPEINFO_INIT_NULLTYPE(dst->typeinfo);
1399 /* string constants (or constant for builtin function) */
1400 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,class_java_lang_String);
1403 /****************************************/
1404 /* CHECKCAST AND INSTANCEOF */
1406 case ICMD_CHECKCAST:
1407 TYPECHECK_ADR(curstack);
1408 /* returnAddress is not allowed */
1409 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1410 panic("Illegal instruction: CHECKCAST on non-reference");
1412 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,(classinfo *)iptr[0].val.a);
1416 case ICMD_INSTANCEOF:
1417 TYPECHECK_ADR(curstack);
1418 /* returnAddress is not allowed */
1419 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1420 panic("Illegal instruction: INSTANCEOF on non-reference");
1423 /****************************************/
1424 /* BRANCH INSTRUCTIONS */
1427 superblockend = true;
1430 case ICMD_IFNONNULL:
1437 case ICMD_IF_ICMPEQ:
1438 case ICMD_IF_ICMPNE:
1439 case ICMD_IF_ICMPLT:
1440 case ICMD_IF_ICMPGE:
1441 case ICMD_IF_ICMPGT:
1442 case ICMD_IF_ICMPLE:
1443 case ICMD_IF_ACMPEQ:
1444 case ICMD_IF_ACMPNE:
1451 case ICMD_IF_LCMPEQ:
1452 case ICMD_IF_LCMPNE:
1453 case ICMD_IF_LCMPLT:
1454 case ICMD_IF_LCMPGE:
1455 case ICMD_IF_LCMPGT:
1456 case ICMD_IF_LCMPLE:
1457 TYPECHECK_COUNT(stat_ins_branch);
1458 tbptr = (basicblock *) iptr->target;
1460 /* propagate stack and variables to the target block */
1464 /****************************************/
1467 case ICMD_TABLESWITCH:
1468 TYPECHECK_COUNT(stat_ins_switch);
1470 s4 *s4ptr = iptr->val.a;
1471 s4ptr++; /* skip default */
1472 i = *s4ptr++; /* low */
1473 i = *s4ptr++ - i + 2; /* +1 for default target */
1475 goto switch_instruction_tail;
1477 case ICMD_LOOKUPSWITCH:
1478 TYPECHECK_COUNT(stat_ins_switch);
1480 s4 *s4ptr = iptr->val.a;
1481 s4ptr++; /* skip default */
1482 i = *s4ptr++ + 1; /* count +1 for default */
1484 switch_instruction_tail:
1485 tptr = (basicblock **)iptr->target;
1489 LOG2("target %d is block %04d",(tptr-(basicblock **)iptr->target)-1,tbptr-block);
1493 superblockend = true;
1496 /****************************************/
1497 /* RETURNS AND THROW */
1500 if (!typeinfo_is_assignable_to_classinfo(
1501 &curstack->typeinfo,class_java_lang_Throwable))
1502 panic("illegal instruction: ATHROW on non-Throwable");
1503 superblockend = true;
1508 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1509 panic("illegal instruction: ARETURN on non-reference");
1511 if (returntype.type != TYPE_ADDRESS
1512 || !typeinfo_is_assignable(&curstack->typeinfo,&(returntype.info)))
1513 panic("Return type mismatch");
1517 if (returntype.type != TYPE_INT) panic("Return type mismatch");
1521 if (returntype.type != TYPE_LONG) panic("Return type mismatch");
1525 if (returntype.type != TYPE_FLOAT) panic("Return type mismatch");
1529 if (returntype.type != TYPE_DOUBLE) panic("Return type mismatch");
1533 if (returntype.type != TYPE_VOID) panic("Return type mismatch");
1536 superblockend = true;
1540 /****************************************/
1541 /* SUBROUTINE INSTRUCTIONS */
1545 jsrencountered = true;
1547 /* This is a dirty hack. It is needed
1548 * because of the special handling of
1549 * ICMD_JSR in stack.c
1551 dst = (stackptr) iptr->val.a;
1553 tbptr = (basicblock *) iptr->target;
1554 if (bptr + 1 == (m->basicblocks + m->basicblockcount + 1))
1555 panic("Illegal instruction: JSR at end of bytecode");
1556 typestack_put_retaddr(dst,bptr+1,localset);
1557 repeat |= typestate_reach(cd, rd,localbuf,bptr,tbptr,dst,
1558 localset,numlocals,true);
1560 superblockend = true;
1564 /* check returnAddress variable */
1565 if (!typevectorset_checkretaddr(localset,iptr->op1))
1566 panic("illegal instruction: RET using non-returnAddress variable");
1568 repeat |= typestate_ret(cd,rd, localbuf,bptr,curstack,
1569 localset,iptr->op1,numlocals);
1571 superblockend = true;
1574 /****************************************/
1577 case ICMD_INVOKEVIRTUAL:
1578 case ICMD_INVOKESPECIAL:
1579 case ICMD_INVOKESTATIC:
1580 case ICMD_INVOKEINTERFACE:
1581 TYPECHECK_COUNT(stat_ins_invoke);
1583 methodinfo *mi = (methodinfo*) iptr->val.a;
1584 bool specialmethod = (mi->name->text[0] == '<');
1585 bool callinginit = (opcode == ICMD_INVOKESPECIAL && mi->name == name_init);
1587 classinfo *initclass;
1589 if (specialmethod && !callinginit)
1590 panic("Invalid invocation of special method");
1592 if (opcode == ICMD_INVOKESPECIAL) {
1593 /* XXX for INVOKESPECIAL: check if the invokation is done at all */
1595 /* (If callinginit the class is checked later.) */
1597 if (!builtin_isanysubclass(myclass,mi->class))
1598 panic("Illegal instruction: INVOKESPECIAL calling non-superclass method");
1602 /* fetch parameter types and return type */
1604 if (opcode != ICMD_INVOKESTATIC) {
1605 ptype[0] = TYPE_ADR;
1606 TYPEINFO_INIT_CLASSINFO(pinfo[0],mi->class);
1609 typeinfo_init_from_method_args(mi->descriptor,ptype+i,pinfo+i,
1613 /* check parameter types */
1614 srcstack = curstack;
1615 i = mi->paramcount; /* number of parameters including 'this'*/
1618 if (srcstack->type != ptype[i])
1619 panic("Parameter type mismatch in method invocation");
1620 if (srcstack->type == TYPE_ADR) {
1621 LOGINFO(&(srcstack->typeinfo));
1623 if (i==0 && callinginit)
1625 /* first argument to <init> method */
1626 if (!TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo))
1627 panic("Calling <init> on initialized object");
1629 /* get the address of the NEW instruction */
1630 LOGINFO(&(srcstack->typeinfo));
1631 ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(srcstack->typeinfo);
1632 initclass = (ins) ? (classinfo*)ins[-1].val.a : m->class;
1633 LOGSTR("class: "); LOGSTRu(initclass->name); LOGNL;
1636 /* (This is checked below.) */
1637 /* TYPEINFO_INIT_CLASSINFO(tempinfo,initclass); */
1638 /* if (!typeinfo_is_assignable(&tempinfo,pinfo+0)) */
1639 /* panic("Parameter reference type mismatch in <init> invocation"); */
1642 if (!typeinfo_is_assignable(&(srcstack->typeinfo),pinfo+i))
1643 panic("Parameter reference type mismatch in method invocation");
1648 if (i) srcstack = srcstack->prev;
1651 /* XXX We should resolve the method and pass its
1652 * class as implementingclass to is_accessible. */
1653 if (!is_accessible(mi->flags,mi->class,NULL, myclass,
1654 (opcode == ICMD_INVOKESTATIC) ? NULL
1655 : &(srcstack->typeinfo)))
1656 panic("Invoking unaccessible method");
1658 LOG("checking return type");
1659 if (rtype != TYPE_VOID) {
1660 if (rtype != dst->type)
1661 panic("Return type mismatch in method invocation");
1662 TYPEINFO_COPY(rinfo,dst->typeinfo);
1666 LOG("replacing uninitialized object");
1667 /* replace uninitialized object type on stack */
1670 if (srcstack->type == TYPE_ADR
1671 && TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo)
1672 && TYPEINFO_NEWOBJECT_INSTRUCTION(srcstack->typeinfo) == ins)
1674 LOG("replacing uninitialized type on stack");
1676 /* If this stackslot is in the instack of
1677 * this basic block we must save the type(s)
1678 * we are going to replace.
1680 if (srcstack <= bptr->instack && !savedstack)
1684 LOG("saving input stack types");
1685 if (!savedstackbuf) {
1686 LOG("allocating savedstack buffer");
1687 savedstackbuf = DMNEW(stackelement, cd->maxstack);
1688 savedstackbuf->prev = NULL;
1689 for (i = 1; i < cd->maxstack; ++i)
1690 savedstackbuf[i].prev = savedstackbuf+(i-1);
1692 sp = savedstack = bptr->instack;
1693 copy = bptr->instack = savedstackbuf + (bptr->indepth-1);
1694 TYPESTACK_COPY(sp,copy);
1697 TYPEINFO_INIT_CLASSINFO(srcstack->typeinfo,initclass);
1699 srcstack = srcstack->prev;
1701 /* replace uninitialized object type in locals */
1702 typevectorset_init_object(localset,ins,initclass,numlocals);
1704 /* initializing the 'this' reference? */
1706 #ifdef TYPECHECK_DEBUG
1708 panic("Internal error: calling <init> on this in non-<init> method.");
1710 /* must be <init> of current class or direct superclass */
1711 if (mi->class != m->class && mi->class != m->class->super)
1712 panic("<init> calling <init> of the wrong class");
1714 /* set our marker variable to type int */
1715 LOG("setting <init> marker");
1716 typevectorset_store(localset,numlocals-1,TYPE_INT,NULL);
1719 /* initializing an instance created with NEW */
1720 /* XXX is this strictness ok? */
1721 if (mi->class != initclass)
1722 panic("Calling <init> method of the wrong class");
1729 case ICMD_MULTIANEWARRAY:
1731 vftbl_t *arrayvftbl;
1732 arraydescriptor *desc;
1734 /* check the array lengths on the stack */
1736 if (i<1) panic("MULTIANEWARRAY with dimensions < 1");
1737 srcstack = curstack;
1740 panic("MULTIANEWARRAY missing array length");
1741 if (srcstack->type != TYPE_INT)
1742 panic("MULTIANEWARRAY using non-int as array length");
1743 srcstack = srcstack->prev;
1746 /* check array descriptor */
1747 arrayvftbl = (vftbl_t*) iptr[0].val.a;
1749 panic("MULTIANEWARRAY with unlinked class");
1750 if ((desc = arrayvftbl->arraydesc) == NULL)
1751 panic("MULTIANEWARRAY with non-array class");
1752 if (desc->dimension < iptr[0].op1)
1753 panic("MULTIANEWARRAY dimension to high");
1755 /* set the array type of the result */
1756 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,arrayvftbl->class);
1762 TYPECHECK_COUNT(stat_ins_builtin);
1763 if (ISBUILTIN(BUILTIN_aastore)) {
1764 TYPECHECK_ADR(curstack);
1765 TYPECHECK_INT(curstack->prev);
1766 TYPECHECK_ADR(curstack->prev->prev);
1767 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(curstack->prev->prev->typeinfo))
1768 panic("illegal instruction: AASTORE to non-reference array");
1771 /* XXX put these checks in a function */
1772 TYPECHECK_COUNT(stat_ins_builtin_gen);
1773 builtindesc = builtin_desc;
1774 while (builtindesc->opcode && builtindesc->builtin
1775 != iptr->val.fp) builtindesc++;
1776 if (!builtindesc->opcode) {
1777 dolog("Builtin not in table: %s",icmd_builtin_name(iptr->val.fp));
1778 panic("Internal error: builtin not found in table");
1780 TYPECHECK_ARGS3(builtindesc->type_s3,builtindesc->type_s2,builtindesc->type_s1);
1786 TYPECHECK_COUNT(stat_ins_builtin);
1787 if (ISBUILTIN(BUILTIN_newarray))
1790 TYPECHECK_INT(curstack->prev);
1791 if (iptr[-1].opc != ICMD_ACONST)
1792 panic("illegal instruction: builtin_newarray without classinfo");
1793 vft = (vftbl_t *)iptr[-1].val.a;
1795 panic("ANEWARRAY with unlinked class");
1796 if (!vft->arraydesc)
1797 panic("ANEWARRAY with non-array class");
1798 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,vft->class);
1800 else if (ISBUILTIN(BUILTIN_arrayinstanceof))
1803 TYPECHECK_ADR(curstack->prev);
1804 if (iptr[-1].opc != ICMD_ACONST)
1805 panic("illegal instruction: builtin_arrayinstanceof without classinfo");
1806 vft = (vftbl_t *)iptr[-1].val.a;
1808 panic("INSTANCEOF with unlinked class");
1809 if (!vft->arraydesc)
1810 panic("internal error: builtin_arrayinstanceof with non-array class");
1812 else if (ISBUILTIN(BUILTIN_checkarraycast)) {
1814 TYPECHECK_ADR(curstack->prev);
1815 if (iptr[-1].opc != ICMD_ACONST)
1816 panic("illegal instruction: BUILTIN_checkarraycast without classinfo");
1817 vft = (vftbl_t *)iptr[-1].val.a;
1819 panic("CHECKCAST with unlinked class");
1820 if (!vft->arraydesc)
1821 panic("internal error: builtin_checkarraycast with non-array class");
1822 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,vft->class);
1825 TYPECHECK_COUNT(stat_ins_builtin_gen);
1826 builtindesc = builtin_desc;
1827 while (builtindesc->opcode && builtindesc->builtin
1828 != iptr->val.fp) builtindesc++;
1829 if (!builtindesc->opcode) {
1830 dolog("Builtin not in table: %s",icmd_builtin_name(iptr->val.fp));
1831 panic("Internal error: builtin not found in table");
1833 TYPECHECK_ARGS2(builtindesc->type_s2,builtindesc->type_s1);
1839 TYPECHECK_COUNT(stat_ins_builtin);
1840 if (ISBUILTIN(BUILTIN_new)) {
1842 if (iptr[-1].opc != ICMD_ACONST)
1843 panic("illegal instruction: builtin_new without classinfo");
1844 cls = (classinfo *) iptr[-1].val.a;
1846 panic("Internal error: NEW with unlinked class");
1847 /* The following check also forbids array classes and interfaces: */
1848 if ((cls->flags & ACC_ABSTRACT) != 0)
1849 panic("Invalid instruction: NEW creating instance of abstract class");
1850 TYPEINFO_INIT_NEWOBJECT(dst->typeinfo,iptr);
1852 else if (ISBUILTIN(BUILTIN_newarray_boolean)) {
1853 TYPECHECK_INT(curstack);
1854 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BOOLEAN);
1856 else if (ISBUILTIN(BUILTIN_newarray_char)) {
1857 TYPECHECK_INT(curstack);
1858 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_CHAR);
1860 else if (ISBUILTIN(BUILTIN_newarray_float)) {
1861 TYPECHECK_INT(curstack);
1862 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_FLOAT);
1864 else if (ISBUILTIN(BUILTIN_newarray_double)) {
1865 TYPECHECK_INT(curstack);
1866 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_DOUBLE);
1868 else if (ISBUILTIN(BUILTIN_newarray_byte)) {
1869 TYPECHECK_INT(curstack);
1870 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BYTE);
1872 else if (ISBUILTIN(BUILTIN_newarray_short)) {
1873 TYPECHECK_INT(curstack);
1874 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_SHORT);
1876 else if (ISBUILTIN(BUILTIN_newarray_int)) {
1877 TYPECHECK_INT(curstack);
1878 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_INT);
1880 else if (ISBUILTIN(BUILTIN_newarray_long)) {
1881 TYPECHECK_INT(curstack);
1882 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_LONG);
1885 TYPECHECK_COUNT(stat_ins_builtin_gen);
1886 builtindesc = builtin_desc;
1887 while (builtindesc->opcode && builtindesc->builtin
1888 != iptr->val.fp) builtindesc++;
1889 if (!builtindesc->opcode) {
1890 dolog("Builtin not in table: %s",icmd_builtin_name(iptr->val.fp));
1891 panic("Internal error: builtin not found in table");
1893 TYPECHECK_ARGS1(builtindesc->type_s1);
1898 /****************************************/
1899 /* SIMPLE EXCEPTION THROWING TESTS */
1901 case ICMD_CHECKASIZE:
1902 /* The argument to CHECKASIZE is typechecked by
1903 * typechecking the array creation instructions. */
1906 case ICMD_NULLCHECKPOP:
1907 /* NULLCHECKPOP just requires that the stack top
1908 * is an address. This is checked in stack.c */
1913 /****************************************/
1914 /* INSTRUCTIONS WHICH SHOULD HAVE BEEN */
1915 /* REPLACED BY OTHER OPCODES */
1917 #ifdef TYPECHECK_DEBUG
1920 case ICMD_ANEWARRAY:
1921 case ICMD_MONITORENTER:
1922 case ICMD_MONITOREXIT:
1924 LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
1925 LOG("Should have been converted to builtin function call.");
1926 panic("Internal error: unexpected instruction encountered");
1929 case ICMD_READONLY_ARG:
1930 case ICMD_CLEAR_ARGREN:
1931 LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
1932 LOG("Should have been replaced in stack.c.");
1933 panic("Internal error: unexpected pseudo instruction encountered");
1937 /****************************************/
1938 /* UNCHECKED OPERATIONS */
1940 /*********************************************
1941 * Instructions below...
1942 * *) don't operate on local variables,
1943 * *) don't operate on references,
1944 * *) don't operate on returnAddresses.
1946 * (These instructions are typechecked in
1948 ********************************************/
1950 /* Instructions which may throw a runtime exception: */
1960 /* Instructions which never throw a runtime exception: */
1961 #if defined(TYPECHECK_DEBUG) || defined(TYPECHECK_STATISTICS)
1971 case ICMD_IFEQ_ICONST:
1972 case ICMD_IFNE_ICONST:
1973 case ICMD_IFLT_ICONST:
1974 case ICMD_IFGE_ICONST:
1975 case ICMD_IFGT_ICONST:
1976 case ICMD_IFLE_ICONST:
1977 case ICMD_ELSE_ICONST:
1999 case ICMD_IREM0X10001:
2000 case ICMD_LREM0X10001:
2003 case ICMD_IADDCONST:
2004 case ICMD_ISUBCONST:
2005 case ICMD_IMULCONST:
2006 case ICMD_IANDCONST:
2008 case ICMD_IXORCONST:
2009 case ICMD_ISHLCONST:
2010 case ICMD_ISHRCONST:
2011 case ICMD_IUSHRCONST:
2013 case ICMD_LADDCONST:
2014 case ICMD_LSUBCONST:
2015 case ICMD_LMULCONST:
2016 case ICMD_LANDCONST:
2018 case ICMD_LXORCONST:
2019 case ICMD_LSHLCONST:
2020 case ICMD_LSHRCONST:
2021 case ICMD_LUSHRCONST:
2038 case ICMD_INT2SHORT:
2041 case ICMD_LCMPCONST:
2060 TYPECHECK_COUNT(stat_ins_unchecked);
2063 /****************************************/
2066 LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
2067 panic("Missing ICMD code during typecheck");
2071 /* the output of this instruction becomes the current stack */
2074 /* reach exception handlers for this instruction */
2076 LOG("reaching exception handlers");
2078 while (handlers[i]) {
2079 TYPECHECK_COUNT(stat_handlers_reached);
2080 cls = handlers[i]->catchtype;
2081 excstack.typeinfo.typeclass = (cls) ? cls
2082 : class_java_lang_Throwable;
2083 repeat |= typestate_reach(cd,rd, localbuf,bptr,
2084 handlers[i]->handler,
2093 } /* while instructions */
2095 LOG("instructions done");
2096 LOGSTR("RESULT=> ");
2097 DOLOG(typestate_print(get_logfile(),curstack,localset,numlocals));
2100 /* propagate stack and variables to the following block */
2101 if (!superblockend) {
2102 LOG("reaching following block");
2104 while (tbptr->flags == BBDELETED) {
2106 #ifdef TYPECHECK_DEBUG
2107 if ((tbptr-block) >= m->basicblockcount)
2108 panic("Control flow falls off the last block");
2114 /* We may have to restore the types of the instack slots. They
2115 * have been saved if an <init> call inside the block has
2116 * modified the instack types. (see INVOKESPECIAL) */
2119 stackptr sp = bptr->instack;
2120 stackptr copy = savedstack;
2121 TYPECHECK_COUNT(stat_savedstack);
2122 LOG("restoring saved instack");
2123 TYPESTACK_COPY(sp,copy);
2124 bptr->instack = savedstack;
2128 } /* if block has to be checked */
2130 } /* while blocks */
2132 LOGIF(repeat,"repeat=true");
2135 #ifdef TYPECHECK_STATISTICS
2136 dolog("Typechecker did %4d iterations",count_iterations);
2137 TYPECHECK_COUNT_FREQ(stat_iterations,count_iterations,STAT_ITERATIONS);
2138 TYPECHECK_COUNTIF(jsrencountered,stat_typechecked_jsr);
2141 #ifdef TYPECHECK_DEBUG
2142 for (i=0; i<m->basicblockcount; ++i) {
2143 if (m->basicblocks[i].flags != BBDELETED
2144 && m->basicblocks[i].flags != BBUNDEF
2145 && m->basicblocks[i].flags != BBFINISHED
2146 && m->basicblocks[i].flags != BBTYPECHECK_UNDEF) /* typecheck may never reach
2147 * some exception handlers,
2150 LOG2("block L%03d has invalid flags after typecheck: %d",
2151 m->basicblocks[i].debug_nr,m->basicblocks[i].flags);
2152 panic("Invalid block flags after typecheck");
2157 /* Reset blocks we never reached */
2158 for (i=0; i<m->basicblockcount; ++i) {
2159 if (m->basicblocks[i].flags == BBTYPECHECK_UNDEF)
2160 m->basicblocks[i].flags = BBFINISHED;
2163 LOGimp("exiting typecheck");
2165 /* just return methodinfo* to signal everything was ok */
2172 #endif /* CACAO_TYPECHECK */
2175 * These are local overrides for various environment variables in Emacs.
2176 * Please do not remove this and leave it at the end of the file, where
2177 * Emacs will automagically detect them.
2178 * ---------------------------------------------------------------------
2181 * indent-tabs-mode: t