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 868 2004-01-10 20:12:10Z edwin $
33 #include "global.h" /* must be here because of CACAO_TYPECHECK */
35 #ifdef CACAO_TYPECHECK
43 #include "toolbox/loging.h"
44 #include "toolbox/memory.h"
46 #define TOUCHED_YES 0x01
47 #define TOUCHED_NO 0x02
48 #define TOUCHED_MAYBE (TOUCHED_YES | TOUCHED_NO)
50 #define REACH_STD 0 /* reached by branch or fallthrough */
51 #define REACH_JSR 1 /* reached by JSR */
52 #define REACH_RET 2 /* reached by RET */ /* XXX ? */
53 #define REACH_THROW 3 /* reached by THROW (exception handler) */
55 /****************************************************************************/
57 /****************************************************************************/
59 #ifdef TYPECHECK_VERBOSE_OPT
60 bool typecheckverbose = false;
61 #define DOLOG(action) do { if (typecheckverbose) {action;} } while(0)
66 #ifdef TYPECHECK_VERBOSE
67 #define TYPECHECK_VERBOSE_IMPORTANT
68 #define LOG(str) DOLOG(log_text(str))
69 #define LOG1(str,a) DOLOG(dolog(str,a))
70 #define LOG2(str,a,b) DOLOG(dolog(str,a,b))
71 #define LOG3(str,a,b,c) DOLOG(dolog(str,a,b,c))
72 #define LOGIF(cond,str) DOLOG(do {if (cond) log_text(str);} while(0))
73 #define LOGINFO(info) DOLOG(do {typeinfo_print_short(get_logfile(),(info));log_plain("\n");} while(0))
74 #define LOGFLUSH DOLOG(fflush(get_logfile()))
75 #define LOGNL DOLOG(log_plain("\n"))
76 #define LOGSTR(str) DOLOG(log_plain(str))
77 #define LOGSTR1(str,a) DOLOG(dolog_plain(str,a))
78 #define LOGSTR2(str,a,b) DOLOG(dolog_plain(str,a,b))
79 #define LOGSTR3(str,a,b,c) DOLOG(dolog_plain(str,a,b,c))
80 #define LOGSTRu(utf) DOLOG(log_plain_utf(utf))
85 #define LOG3(str,a,b,c)
86 #define LOGIF(cond,str)
91 #define LOGSTR1(str,a)
92 #define LOGSTR2(str,a,b)
93 #define LOGSTR3(str,a,b,c)
97 #ifdef TYPECHECK_VERBOSE_IMPORTANT
98 #define LOGimp(str) DOLOG(log_text(str))
99 #define LOGimpSTR(str) DOLOG(log_plain(str))
100 #define LOGimpSTRu(utf) DOLOG(log_plain_utf(utf))
103 #define LOGimpSTR(str)
104 #define LOGimpSTRu(utf)
107 #if defined(TYPECHECK_VERBOSE) || defined(TYPECHECK_VERBOSE_IMPORTANT)
113 typeinfo_print_locals(FILE *file,u1 *vtype,typeinfo *vinfo,u1 *touched,int num)
117 for (i=0; i<num; ++i) {
119 fprintf(file," %d%s=",i,
120 (touched[i]==TOUCHED_YES) ? "*"
121 : ((touched[i]==TOUCHED_NO) ? "" : "~"));
123 fprintf(file," %d=",i);
124 typeinfo_print_type(file,vtype[i],vinfo+i);
130 typeinfo_print_stack(FILE *file,stackptr stack)
133 typeinfo_print_type(file,stack->type,&stack->typeinfo);
135 if (stack) fprintf(file," ");
141 typeinfo_print_block(FILE *file,stackptr instack,
142 int vnum,u1 *vtype,typeinfo *vinfo,u1 *touched)
144 fprintf(file,"Stack: ");
145 typeinfo_print_stack(file,instack);
146 fprintf(file," Locals:");
147 typeinfo_print_locals(file,vtype,vinfo,touched,vnum);
152 typestack_print(FILE *file,stackptr stack)
155 typeinfo_print_stacktype(file,stack->type,&stack->typeinfo);
157 if (stack) fprintf(file," ");
163 typestate_print(FILE *file,stackptr instack,typevector *localset,int size)
165 fprintf(file,"Stack: ");
166 typestack_print(file,instack);
167 fprintf(file," Locals:");
168 typevectorset_print(file,localset,size);
175 typeinfo_print_blocks(FILE *file,int vnum,u1 *vtype,typeinfo *vinfo)
180 for (bi=0; bi<block_count; ++bi) {
181 fprintf(file,"%04d: (%3d) ",bi,block[bi].flags);
182 typeinfo_print_block(file,block[bi].instack,
183 vnum,vtype+vnum*bi,vinfo+vnum*bi,NULL);
186 /* for (j=0; j<block[bi].icount; ++j) { */
187 /* fprintf(file,"\t%s\n",icmd_names[block[bi].iinstr[j].opc]); */
190 show_icmd_block(block+bi);
197 /****************************************************************************/
198 /* TYPESTACK FUNCTIONS */
199 /****************************************************************************/
201 #define TYPESTACK_IS_RETURNADDRESS(sptr) \
202 TYPE_IS_RETURNADDRESS((sptr)->type,(sptr)->typeinfo)
204 #define TYPESTACK_IS_REFERENCE(sptr) \
205 TYPE_IS_REFERENCE((sptr)->type,(sptr)->typeinfo)
207 #define TYPESTACK_RETURNADDRESSSET(sptr) \
208 ((typeinfo_retaddr_set*)TYPEINFO_RETURNADDRESS((sptr)->typeinfo))
210 #define RETURNADDRESSSET_SEEK(set,pos) \
211 do {int i; for (i=pos;i--;) set=set->alt;} while(0)
214 typestack_copy(stackptr dst,stackptr y,typevector *selected)
217 typeinfo_retaddr_set *sety;
218 typeinfo_retaddr_set *new;
219 typeinfo_retaddr_set **next;
222 for (;dst; dst=dst->prev, y=y->prev) {
223 if (!y) panic("Stack depth mismatch");
224 if (dst->type != y->type)
225 panic("Stack type mismatch");
226 LOG3("copy %p -> %p (type %d)",y,dst,dst->type);
227 if (dst->type == TYPE_ADDRESS) {
228 if (TYPEINFO_IS_PRIMITIVE(y->typeinfo)) {
229 /* We copy the returnAddresses from the selected
232 LOG("copying returnAddress");
233 sety = TYPESTACK_RETURNADDRESSSET(y);
235 for (k=0,sel=selected; sel; sel=sel->alt) {
236 LOG1("selected k=%d",sel->k);
241 *next = DNEW(typeinfo_retaddr_set);
242 (*next)->addr = sety->addr;
243 next = &((*next)->alt);
246 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,new);
249 TYPEINFO_CLONE(y->typeinfo,dst->typeinfo);
253 if (y) panic("Stack depth mismatch");
257 typestack_put_retaddr(stackptr dst,void *retaddr,typevector *loc)
259 #ifdef TYPECHECK_DEBUG
260 if (dst->type != TYPE_ADDRESS)
261 panic("Internal error: Storing returnAddress in non-address slot");
265 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,NULL);
266 for (;loc; loc=loc->alt) {
267 typeinfo_retaddr_set *set = DNEW(typeinfo_retaddr_set);
269 set->alt = TYPESTACK_RETURNADDRESSSET(dst);
270 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,set);
275 typestack_canmerge(stackptr a,stackptr b)
277 for (; a; a = a->prev, b = b->prev) {
278 if (!b) return false;
279 if (a->type != b->type) return false;
280 if (a->type == TYPE_ADDRESS) {
281 if (((TYPEINFO_IS_PRIMITIVE(a->typeinfo)) ? 1 : 0)
283 ((TYPEINFO_IS_PRIMITIVE(b->typeinfo)) ? 1 : 0))
292 typestack_collapse(stackptr dst)
294 for (; dst; dst = dst->prev) {
295 if (TYPESTACK_IS_RETURNADDRESS(dst))
296 TYPESTACK_RETURNADDRESSSET(dst)->alt = NULL;
300 /* 'dst' and 'y' are assumed to have passed typestack_canmerge! */
302 typestack_merge(stackptr dst,stackptr y)
304 bool changed = false;
305 for (; dst; dst = dst->prev, y=y->prev) {
306 if (TYPESTACK_IS_REFERENCE(dst))
307 changed |= typeinfo_merge(&(dst->typeinfo),&(y->typeinfo));
313 typestack_add(stackptr dst,stackptr y,int ky)
315 typeinfo_retaddr_set *setd;
316 typeinfo_retaddr_set *sety;
318 for (; dst; dst = dst->prev, y=y->prev) {
319 if (TYPESTACK_IS_RETURNADDRESS(dst)) {
320 setd = TYPESTACK_RETURNADDRESSSET(dst);
321 sety = TYPESTACK_RETURNADDRESSSET(y);
322 RETURNADDRESSSET_SEEK(sety,ky);
325 setd->alt = DNEW(typeinfo_retaddr_set);
326 setd->alt->addr = sety->addr;
327 setd->alt->alt = NULL;
332 /* 'a' and 'b' are assumed to have passed typestack_canmerge! */
334 typestack_separable_with(stackptr a,stackptr b,int kb)
336 typeinfo_retaddr_set *seta;
337 typeinfo_retaddr_set *setb;
339 for (; a; a = a->prev, b = b->prev) {
340 #ifdef TYPECHECK_DEBUG
341 if (!b) panic("Internal error: typestack_separable_from: different depth");
343 if (TYPESTACK_IS_RETURNADDRESS(a)) {
344 #ifdef TYPECHECK_DEBUG
345 if (!TYPESTACK_IS_RETURNADDRESS(b))
346 panic("Internal error: typestack_separable_from: unmergable stacks");
348 seta = TYPESTACK_RETURNADDRESSSET(a);
349 setb = TYPESTACK_RETURNADDRESSSET(b);
350 RETURNADDRESSSET_SEEK(setb,kb);
352 for (;seta;seta=seta->alt)
353 if (seta->addr != setb->addr) return true;
356 #ifdef TYPECHECK_DEBUG
357 if (b) panic("Internal error: typestack_separable_from: different depth");
362 /* 'a' and 'b' are assumed to have passed typestack_canmerge! */
364 typestack_separable_from(stackptr a,int ka,stackptr b,int kb)
366 typeinfo_retaddr_set *seta;
367 typeinfo_retaddr_set *setb;
370 for (; a; a = a->prev, b = b->prev) {
371 #ifdef TYPECHECK_DEBUG
372 if (!b) panic("Internal error: typestack_separable_from: different depth");
374 if (TYPESTACK_IS_RETURNADDRESS(a)) {
375 #ifdef TYPECHECK_DEBUG
376 if (!TYPESTACK_IS_RETURNADDRESS(b))
377 panic("Internal error: typestack_separable_from: unmergable stacks");
379 seta = TYPESTACK_RETURNADDRESSSET(a);
380 setb = TYPESTACK_RETURNADDRESSSET(b);
381 RETURNADDRESSSET_SEEK(seta,ka);
382 RETURNADDRESSSET_SEEK(setb,kb);
384 if (seta->addr != setb->addr) return true;
387 #ifdef TYPECHECK_DEBUG
388 if (b) panic("Internal error: typestack_separable_from: different depth");
393 /****************************************************************************/
394 /* TYPESTATE FUNCTIONS */
395 /****************************************************************************/
398 typestate_merge(stackptr deststack,typevector *destloc,
399 stackptr ystack,typevector *yloc,
400 /* int retindex,void *retaddr, */
403 typevector *dvec,*yvec;
405 bool changed = false;
407 #ifdef TYPECHECK_DEBUG
408 /* Do some sanity checks */
410 if (retindex < -1 || retindex >= locsize || (retindex >= 0 && !retaddr))
411 panic("Internal error: typestate_merge: invalid arguments");
416 LOGSTR("dstack: "); DOLOG(typestack_print(get_logfile(),deststack)); LOGNL;
417 LOGSTR("ystack: "); DOLOG(typestack_print(get_logfile(),ystack)); LOGNL;
418 LOGSTR("dloc : "); DOLOG(typevectorset_print(get_logfile(),destloc,locsize)); LOGNL;
419 LOGSTR("yloc : "); DOLOG(typevectorset_print(get_logfile(),yloc,locsize)); LOGNL;
421 /* Check if the stack types of deststack and ystack match */
423 /* XXX move this check into typestack_merge? */
424 if (!typestack_canmerge(deststack,ystack))
425 panic("Stack depth or stack type mismatch");
427 /* The stack is always merged. If there are returnAddresses on
428 * the stack they are ignored in this step. */
430 changed |= typestack_merge(deststack,ystack);
432 for (yvec=yloc; yvec; yvec=yvec->alt) {
435 /* If retindex >= 0 we select only those states (ystack,yvec)
436 * with returnAddress retaddr in variable no. retindex. */
440 if (!TYPEDESC_IS_RETURNADDRESS(yvec->td[retindex]))
441 panic("Illegal instruction: RET on non-returnAddress");
442 if (TYPEINFO_RETURNADDRESS(yvec->td[retindex].info)
448 /* Check if the typestates (deststack,destloc) will be
449 * separable when (ystack,yvec) is added. */
451 if (!typestack_separable_with(deststack,ystack,ky)
452 && !typevectorset_separable_with(destloc,yvec,locsize))
454 /* No, the resulting set won't be separable, thus we
455 * may merge all states in (deststack,destloc) and
458 typestack_collapse(deststack);
459 typevectorset_collapse(destloc,locsize);
460 typevector_merge(destloc,yvec,locsize);
463 /* Yes, the resulting set will be separable. Thus we check
464 * if we may merge (ystack,yvec) with a single state in
465 * (deststack,destloc). */
467 for (dvec=destloc,kd=0; dvec; dvec=dvec->alt, kd++) {
468 if (!typestack_separable_from(ystack,ky,deststack,kd)
469 && !typevector_separable_from(yvec,dvec,locsize))
471 /* The typestate (ystack,yvec) is not separable from
472 * (deststack,dvec) by any returnAddress. Thus we may
473 * merge the states. */
475 changed |= typevector_merge(dvec,yvec,locsize);
481 /* The typestate (ystack,yvec) is separable from all typestates
482 * (deststack,destloc). Thus we must add this state to the
485 typestack_add(deststack,ystack,ky);
486 typevectorset_add(destloc,yvec,locsize);
495 LOGSTR("dstack: "); DOLOG(typestack_print(get_logfile(),deststack)); LOGNL;
496 LOGSTR("dloc : "); DOLOG(typevectorset_print(get_logfile(),destloc,locsize)); LOGNL;
505 typestate_reach(void *localbuf,
507 basicblock *destblock,
508 stackptr ystack,typevector *yloc,
515 bool changed = false;
517 destidx = destblock - block;
518 destloc = MGET_TYPEVECTOR(localbuf,destidx,locsize);
520 if (destblock->flags == BBTYPECHECK_UNDEF) {
521 /* The destblock has never been reached before */
523 LOG1("block (index %04d) reached first time",destidx);
525 typestack_copy(destblock->instack,ystack,yloc);
526 COPY_TYPEVECTORSET(yloc,destloc,locsize);
530 /* The destblock has already been reached before */
532 LOG1("block (index %04d) reached before",destidx);
534 changed = typestate_merge(destblock->instack,destloc,
535 ystack,yloc,locsize);
540 destblock->flags = BBTYPECHECK_REACHED;
541 if (destblock <= current) {repeat = true; LOG("REPEAT!");}
547 * see typestate_reach
550 typestate_ret(void *localbuf,
552 stackptr ystack,typevector *yloc,
553 int retindex,int locsize)
556 typevector *selected;
557 basicblock *destblock;
560 for (yvec=yloc; yvec; ) {
561 if (!TYPEDESC_IS_RETURNADDRESS(yvec->td[retindex]))
562 panic("Illegal instruction: RET on non-returnAddress");
564 destblock = (basicblock*) TYPEINFO_RETURNADDRESS(yvec->td[retindex].info);
566 selected = typevectorset_select(&yvec,retindex,destblock);
568 repeat |= typestate_reach(localbuf,current,destblock,
569 ystack,selected,locsize);
575 typestate_jsr(void *localbuf,
576 basicblock *current,basicblock *destblock,
577 stackptr ystack,typevector *yloc,
580 typestack_put_retaddr(ystack,current+1,yloc);
581 return typestate_reach(localbuf,current,destblock,ystack,yloc,locsize);
584 /****************************************************************************/
585 /* HELPER FUNCTIONS */
586 /****************************************************************************/
588 /* If a field is checked, definingclass == implementingclass */
590 is_accessible(int flags,classinfo *definingclass,classinfo *implementingclass,
593 /* check access rights */
594 if (class != definingclass) {
595 switch (flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED)) {
599 /* In the cases below, definingclass cannot be an interface */
602 /* XXX check package access */
605 /* XXX check package access and superclass access */
608 if (definingclass != class) {
609 LOG("private access");
613 /* XXX check package access */
615 panic("Invalid access flags");
620 if ((flags & ACC_STATIC) != 0) {
621 LOG("accessing STATIC member with instance");
625 if (implementingclass
626 && !TYPEINFO_IS_NULLTYPE(*instance)
627 && !TYPEINFO_IS_NEWOBJECT(*instance))
631 if (((flags & ACC_PROTECTED) != 0)
632 && builtin_isanysubclass(class,implementingclass))
634 /* For protected access of super class members
635 * the instance must be a subclass of or the same
636 * as the current class. */
638 /* XXX maybe we only are allowed to do this, if we
639 * don't have package access? */
640 /* implementingclass = class; */ /* XXX does not work */
643 /* XXX use classinfo directly? */
644 TYPEINFO_INIT_CLASSINFO(tempinfo,implementingclass);
645 if (!typeinfo_is_assignable(instance,&tempinfo)) {
646 LOG("instance not assignable");
654 if ((flags & ACC_STATIC) == 0) {
655 LOG("accessing non-STATIC member without instance");
663 /****************************************************************************/
665 /****************************************************************************/
667 #ifdef TYPECHECK_DEBUG
668 /*#define TYPECHECK_STATISTICS*/
671 #ifdef TYPECHECK_STATISTICS
672 #define TYPECHECK_COUNT(cnt) (cnt)++
674 #define TYPECHECK_COUNT(cnt)
677 /****************************************************************************/
678 /* INTERNAL DATA STRUCTURES */
679 /****************************************************************************/
681 typedef struct jsr_record jsr_record;
684 * For each basic block we store the chain of JSR instructions which
685 * were used to reach the block (usually zero or one). For more
686 * details on verifying JSR and RET instructions see the Java VM
689 * CAUTION: The fields starting with sbr_ are only valid for the
690 * jsr_record of the first block of the subroutine.
693 basicblock *target; /* target of the JSR instruction (first block of subroutine) */
694 jsr_record *next; /* for chaining in nested try ... finally */ /* XXX make it sbr_next? */
695 u1 *sbr_touched; /* specifies which variables the subroutine touches */
696 u1 *sbr_vtype; /* Types of local variables after RET */
697 typeinfo *sbr_vinfo; /* Types of local variables after RET */
698 instruction *sbr_ret; /* RET instruction of the subroutine */
699 u1 touched[1]; /* touched flags for local variables */
702 /****************************************************************************/
703 /* MACROS USED INTERNALLY IN typecheck() */
704 /****************************************************************************/
706 #define TOUCH_VARIABLE(num) \
707 do {if (jsrchain) touched[num] = TOUCHED_YES;} while (0)
708 #define TOUCH_TWOWORD(num) \
709 do {TOUCH_VARIABLE(num);TOUCH_VARIABLE((num)+1);} while (0)
711 #define INDEX_ONEWORD(num) \
712 do { if((num)<0 || (num)>=validlocals) \
713 panic("Invalid local variable index"); } while (0)
714 #define INDEX_TWOWORD(num) \
715 do { if((num)<0 || ((num)+1)>=validlocals) \
716 panic("Invalid local variable index"); } while (0)
718 #define SET_VARIABLE(num,type) \
719 do {vtype[num] = (type); \
720 if ((num)>0 && IS_2_WORD_TYPE(vtype[(num)-1])) { \
721 vtype[(num)-1] = TYPE_VOID; \
722 TOUCH_VARIABLE((num)-1); \
724 TOUCH_VARIABLE(num);} while(0)
726 #define STORE_ONEWORD(num,type) \
727 do {INDEX_ONEWORD(num); \
728 typevectorset_store(localset,num,type,NULL);} while(0)
730 #define STORE_TWOWORD(num,type) \
731 do {INDEX_TWOWORD(num); \
732 typevectorset_store_twoword(localset,num,type);} while(0)
734 #define CHECK_ONEWORD(num,type) \
735 do {INDEX_ONEWORD(num); \
736 if (!typevectorset_checktype(localset,num,type)) \
737 panic("Variable type mismatch"); \
740 #define CHECK_TWOWORD(num,type) \
741 do {INDEX_TWOWORD(num); \
742 if (!typevectorset_checktype(localset,num,type)) \
743 panic("Variable type mismatch"); \
746 /* XXX maybe it's faster to copy always */
747 #define COPYTYPE(source,dest) \
748 {if ((source)->type == TYPE_ADR) \
749 TYPEINFO_COPY((source)->typeinfo,(dest)->typeinfo);}
751 #define ISBUILTIN(v) (iptr->val.a == (functionptr)(v))
753 #define TYPECHECK_STACK(sp,tp) \
754 do { if ((sp)->type != (tp)) \
755 panic("Wrong data type on stack"); } while(0)
757 #define TYPECHECK_ADR(sp) TYPECHECK_STACK(sp,TYPE_ADR)
758 #define TYPECHECK_INT(sp) TYPECHECK_STACK(sp,TYPE_INT)
759 #define TYPECHECK_LNG(sp) TYPECHECK_STACK(sp,TYPE_LNG)
760 #define TYPECHECK_FLT(sp) TYPECHECK_STACK(sp,TYPE_FLT)
761 #define TYPECHECK_DBL(sp) TYPECHECK_STACK(sp,TYPE_DBL)
763 #define TYPECHECK_ARGS1(t1) \
764 do {TYPECHECK_STACK(curstack,t1);} while (0)
765 #define TYPECHECK_ARGS2(t1,t2) \
766 do {TYPECHECK_ARGS1(t1); \
767 TYPECHECK_STACK(curstack->prev,t2);} while (0)
768 #define TYPECHECK_ARGS3(t1,t2,t3) \
769 do {TYPECHECK_ARGS2(t1,t2); \
770 TYPECHECK_STACK(curstack->prev->prev,t3);} while (0)
772 /* TYPECHECK_COPYVARS: copy the types and typeinfos of the current local
773 * variables to the local variables of the target block.
775 * vtype......current local variable types
776 * vinfo......current local variable typeinfos
777 * ttype......local variable types of target block
778 * tinfo......local variable typeinfos of target block
779 * numlocals..number of local variables
783 #define TYPECHECK_COPYVARS \
785 LOG("TYPECHECK_COPYVARS"); \
786 for (macro_i=0; macro_i<numlocals; ++macro_i) { \
787 if ((ttype[macro_i] = vtype[macro_i]) == TYPE_ADR) \
788 TYPEINFO_CLONE(vinfo[macro_i],tinfo[macro_i]); \
791 /* TYPECHECK_MERGEVARS: merge the local variables of the target block
792 * with the current local variables.
794 * vtype......current local variable types
795 * vinfo......current local variable typeinfos
796 * ttype......local variable types of target block
797 * tinfo......local variable typeinfos of target block
798 * numlocals..number of local variables
800 * changed....set to true if any typeinfo has changed
804 #define TYPECHECK_MERGEVARS \
806 LOG("TYPECHECK_MERGEVARS"); \
807 for (macro_i=0; macro_i<numlocals; ++macro_i) { \
808 if ((ttype[macro_i] != TYPE_VOID) && (vtype[macro_i] != ttype[macro_i])) { \
809 LOG3("var %d: type %d + type %d = void",macro_i,ttype[macro_i],vtype[macro_i]); \
810 ttype[macro_i] = TYPE_VOID; \
812 } else if (ttype[macro_i] == TYPE_ADR) { \
813 if ( ((TYPEINFO_IS_PRIMITIVE(tinfo[macro_i])) ? 1 : 0) \
815 ((TYPEINFO_IS_PRIMITIVE(vinfo[macro_i])) ? 1 : 0)) { \
816 LOG1("var %d: primitive + reference merge",macro_i); \
817 ttype[macro_i] = TYPE_VOID; \
821 LOG1("var %d:",macro_i); \
822 LOGINFO(tinfo+macro_i); \
823 LOGINFO(vinfo+macro_i); \
824 changed |= typeinfo_merge(tinfo+macro_i,vinfo+macro_i); \
825 LOGINFO(tinfo+macro_i); \
826 LOGIF(changed,"vars have changed"); \
831 /* TYPECHECK_MERGEJSR:
835 * tbptr......target block
836 * changed....set to true if any typeinfo has changed
837 * numlocals..number of local variables
838 * touched....current touched flags of local variables
840 * macro_i, jsrtemp, jsrtemp2
842 #define TYPECHECK_MERGEJSR \
844 LOG("TYPECHECK_MERGEJSR"); \
845 jsrtemp = jsrbuffer[tbptr-block]; \
846 jsrtemp2 = jsrchain; \
847 while (jsrtemp || jsrtemp2) { \
848 if (!jsrtemp || !jsrtemp2) \
849 panic("Merging JSR subroutines of different depth"); \
850 if (jsrtemp->target != jsrtemp2->target) \
851 panic("Merging different JSR subroutines"); \
852 jsrtemp = jsrtemp->next; \
853 jsrtemp2 = jsrtemp2->next; \
855 jsrtemp = jsrbuffer[tbptr-block]; \
857 for (macro_i=0; macro_i<numlocals; ++macro_i) { \
858 jsrtemp->touched[i] |= touched[i]; \
861 /* TYPECHECK_COPYSTACK: copy the typeinfos of the current stack to
862 * the input stack of the target block.
864 * srcstack...current stack
865 * dststack...input stack of target block
867 #define TYPECHECK_COPYSTACK \
869 LOG("TYPECHECK_COPYSTACK"); \
871 LOG1("copy %d",srcstack->type); \
872 if (!dststack) panic("Stack depth mismatch"); \
873 if (srcstack->type != dststack->type) \
874 panic("Type mismatch on stack"); \
875 if (srcstack->type == TYPE_ADR) { \
876 TYPEINFO_CLONE(srcstack->typeinfo,dststack->typeinfo); \
878 dststack = dststack->prev; \
879 srcstack = srcstack->prev; \
881 if (dststack) panic("Stack depth mismatch"); \
884 /* TYPECHECK_MERGESTACK: merge the input stack of the target block
885 * with the current stack.
887 * srcstack...current stack
888 * dststack...input stack of target block
890 * changed....set to true if any typeinfo has changed
892 #define TYPECHECK_MERGESTACK \
894 LOG("TYPECHECK_MERGESTACK"); \
896 if (!dststack) panic("Stack depth mismatch"); \
897 if (srcstack->type != dststack->type) \
898 panic("Type mismatch on stack"); \
899 if (srcstack->type == TYPE_ADR) { \
900 LOGINFO(&dststack->typeinfo); \
901 LOGINFO(&srcstack->typeinfo); LOGFLUSH; \
902 changed |= typeinfo_merge(&dststack->typeinfo, \
903 &srcstack->typeinfo); \
904 LOGINFO(&dststack->typeinfo); \
905 LOG((changed)?"CHANGED!\n":"not changed.\n"); \
907 dststack = dststack->prev; \
908 srcstack = srcstack->prev; \
910 if (dststack) panic("Stack depth mismatch"); \
914 /* TYPECHECK_CHECK_JSR_CHAIN: checks if the target block is reached by
915 * the same JSR targets on all control paths.
918 * tbptr......target block
919 * jsrchain...current JSR target chain
920 * jsrbuffer..JSR target chain for each basic block
922 * panic if the JSR target chains don't match
926 #define TYPECHECK_CHECK_JSR_CHAIN \
928 jsrtemp = jsrbuffer[tbptr-block]; \
929 if (!jsrtemp) panic("non-subroutine called by JSR"); \
930 if (jsrtemp->target != tbptr) \
931 panic("Merging different JSR subroutines"); \
932 jsrtemp = jsrtemp->next; \
933 jsrtemp2 = jsrchain; \
934 while (jsrtemp || jsrtemp2) { \
935 if (!jsrtemp || !jsrtemp2) \
936 panic("Merging JSR subroutines of different depth"); \
937 if (jsrtemp->target != jsrtemp2->target) \
938 panic("Merging different JSR subroutines"); \
939 jsrtemp = jsrtemp->next; \
940 jsrtemp2 = jsrtemp2->next; \
943 /* TYPECHECK_ADD_JSR: add a JSR target to the current JSR target chain
944 * and store the resulting chain in the target block.
947 * jsrchain...current JSR target chain
948 * tbptr.....the basic block targeted by the JSR
949 * numlocals..number of local variables
950 * jsrbuffer..JSR target chain for each basic block
954 #define TYPECHECK_ADD_JSR \
956 LOG1("adding JSR to block %04d",(tbptr)-block); \
957 jsrtemp = jsrchain; \
959 if (jsrtemp->target == tbptr) \
960 panic("recursive JSR call"); \
961 jsrtemp = jsrtemp->next; \
963 jsrtemp = (jsr_record *) dump_alloc(sizeof(jsr_record)+(numlocals-1)*sizeof(u1)); \
964 jsrtemp->target = (tbptr); \
965 jsrtemp->next = jsrchain; \
966 jsrtemp->sbr_touched = NULL; \
967 memset(&jsrtemp->touched,TOUCHED_NO,sizeof(u1)*numlocals); \
968 jsrbuffer[tbptr-block] = jsrtemp; \
971 /* TYPECHECK_COPYJSR: copy the current JSR chain to the target block.
974 * chain......current JSR target chain
975 * tbptr.....the basic block targeted by the JSR
976 * numlocals..number of local variables
977 * jsrbuffer..JSR target chain for each basic block
978 * touched....current touched flags of local variables
982 #define TYPECHECK_COPYJSR(chain) \
984 LOG("TYPECHECK_COPYJSR"); \
986 jsrtemp = (jsr_record *) dump_alloc(sizeof(jsr_record)+(numlocals-1)*sizeof(u1)); \
987 jsrtemp->target = (chain)->target; \
988 jsrtemp->next = (chain)->next; \
989 jsrtemp->sbr_touched = NULL; \
990 memcpy(&jsrtemp->touched,touched,sizeof(u1)*numlocals); \
991 jsrbuffer[tbptr-block] = jsrtemp; \
994 jsrbuffer[tbptr-block] = NULL; \
997 /* TYPECHECK_BRANCH_BACKWARDS: executed when control flow moves
998 * backwards. Checks if there are uninitialized objects on the
999 * stack or in local variables.
1001 * dst........current output stack pointer (not needed for REACH_THROW)
1002 * vtype......current local variable types
1003 * vinfo......current local variable typeinfos
1007 #define TYPECHECK_BRANCH_BACKWARDS \
1009 LOG("BACKWARDS!"); \
1011 while (srcstack) { \
1012 if (srcstack->type == TYPE_ADR && \
1013 TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo)) \
1014 panic("Branching backwards with uninitialized object on stack"); \
1015 srcstack = srcstack->prev; \
1017 for (macro_i=0; macro_i<numlocals; ++macro_i) \
1018 if (localset->td[macro_i].type == TYPE_ADR && \
1019 TYPEINFO_IS_NEWOBJECT(localset->td[macro_i].info)) \
1020 panic("Branching backwards with uninitialized object in local variable"); \
1023 /* XXX convert this into a function */
1024 /* TYPECHECK_REACH: executed, when the target block (tbptr) can be reached
1025 * from the current block (bptr). The types of local variables and
1026 * stack slots are propagated to the target block.
1028 * bptr.......current block
1029 * tbptr......target block
1030 * dst........current output stack pointer (not needed for REACH_THROW)
1031 * numlocals..number of local variables
1032 * vtype......current local variable types
1033 * vinfo......current local variable typeinfos
1034 * jsrchain...current JSR target chain
1035 * jsrbuffer..JSR target chain for each basic block
1036 * way........in which way the block is reached (REACH_ constant)
1037 * touched....current touched flags of local variables
1039 * repeat.....changed to true if a block before the current
1042 * ttype, tinfo, srcstack, dststack, changed, macro_i
1044 #define TYPECHECK_REACH(way) \
1046 LOG2("reaching block %04d (%d)",tbptr-block,way); \
1047 if (tbptr <= bptr) \
1048 TYPECHECK_BRANCH_BACKWARDS; \
1049 repeat |= typestate_reach(localbuf,bptr,tbptr,dst, \
1050 localset,numlocals); \
1054 /* TYPECHECK_LEAVE: executed when the method is exited non-abruptly
1056 * class........class of the current method
1057 * numlocals....number of local variables
1058 * vtype........current local variable types
1059 * vinfo........current local variable typeinfos
1060 * initmethod...true if this is an <init> method
1062 #define TYPECHECK_LEAVE \
1064 if (initmethod && class != class_java_lang_Object) { \
1065 /* check the marker variable */ \
1066 LOG("Checking <init> marker"); \
1067 if (!typevectorset_checktype(localset,numlocals-1,TYPE_INT))\
1068 panic("<init> method does not initialize 'this'"); \
1072 /****************************************************************************/
1074 /****************************************************************************/
1076 #define MAXPARAMS 255
1078 /* typecheck is called directly after analyse_stack */
1082 int b_count, b_index;
1083 stackptr curstack; /* input stack top for current instruction */
1084 stackptr srcstack; /* source stack for copying and merging */
1085 stackptr dststack; /* target stack for copying and merging */
1086 int opcode; /* current opcode */
1087 int macro_i, i; /* temporary counters */
1088 int len; /* for counting instructions, etc. */
1089 bool superblockend; /* true if no fallthrough to next block */
1090 bool repeat; /* if true, blocks are iterated over again */
1091 bool changed; /* used in macros */
1092 instruction *iptr; /* pointer to current instruction */
1093 basicblock *bptr; /* pointer to current basic block */
1094 basicblock *tbptr; /* temporary for target block */
1095 int numlocals; /* number of local variables */
1096 int validlocals; /* number of valid local variable indices */
1098 void *localbuf; /* local variable types for each block start */
1099 typevector *localset; /* typevector set for local variables */
1100 typevector *lset; /* temporary pointer */
1101 typedescriptor *td; /* temporary pointer */
1103 typeinfo tempinfo; /* temporary */
1105 typedescriptor returntype; /* return type of current method */
1107 u1 *ptype; /* parameter types of called method */
1108 typeinfo *pinfo; /* parameter typeinfos of called method */
1109 int rtype; /* return type of called method */
1110 typeinfo rinfo; /* typeinfo for return type of called method */
1111 stackptr dst; /* output stack of current instruction */
1112 basicblock **tptr; /* pointer into target list of switch instr. */
1113 jsr_record **jsrbuffer; /* JSR target chain for each basic block */
1114 jsr_record *jsrchain; /* JSR chain for current block */
1115 jsr_record *jsrtemp,*jsrtemp2; /* temporary variables */
1116 jsr_record *subroutine; /* jsr_record of the current subroutine */
1117 u1 *touched; /* touched flags for local variables */
1118 xtable **handlers; /* active exception handlers */
1119 classinfo *cls; /* temporary */
1120 bool maythrow; /* true if this instruction may throw */
1121 utf *name_init; /* "<init>" */
1122 bool initmethod; /* true if this is an "<init>" method */
1123 builtin_descriptor *builtindesc;
1125 #ifdef TYPECHECK_STATISTICS
1126 int count_iterations = 0;
1129 LOGSTR("\n==============================================================================\n");
1130 DOLOG(show_icmd_method());
1131 LOGSTR("\n==============================================================================\n");
1132 LOGimpSTR("Entering typecheck: ");
1133 LOGimpSTRu(method->name);
1135 LOGimpSTRu(method->descriptor);
1136 LOGimpSTR(" (class ");
1137 LOGimpSTRu(method->class->name);
1140 name_init = utf_new_char("<init>");
1141 initmethod = (method->name == name_init);
1143 ptype = DMNEW(u1,MAXPARAMS);
1144 pinfo = DMNEW(typeinfo,MAXPARAMS);
1146 LOG("Buffer allocated.\n");
1148 /* reset all BBFINISHED blocks to BBTYPECHECK_UNDEF. */
1149 b_count = block_count;
1151 while (--b_count >= 0) {
1152 #ifdef TYPECHECK_DEBUG
1153 if (bptr->flags != BBFINISHED && bptr->flags != BBDELETED
1154 && bptr->flags != BBUNDEF)
1157 LOGSTR1("block flags: %d\n",bptr->flags); LOGFLUSH;
1158 panic("Internal error: Unexpected block flags in typecheck()");
1161 if (bptr->flags >= BBFINISHED) {
1162 bptr->flags = BBTYPECHECK_UNDEF;
1167 /* The first block is always reached */
1168 if (block_count && block[0].flags == BBTYPECHECK_UNDEF)
1169 block[0].flags = BBTYPECHECK_REACHED;
1171 LOG("Blocks reset.\n");
1173 /* number of local variables */
1175 /* In <init> methods we use an extra local variable to signal if
1176 * the 'this' reference has been initialized. */
1177 numlocals = maxlocals;
1178 validlocals = numlocals;
1179 if (initmethod) numlocals++;
1181 /* allocate the buffers for local variables */
1182 localbuf = DMNEW_TYPEVECTOR(block_count+1, numlocals);
1183 localset = MGET_TYPEVECTOR(localbuf,block_count,numlocals);
1184 memset(localbuf,0,(block_count+1) * TYPEVECTOR_SIZE(numlocals));
1186 LOG("Variable buffer allocated.\n");
1188 /* allocate the buffer for storing JSR target chains */
1189 jsrbuffer = DMNEW(jsr_record*,block_count);
1190 memset(jsrbuffer,0,block_count * sizeof(jsr_record*));
1193 LOG("jsrbuffer initialized.\n");
1195 /* allocate the buffer of active exception handlers */
1196 handlers = DMNEW(xtable*,method->exceptiontablelength + 1);
1198 /* initialize the variable types of the first block */
1199 /* to the types of the arguments */
1200 lset = MGET_TYPEVECTOR(localbuf,0,numlocals);
1204 /* if this is an instance method initialize the "this" ref type */
1205 if (!(method->flags & ACC_STATIC)) {
1206 td->type = TYPE_ADDRESS;
1208 TYPEINFO_INIT_NEWOBJECT(td->info,NULL);
1210 TYPEINFO_INIT_CLASSINFO(td->info,class);
1215 LOG("'this' argument set.\n");
1217 /* the rest of the arguments and the return type */
1218 i = typedescriptors_init_from_method_args(td,method->descriptor,
1220 true, /* two word types use two slots */
1223 i = numlocals - (td - lset->td);
1225 td->type = TYPE_VOID;
1229 LOG("Arguments set.\n");
1231 /* initialize the input stack of exception handlers */
1232 for (i=0; i<method->exceptiontablelength; ++i) {
1233 cls = extable[i].catchtype;
1234 if (!cls) cls = class_java_lang_Throwable;
1235 LOGSTR1("handler %i: ",i); LOGSTRu(cls->name); LOGNL;
1236 TYPEINFO_INIT_CLASSINFO(extable[i].handler->instack->typeinfo,cls);
1239 LOG("Exception handler stacks set.\n");
1241 /* loop while there are still blocks to be checked */
1243 TYPECHECK_COUNT(count_iterations);
1247 b_count = block_count;
1250 while (--b_count >= 0) {
1251 LOGSTR1("---- BLOCK %04d, ",bptr-block);
1252 LOGSTR1("blockflags: %d\n",bptr->flags);
1255 if (bptr->flags == BBTYPECHECK_REACHED) {
1256 LOGSTR1("\n---- BLOCK %04d ------------------------------------------------\n",bptr-block);
1259 superblockend = false;
1260 bptr->flags = BBFINISHED;
1261 b_index = bptr - block;
1263 /* init stack at the start of this block */
1264 curstack = bptr->instack;
1266 /* determine the active exception handlers for this block */
1267 /* XXX could use a faster algorithm with sorted lists or
1270 for (i=0; i<method->exceptiontablelength; ++i) {
1271 if ((extable[i].start <= bptr) && (extable[i].end > bptr)) {
1272 LOG1("active handler L%03d",extable[i].handler->debug_nr);
1273 handlers[len++] = extable + i;
1276 handlers[len] = NULL;
1278 /* init variable types at the start of this block */
1279 COPY_TYPEVECTORSET(MGET_TYPEVECTOR(localbuf,b_index,numlocals),
1280 localset,numlocals);
1282 for (i=0; i<numlocals; ++i)
1283 if (localset->td[i].type == TYPE_ADR
1284 && TYPEINFO_IS_NEWOBJECT(localset->td[i].info))
1285 panic("Uninitialized object in local variable inside try block");
1287 /* init JSR target chain */
1288 if ((jsrchain = jsrbuffer[b_index]) != NULL) {
1289 #ifdef TYPECHECK_VERBOSE
1290 if (typecheckverbose) {
1291 LOGSTR("jsr chain:");
1294 LOGSTR1(" L%03d",jsrtemp->target->debug_nr);
1295 jsrtemp = jsrtemp->next;
1302 subroutine = jsrbuffer[jsrchain->target - block];
1303 memcpy(touched,jsrchain->touched,sizeof(u1)*numlocals);
1307 #ifdef TYPECHECK_VERBOSE
1308 if (typecheckverbose) {
1309 if (subroutine) {LOGSTR1("subroutine L%03d\n",subroutine->target->debug_nr);LOGFLUSH;}
1310 typestate_print(get_logfile(),curstack,localset,numlocals);
1315 /* loop over the instructions */
1317 iptr = bptr->iinstr;
1318 while (--len >= 0) {
1319 DOLOG(show_icmd(iptr,false));
1329 /****************************************/
1330 /* STACK MANIPULATIONS */
1332 /* We just need to copy the typeinfo */
1333 /* for slots containing addresses. */
1335 /* XXX We assume that the destination stack
1336 * slots were continuously allocated in
1337 * memory. (The current implementation in
1342 COPYTYPE(curstack,dst);
1346 COPYTYPE(curstack,dst);
1347 COPYTYPE(curstack,dst-2);
1348 COPYTYPE(curstack->prev,dst-1);
1352 COPYTYPE(curstack,dst);
1353 COPYTYPE(curstack,dst-3);
1354 COPYTYPE(curstack->prev,dst-1);
1355 COPYTYPE(curstack->prev->prev,dst-2);
1359 COPYTYPE(curstack,dst);
1360 COPYTYPE(curstack->prev,dst-1);
1364 COPYTYPE(curstack,dst);
1365 COPYTYPE(curstack->prev,dst-1);
1366 COPYTYPE(curstack,dst-3);
1367 COPYTYPE(curstack->prev,dst-4);
1368 COPYTYPE(curstack->prev->prev,dst-2);
1372 COPYTYPE(curstack,dst);
1373 COPYTYPE(curstack->prev,dst-1);
1374 COPYTYPE(curstack,dst-4);
1375 COPYTYPE(curstack->prev,dst-5);
1376 COPYTYPE(curstack->prev->prev,dst-2);
1377 COPYTYPE(curstack->prev->prev->prev,dst-3);
1381 COPYTYPE(curstack,dst-1);
1382 COPYTYPE(curstack->prev,dst);
1385 /****************************************/
1386 /* PRIMITIVE VARIABLE ACCESS */
1388 case ICMD_ILOAD: CHECK_ONEWORD(iptr->op1,TYPE_INT); break;
1389 case ICMD_FLOAD: CHECK_ONEWORD(iptr->op1,TYPE_FLOAT); break;
1390 case ICMD_IINC: CHECK_ONEWORD(iptr->op1,TYPE_INT); break;
1391 case ICMD_LLOAD: CHECK_TWOWORD(iptr->op1,TYPE_LONG); break;
1392 case ICMD_DLOAD: CHECK_TWOWORD(iptr->op1,TYPE_DOUBLE); break;
1394 case ICMD_FSTORE: STORE_ONEWORD(iptr->op1,TYPE_FLOAT); break;
1395 case ICMD_ISTORE: STORE_ONEWORD(iptr->op1,TYPE_INT); break;
1396 case ICMD_LSTORE: STORE_TWOWORD(iptr->op1,TYPE_LONG); break;
1397 case ICMD_DSTORE: STORE_TWOWORD(iptr->op1,TYPE_DOUBLE); break;
1399 /****************************************/
1400 /* LOADING ADDRESS FROM VARIABLE */
1403 INDEX_ONEWORD(iptr->op1);
1405 /* loading a returnAddress is not allowed */
1406 if (!typevectorset_checkreference(localset,iptr->op1))
1407 panic("illegal instruction: ALOAD loading non-reference");
1409 typevectorset_copymergedtype(localset,iptr->op1,&(dst->typeinfo));
1412 /****************************************/
1413 /* STORING ADDRESS TO VARIABLE */
1417 TYPEINFO_IS_NEWOBJECT(curstack->typeinfo))
1418 panic("Storing uninitialized object in local variable inside try block");
1420 INDEX_ONEWORD(iptr->op1);
1421 if (TYPESTACK_IS_RETURNADDRESS(curstack))
1422 typevectorset_store_retaddr(localset,iptr->op1,&(curstack->typeinfo));
1424 typevectorset_store(localset,iptr->op1,TYPE_ADDRESS,
1425 &(curstack->typeinfo));
1428 /****************************************/
1429 /* LOADING ADDRESS FROM ARRAY */
1432 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(curstack->prev->typeinfo))
1433 panic("illegal instruction: AALOAD on non-reference array");
1435 typeinfo_init_component(&curstack->prev->typeinfo,&dst->typeinfo);
1439 /****************************************/
1443 if (!TYPEINFO_IS_REFERENCE(curstack->prev->typeinfo))
1444 panic("illegal instruction: PUTFIELD on non-reference");
1445 if (TYPEINFO_IS_ARRAY(curstack->prev->typeinfo)) /* XXX arraystub */
1446 panic("illegal instruction: PUTFIELD on array");
1448 /* check if the value is assignable to the field */
1450 fieldinfo *fi = (fieldinfo*) iptr[0].val.a;
1452 if (TYPEINFO_IS_NEWOBJECT(curstack->prev->typeinfo)) {
1454 && !TYPEINFO_NEWOBJECT_INSTRUCTION(curstack->prev->typeinfo))
1456 /* uninitialized "this" instance */
1457 if (fi->class != class || (fi->flags & ACC_STATIC) != 0)
1458 panic("Setting unaccessible field in uninitialized object");
1461 panic("PUTFIELD on uninitialized object");
1465 if (!is_accessible(fi->flags,fi->class,fi->class,
1466 &(curstack->prev->typeinfo)))
1467 panic("PUTFIELD: field is not accessible");
1470 /* XXX ---> unify with ICMD_PUTSTATIC? */
1472 if (curstack->type != fi->type)
1473 panic("PUTFIELD type mismatch");
1474 if (fi->type == TYPE_ADR) {
1475 TYPEINFO_INIT_FROM_FIELDINFO(rinfo,fi);
1476 if (!typeinfo_is_assignable(&(curstack->typeinfo),
1478 panic("PUTFIELD reference type not assignable");
1484 case ICMD_PUTSTATIC:
1485 /* check if the value is assignable to the field */
1487 fieldinfo *fi = (fieldinfo*) iptr[0].val.a;
1489 if (!is_accessible(fi->flags,fi->class,fi->class,NULL))
1490 panic("PUTSTATIC: field is not accessible");
1492 if (curstack->type != fi->type)
1493 panic("PUTSTATIC type mismatch");
1494 if (fi->type == TYPE_ADR) {
1495 TYPEINFO_INIT_FROM_FIELDINFO(rinfo,fi);
1496 if (!typeinfo_is_assignable(&(curstack->typeinfo),
1498 panic("PUTSTATIC reference type not assignable");
1505 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1506 panic("illegal instruction: GETFIELD on non-reference");
1507 if (TYPEINFO_IS_ARRAY(curstack->typeinfo))
1508 panic("illegal instruction: GETFIELD on array");
1511 fieldinfo *fi = (fieldinfo *)(iptr->val.a);
1513 if (!is_accessible(fi->flags,fi->class,fi->class,
1514 &(curstack->typeinfo)))
1515 panic("GETFIELD: field is not accessible");
1517 if (dst->type == TYPE_ADR) {
1518 TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi);
1521 /* XXX check field type? */
1522 TYPEINFO_INIT_PRIMITIVE(dst->typeinfo);
1528 case ICMD_GETSTATIC:
1530 fieldinfo *fi = (fieldinfo *)(iptr->val.a);
1532 if (!is_accessible(fi->flags,fi->class,fi->class,NULL))
1533 panic("GETSTATIC: field is not accessible");
1535 if (dst->type == TYPE_ADR) {
1536 TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi);
1539 /* XXX check field type? */
1540 TYPEINFO_INIT_PRIMITIVE(dst->typeinfo);
1546 /****************************************/
1547 /* PRIMITIVE ARRAY ACCESS */
1549 case ICMD_ARRAYLENGTH:
1550 /* XXX should this also work on arraystubs? */
1551 if (!TYPEINFO_MAYBE_ARRAY(curstack->typeinfo))
1552 panic("illegal instruction: ARRAYLENGTH on non-array");
1556 /* XXX unify cases? */
1558 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_BOOLEAN)
1559 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_BYTE))
1560 panic("Array type mismatch");
1564 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_CHAR))
1565 panic("Array type mismatch");
1569 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_DOUBLE))
1570 panic("Array type mismatch");
1574 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_FLOAT))
1575 panic("Array type mismatch");
1579 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_INT))
1580 panic("Array type mismatch");
1584 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_SHORT))
1585 panic("Array type mismatch");
1589 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_LONG))
1590 panic("Array type mismatch");
1595 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_BOOLEAN)
1596 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_BYTE))
1597 panic("Array type mismatch");
1601 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_CHAR))
1602 panic("Array type mismatch");
1606 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_DOUBLE))
1607 panic("Array type mismatch");
1611 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_FLOAT))
1612 panic("Array type mismatch");
1616 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_INT))
1617 panic("Array type mismatch");
1621 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_SHORT))
1622 panic("Array type mismatch");
1626 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_LONG))
1627 panic("Array type mismatch");
1631 /****************************************/
1632 /* ADDRESS CONSTANTS */
1635 if (iptr->val.a == NULL)
1636 TYPEINFO_INIT_NULLTYPE(dst->typeinfo);
1638 /* XXX constants for builtin functions */
1639 /* string constants */
1640 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,class_java_lang_String);
1643 /****************************************/
1644 /* CHECKCAST AND INSTANCEOF */
1646 case ICMD_CHECKCAST:
1647 TYPECHECK_ADR(curstack);
1648 /* returnAddress is not allowed */
1649 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1650 panic("Illegal instruction: CHECKCAST on non-reference");
1652 /* XXX check if the cast can be done statically */
1653 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,(classinfo *)iptr[0].val.a);
1658 case ICMD_INSTANCEOF:
1659 TYPECHECK_ADR(curstack);
1660 /* returnAddress is not allowed */
1661 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1662 panic("Illegal instruction: INSTANCEOF on non-reference");
1664 /* XXX optimize statically? */
1667 /****************************************/
1668 /* BRANCH INSTRUCTIONS */
1671 superblockend = true;
1674 case ICMD_IFNONNULL:
1681 case ICMD_IF_ICMPEQ:
1682 case ICMD_IF_ICMPNE:
1683 case ICMD_IF_ICMPLT:
1684 case ICMD_IF_ICMPGE:
1685 case ICMD_IF_ICMPGT:
1686 case ICMD_IF_ICMPLE:
1687 case ICMD_IF_ACMPEQ:
1688 case ICMD_IF_ACMPNE:
1695 case ICMD_IF_LCMPEQ:
1696 case ICMD_IF_LCMPNE:
1697 case ICMD_IF_LCMPLT:
1698 case ICMD_IF_LCMPGE:
1699 case ICMD_IF_LCMPGT:
1700 case ICMD_IF_LCMPLE:
1701 tbptr = (basicblock *) iptr->target;
1703 /* propagate stack and variables to the target block */
1704 TYPECHECK_REACH(REACH_STD);
1708 /****************************************/
1711 case ICMD_TABLESWITCH:
1713 s4 *s4ptr = iptr->val.a;
1714 s4ptr++; /* skip default */
1715 i = *s4ptr++; /* low */
1716 i = *s4ptr++ - i + 2; /* +1 for default target */
1718 goto switch_instruction_tail;
1720 case ICMD_LOOKUPSWITCH:
1722 s4 *s4ptr = iptr->val.a;
1723 s4ptr++; /* skip default */
1724 i = *s4ptr++ + 1; /* count +1 for default */
1726 switch_instruction_tail:
1727 tptr = (basicblock **)iptr->target;
1731 LOG2("target %d is block %04d",(tptr-(basicblock **)iptr->target)-1,tbptr-block);
1732 TYPECHECK_REACH(REACH_STD);
1735 superblockend = true;
1738 /****************************************/
1739 /* RETURNS AND THROW */
1742 TYPEINFO_INIT_CLASSINFO(tempinfo,class_java_lang_Throwable);
1743 if (!typeinfo_is_assignable(&curstack->typeinfo,&tempinfo))
1744 panic("illegal instruction: ATHROW on non-Throwable");
1745 superblockend = true;
1750 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1751 panic("illegal instruction: ARETURN on non-reference");
1753 if (returntype.type != TYPE_ADDRESS
1754 || !typeinfo_is_assignable(&curstack->typeinfo,&(returntype.info)))
1755 panic("Return type mismatch");
1759 if (returntype.type != TYPE_INT) panic("Return type mismatch");
1763 if (returntype.type != TYPE_LONG) panic("Return type mismatch");
1767 if (returntype.type != TYPE_FLOAT) panic("Return type mismatch");
1771 if (returntype.type != TYPE_DOUBLE) panic("Return type mismatch");
1775 if (returntype.type != TYPE_VOID) panic("Return type mismatch");
1778 superblockend = true;
1782 /****************************************/
1783 /* SUBROUTINE INSTRUCTIONS */
1788 /* XXX This is a dirty hack. It is needed
1789 * because of the special handling of ICMD_JSR in stack.c
1791 dst = (stackptr) iptr->val.a;
1793 tbptr = (basicblock *) iptr->target;
1794 repeat |= typestate_jsr(localbuf,bptr,tbptr,dst,localset,numlocals);
1796 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,tbptr);
1798 LOG("reaching block...");
1800 /* add the target to the JSR target chain and */
1801 /* propagate stack and variables to the target block */
1802 TYPECHECK_REACH(REACH_JSR);
1804 /* set dst to the stack after the subroutine execution */
1805 /* XXX We assume (as in stack.c) that the
1806 * subroutine returns the stack as it was
1807 * before the JSR instruction. Is this
1812 /* Find the jsr_record of the called subroutine */
1813 jsrtemp = jsrbuffer[tbptr - block];
1815 /* Check if we already calculated (at least
1816 * for one RET) which variables the
1817 * subroutine touches.
1819 if (jsrtemp->sbr_touched) {
1820 /* Calculate the local variables after the subroutine call */
1821 for (i=0; i<numlocals; ++i)
1822 if (jsrtemp->sbr_touched[i] != TOUCHED_NO) {
1824 if ((vtype[i] = jsrtemp->sbr_vtype[i]) == TYPE_ADR)
1825 TYPEINFO_CLONE(jsrtemp->sbr_vinfo[i],vinfo[i]);
1828 /* continue after the JSR call */
1829 superblockend = false;
1832 /* We cannot proceed until the subroutine has been typechecked. */
1833 /* XXX actually we would not have to check this block again */
1834 bptr->flags = BBTYPECHECK_REACHED;
1836 superblockend = true;
1839 /* XXX may throw? I don't think so. */
1840 superblockend = true;
1844 /* check returnAddress variable */
1845 INDEX_ONEWORD(iptr->op1);
1846 if (!typevectorset_checkretaddr(localset,iptr->op1))
1847 panic("illegal instruction: RET using non-returnAddress variable");
1849 repeat |= typestate_ret(localbuf,bptr,curstack,
1850 localset,iptr->op1,numlocals);
1853 /* check if we are inside a subroutine */
1855 panic("RET outside of subroutine");
1857 /* check if the right returnAddress is used (XXX is this too strict?) */
1858 if ((basicblock*)TYPEINFO_RETURNADDRESS(vinfo[iptr->op1])
1859 != subroutine->target)
1860 panic("RET uses returnAddress of another subroutine");
1862 /* determine which variables are touched by this subroutine */
1863 /* and their types */
1864 if (subroutine->sbr_touched) {
1865 /* We have reached a RET in this subroutine before. */
1867 /* Check if there is more than one RET instruction
1868 * returning from this subroutine. */
1869 if (subroutine->sbr_ret != iptr)
1870 panic("JSR subroutine has more than one RET instruction");
1872 /* Merge the array of touched locals and their types */
1873 for (i=0; i<numlocals; ++i)
1874 subroutine->sbr_touched[i] |= touched[i];
1875 ttype = subroutine->sbr_vtype;
1876 tinfo = subroutine->sbr_vinfo;
1877 TYPECHECK_MERGEVARS;
1878 /* XXX check if subroutine changed types? */
1881 /* This is the first time we reach a RET in this subroutine */
1882 subroutine->sbr_ret = iptr;
1883 subroutine->sbr_touched = DMNEW(u1,numlocals);
1884 memcpy(subroutine->sbr_touched,touched,sizeof(u1)*numlocals);
1885 subroutine->sbr_vtype = DMNEW(u1,numlocals);
1886 memcpy(subroutine->sbr_vtype,vtype,sizeof(u1)*numlocals);
1887 subroutine->sbr_vinfo = DMNEW(typeinfo,numlocals);
1888 for (i=0; i<numlocals; ++i)
1889 if (vtype[i] == TYPE_ADR)
1890 TYPEINFO_CLONE(vinfo[i],subroutine->sbr_vinfo[i]);
1893 LOGSTR("subroutine touches:");
1894 DOLOG(typeinfo_print_locals(get_logfile(),subroutine->sbr_vtype,subroutine->sbr_vinfo,
1895 subroutine->sbr_touched,numlocals));
1898 /* XXX reach blocks after JSR statements */
1899 for (i=0; i<block_count; ++i) {
1901 LOG1("block L%03d",tbptr->debug_nr);
1902 if (tbptr->iinstr[tbptr->icount - 1].opc != ICMD_JSR)
1904 LOG("ends with JSR");
1905 if ((basicblock*) tbptr->iinstr[tbptr->icount - 1].target != subroutine->target)
1909 LOG1("RET reaches block L%03d",tbptr->debug_nr);
1911 /*TYPECHECK_REACH(REACH_RET);*/
1915 superblockend = true;
1918 /****************************************/
1921 case ICMD_INVOKEVIRTUAL:
1922 case ICMD_INVOKESPECIAL:
1923 case ICMD_INVOKESTATIC:
1924 case ICMD_INVOKEINTERFACE:
1926 methodinfo *mi = (methodinfo*) iptr->val.a;
1927 bool specialmethod = (mi->name->text[0] == '<');
1928 bool callinginit = (opcode == ICMD_INVOKESPECIAL && mi->name == name_init);
1930 classinfo *initclass;
1932 if (specialmethod && !callinginit)
1933 panic("Invalid invocation of special method");
1935 if (opcode == ICMD_INVOKESPECIAL) {
1936 /* XXX for INVOKESPECIAL: check if the invokation is done at all */
1938 /* (If callinginit the class is checked later.) */
1940 if (!builtin_isanysubclass(class,mi->class))
1941 panic("Illegal instruction: INVOKESPECIAL calling non-superclass method");
1945 /* fetch parameter types and return type */
1946 /* XXX might use dst->typeinfo directly if non void */
1948 if (opcode != ICMD_INVOKESTATIC) {
1949 ptype[0] = TYPE_ADR;
1950 TYPEINFO_INIT_CLASSINFO(pinfo[0],mi->class);
1953 typeinfo_init_from_method_args(mi->descriptor,ptype+i,pinfo+i,
1957 /* check parameter types */
1958 srcstack = curstack;
1959 i = mi->paramcount; /* number of parameters including 'this'*/
1962 if (srcstack->type != ptype[i])
1963 panic("Parameter type mismatch in method invocation");
1964 if (srcstack->type == TYPE_ADR) {
1965 LOGINFO(&(srcstack->typeinfo));
1967 if (i==0 && callinginit)
1969 /* typeinfo tempinfo; */
1971 /* first argument to <init> method */
1972 if (!TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo))
1973 panic("Calling <init> on initialized object");
1975 /* get the address of the NEW instruction */
1976 LOGINFO(&(srcstack->typeinfo));
1977 ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(srcstack->typeinfo);
1978 initclass = (ins) ? (classinfo*)ins[-1].val.a : method->class;
1979 LOGSTR("class: "); LOGSTRu(initclass->name); LOGNL;
1982 /* (This is checked below.) */
1983 /* TYPEINFO_INIT_CLASSINFO(tempinfo,initclass); */
1984 /* if (!typeinfo_is_assignable(&tempinfo,pinfo+0)) */
1985 /* panic("Parameter reference type mismatch in <init> invocation"); */
1988 if (!typeinfo_is_assignable(&(srcstack->typeinfo),pinfo+i))
1989 panic("Parameter reference type mismatch in method invocation");
1994 if (i) srcstack = srcstack->prev;
1997 /* XXX We should resolve the method and pass its
1998 * class as implementingclass to is_accessible. */
1999 if (!is_accessible(mi->flags,mi->class,NULL,
2000 (opcode == ICMD_INVOKESTATIC) ? NULL
2001 : &(srcstack->typeinfo)))
2002 panic("Invoking unaccessible method");
2004 LOG("checking return type");
2005 if (rtype != TYPE_VOID) {
2006 if (rtype != dst->type)
2007 panic("Return type mismatch in method invocation");
2008 TYPEINFO_COPY(rinfo,dst->typeinfo);
2012 LOG("replacing uninitialized object");
2013 /* replace uninitialized object type on stack */
2016 if (srcstack->type == TYPE_ADR
2017 && TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo)
2018 && TYPEINFO_NEWOBJECT_INSTRUCTION(srcstack->typeinfo) == ins)
2020 LOG("replacing uninitialized type on stack");
2021 TYPEINFO_INIT_CLASSINFO(srcstack->typeinfo,initclass);
2023 srcstack = srcstack->prev;
2025 /* replace uninitialized object type in locals */
2026 typevectorset_init_object(localset,ins,initclass,numlocals);
2028 /* initializing the 'this' reference? */
2030 #ifdef TYPECHECK_DEBUG
2032 panic("Internal error: calling <init> on this in non-<init> method.");
2034 /* must be <init> of current class or direct superclass */
2035 if (mi->class != class && mi->class != class->super)
2036 panic("<init> calling <init> of the wrong class");
2038 /* set our marker variable to type int */
2039 LOG("setting <init> marker");
2040 typevectorset_store(localset,numlocals-1,TYPE_INT,NULL);
2043 /* initializing an instance created with NEW */
2044 /* XXX is this strictness ok? */
2045 if (mi->class != initclass)
2046 panic("Calling <init> method of the wrong class");
2053 case ICMD_MULTIANEWARRAY:
2056 arraydescriptor *desc;
2058 /* check the array lengths on the stack */
2060 if (i<1) panic("MULTIANEWARRAY with dimensions < 1");
2061 srcstack = curstack;
2064 panic("MULTIANEWARRAY missing array length");
2065 if (srcstack->type != TYPE_INT)
2066 panic("MULTIANEWARRAY using non-int as array length");
2067 srcstack = srcstack->prev;
2070 /* check array descriptor */
2071 arrayvftbl = (vftbl*) iptr[0].val.a;
2073 panic("MULTIANEWARRAY with unlinked class");
2074 if ((desc = arrayvftbl->arraydesc) == NULL)
2075 panic("MULTIANEWARRAY with non-array class");
2076 if (desc->dimension < iptr[0].op1)
2077 panic("MULTIANEWARRAY dimension to high");
2079 /* set the array type of the result */
2080 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,arrayvftbl->class);
2086 if (ISBUILTIN(BUILTIN_aastore)) {
2087 TYPECHECK_ADR(curstack);
2088 TYPECHECK_INT(curstack->prev);
2089 TYPECHECK_ADR(curstack->prev->prev);
2090 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(curstack->prev->prev->typeinfo))
2091 panic("illegal instruction: AASTORE to non-reference array");
2095 typeinfo_init_component(&curstack->prev->prev->typeinfo,&tempinfo);
2096 if (!typeinfo_is_assignable(&curstack->typeinfo,&tempinfo))
2097 panic("illegal instruction: AASTORE to incompatible type");
2101 /* XXX put these checks in a function */
2102 builtindesc = builtin_desc;
2103 while (builtindesc->opcode && builtindesc->builtin
2104 != (functionptr) iptr->val.a) builtindesc++;
2105 if (!builtindesc->opcode) {
2106 dolog("Builtin not in table: %s",icmd_builtin_name((functionptr) iptr->val.a));
2107 panic("Internal error: builtin not found in table");
2109 TYPECHECK_ARGS3(builtindesc->type_s3,builtindesc->type_s2,builtindesc->type_s1);
2111 maythrow = true; /* XXX better safe than sorry */
2115 if (ISBUILTIN(BUILTIN_newarray))
2118 TYPECHECK_INT(curstack->prev);
2119 if (iptr[-1].opc != ICMD_ACONST)
2120 panic("illegal instruction: builtin_newarray without classinfo");
2121 vft = (vftbl *)iptr[-1].val.a;
2123 panic("ANEWARRAY with unlinked class");
2124 if (!vft->arraydesc)
2125 panic("ANEWARRAY with non-array class");
2126 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,vft->class);
2128 else if (ISBUILTIN(BUILTIN_arrayinstanceof))
2131 TYPECHECK_ADR(curstack->prev);
2132 if (iptr[-1].opc != ICMD_ACONST)
2133 panic("illegal instruction: builtin_arrayinstanceof without classinfo");
2134 vft = (vftbl *)iptr[-1].val.a;
2136 panic("INSTANCEOF with unlinked class");
2137 if (!vft->arraydesc)
2138 panic("internal error: builtin_arrayinstanceof with non-array class");
2140 else if (ISBUILTIN(BUILTIN_checkarraycast)) {
2142 TYPECHECK_ADR(curstack->prev);
2143 if (iptr[-1].opc != ICMD_ACONST)
2144 panic("illegal instruction: BUILTIN_checkarraycast without classinfo");
2145 vft = (vftbl *)iptr[-1].val.a;
2147 panic("CHECKCAST with unlinked class");
2148 if (!vft->arraydesc)
2149 panic("internal error: builtin_checkarraycast with non-array class");
2150 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,vft->class);
2153 builtindesc = builtin_desc;
2154 while (builtindesc->opcode && builtindesc->builtin
2155 != (functionptr) iptr->val.a) builtindesc++;
2156 if (!builtindesc->opcode) {
2157 dolog("Builtin not in table: %s",icmd_builtin_name((functionptr) iptr->val.a));
2158 panic("Internal error: builtin not found in table");
2160 TYPECHECK_ARGS2(builtindesc->type_s2,builtindesc->type_s1);
2162 maythrow = true; /* XXX better safe than sorry */
2166 if (ISBUILTIN(BUILTIN_new)) {
2168 if (iptr[-1].opc != ICMD_ACONST)
2169 panic("illegal instruction: builtin_new without classinfo");
2170 cls = (classinfo *) iptr[-1].val.a;
2172 panic("Internal error: NEW with unlinked class");
2173 /* The following check also forbids array classes and interfaces: */
2174 if ((cls->flags & ACC_ABSTRACT) != 0)
2175 panic("Invalid instruction: NEW creating instance of abstract class");
2176 TYPEINFO_INIT_NEWOBJECT(dst->typeinfo,iptr);
2178 /* XXX unify the following cases? */
2179 else if (ISBUILTIN(BUILTIN_newarray_boolean)) {
2180 TYPECHECK_INT(curstack);
2181 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BOOLEAN);
2183 else if (ISBUILTIN(BUILTIN_newarray_char)) {
2184 TYPECHECK_INT(curstack);
2185 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_CHAR);
2187 else if (ISBUILTIN(BUILTIN_newarray_float)) {
2188 TYPECHECK_INT(curstack);
2189 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_FLOAT);
2191 else if (ISBUILTIN(BUILTIN_newarray_double)) {
2192 TYPECHECK_INT(curstack);
2193 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_DOUBLE);
2195 else if (ISBUILTIN(BUILTIN_newarray_byte)) {
2196 TYPECHECK_INT(curstack);
2197 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BYTE);
2199 else if (ISBUILTIN(BUILTIN_newarray_short)) {
2200 TYPECHECK_INT(curstack);
2201 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_SHORT);
2203 else if (ISBUILTIN(BUILTIN_newarray_int)) {
2204 TYPECHECK_INT(curstack);
2205 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_INT);
2207 else if (ISBUILTIN(BUILTIN_newarray_long)) {
2208 TYPECHECK_INT(curstack);
2209 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_LONG);
2212 builtindesc = builtin_desc;
2213 while (builtindesc->opcode && builtindesc->builtin
2214 != (functionptr) iptr->val.a) builtindesc++;
2215 if (!builtindesc->opcode) {
2216 dolog("Builtin not in table: %s",icmd_builtin_name((functionptr) iptr->val.a));
2217 panic("Internal error: builtin not found in table");
2219 TYPECHECK_ARGS1(builtindesc->type_s1);
2221 maythrow = true; /* XXX better safe than sorry */
2224 /****************************************/
2225 /* UNCHECKED OPERATIONS */
2227 /* These ops have no input or output to be checked */
2228 /* (apart from the checks done in analyse_stack). */
2229 /* XXX only add cases for them in debug mode? */
2236 /****************************************/
2237 /* SIMPLE EXCEPTION THROWING TESTS */
2239 case ICMD_CHECKASIZE:
2240 /* The argument to CHECKASIZE is typechecked by
2241 * typechecking the array creation instructions. */
2244 case ICMD_NULLCHECKPOP:
2245 /* NULLCHECKPOP just requires that the stack top
2246 * is an address. This is checked in stack.c */
2251 /****************************************/
2252 /* INSTRUCTIONS WHICH SHOULD HAVE BEEN */
2253 /* REPLACED BY OTHER OPCODES */
2257 case ICMD_ANEWARRAY:
2258 case ICMD_MONITORENTER:
2259 case ICMD_MONITOREXIT:
2261 /* XXX only check this in debug mode? */
2262 LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
2263 LOG("Should have been converted to builtin function call.");
2264 panic("Internal error: unexpected instruction encountered");
2267 case ICMD_READONLY_ARG:
2268 case ICMD_CLEAR_ARGREN:
2269 /* XXX only check this in debug mode? */
2270 LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
2271 LOG("Should have been replaced in stack.c.");
2272 panic("Internal error: unexpected pseudo instruction encountered");
2275 /****************************************/
2276 /* ARITHMETIC AND CONVERSION */
2278 /*********************************************
2279 * Instructions below...
2280 * *) don't operate on local variables,
2281 * *) don't operate on references,
2282 * *) don't operate on returnAddresses.
2284 * (These instructions are typechecked in
2286 ********************************************/
2288 /* Instructions which may throw a runtime exception: */
2298 /* Instructions which never throw a runtime exception: */
2299 /* XXX only add cases for them in debug mode? */
2306 case ICMD_IFEQ_ICONST:
2307 case ICMD_IFNE_ICONST:
2308 case ICMD_IFLT_ICONST:
2309 case ICMD_IFGE_ICONST:
2310 case ICMD_IFGT_ICONST:
2311 case ICMD_IFLE_ICONST:
2312 case ICMD_ELSE_ICONST:
2334 case ICMD_IREM0X10001:
2335 case ICMD_LREM0X10001:
2338 case ICMD_IADDCONST:
2339 case ICMD_ISUBCONST:
2340 case ICMD_IMULCONST:
2341 case ICMD_IANDCONST:
2343 case ICMD_IXORCONST:
2344 case ICMD_ISHLCONST:
2345 case ICMD_ISHRCONST:
2346 case ICMD_IUSHRCONST:
2348 case ICMD_LADDCONST:
2349 case ICMD_LSUBCONST:
2350 case ICMD_LMULCONST:
2351 case ICMD_LANDCONST:
2353 case ICMD_LXORCONST:
2354 case ICMD_LSHLCONST:
2355 case ICMD_LSHRCONST:
2356 case ICMD_LUSHRCONST:
2373 case ICMD_INT2SHORT:
2376 case ICMD_LCMPCONST:
2397 /****************************************/
2400 LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
2401 panic("Missing ICMD code during typecheck");
2404 /* the output of this instruction becomes the current stack */
2407 /* reach exception handlers for this instruction */
2409 LOG("reaching exception handlers");
2411 while (handlers[i]) {
2412 tbptr = handlers[i]->handler;
2413 repeat |= typestate_reach(localbuf,bptr,tbptr,
2414 tbptr->instack,localset,numlocals);
2420 DOLOG(typeinfo_print_block(get_logfile(),curstack,numlocals,vtype,vinfo,(jsrchain) ? touched : NULL));
2425 } /* while instructions */
2427 LOG("instructions done");
2428 LOGSTR("RESULT=> ");
2429 DOLOG(typestate_print(get_logfile(),curstack,localset,numlocals));
2432 /* propagate stack and variables to the following block */
2433 if (!superblockend) {
2434 LOG("reaching following block");
2436 while (tbptr->flags == BBDELETED) {
2438 #ifdef TYPECHECK_DEBUG
2439 if ((tbptr-block) >= block_count)
2440 panic("Control flow falls off the last block");
2443 TYPECHECK_REACH(REACH_STD);
2446 } /* if block has to be checked */
2448 } /* while blocks */
2450 LOGIF(repeat,"repeat=true");
2453 #ifdef TYPECHECK_STATISTICS
2454 dolog("Typechecker did %4d iterations",count_iterations);
2457 #ifdef TYPECHECK_DEBUG
2458 for (i=0; i<block_count; ++i) {
2459 if (block[i].flags != BBDELETED
2460 && block[i].flags != BBUNDEF
2461 && block[i].flags != BBFINISHED
2462 && block[i].flags != BBTYPECHECK_UNDEF) /* typecheck may never reach
2463 * some exception handlers,
2466 LOG2("block L%03d has invalid flags after typecheck: %d",
2467 block[i].debug_nr,block[i].flags);
2468 panic("Invalid block flags after typecheck");
2473 /* Reset blocks we never reached */
2474 for (i=0; i<block_count; ++i) {
2475 if (block[i].flags == BBTYPECHECK_UNDEF)
2476 block[i].flags = BBFINISHED;
2479 LOGimp("exiting typecheck");
2484 #endif /* CACAO_TYPECHECK */
2487 * These are local overrides for various environment variables in Emacs.
2488 * Please do not remove this and leave it at the end of the file, where
2489 * Emacs will automagically detect them.
2490 * ---------------------------------------------------------------------
2493 * indent-tabs-mode: t