1 /* vm/jit/verify/typecheck.c - typechecking (part of bytecode verification)
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 Institut f. Computersprachen - TU Wien
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 1795 2004-12-21 15:15:26Z jowenn $
35 #include "vm/global.h" /* must be here because of CACAO_TYPECHECK */
37 #ifdef CACAO_TYPECHECK
40 /* #include "main.h" */
41 #include "mm/memory.h"
42 #include "toolbox/logging.h"
43 #include "native/native.h"
44 #include "vm/builtin.h"
45 #include "vm/loader.h"
46 #include "vm/options.h"
47 #include "vm/tables.h"
48 #include "vm/jit/jit.h"
49 #include "vm/jit/stack.h"
52 /****************************************************************************/
54 /****************************************************************************/
56 #ifdef TYPECHECK_VERBOSE_OPT
57 bool typecheckverbose = false;
58 #define DOLOG(action) do { if (typecheckverbose) {action;} } while(0)
63 #ifdef TYPECHECK_VERBOSE
64 #define TYPECHECK_VERBOSE_IMPORTANT
65 #define LOG(str) DOLOG(log_text(str))
66 #define LOG1(str,a) DOLOG(dolog(str,a))
67 #define LOG2(str,a,b) DOLOG(dolog(str,a,b))
68 #define LOG3(str,a,b,c) DOLOG(dolog(str,a,b,c))
69 #define LOGIF(cond,str) DOLOG(do {if (cond) log_text(str);} while(0))
71 #define LOGINFO(info) DOLOG(do {typeinfo_print_short(get_logfile(),(info));log_plain("\n");} while(0))
74 #define typevectorset_print(x,y,z)
76 #define LOGFLUSH DOLOG(fflush(get_logfile()))
77 #define LOGNL DOLOG(log_plain("\n"))
78 #define LOGSTR(str) DOLOG(log_plain(str))
79 #define LOGSTR1(str,a) DOLOG(dolog_plain(str,a))
80 #define LOGSTR2(str,a,b) DOLOG(dolog_plain(str,a,b))
81 #define LOGSTR3(str,a,b,c) DOLOG(dolog_plain(str,a,b,c))
82 #define LOGSTRu(utf) DOLOG(log_plain_utf(utf))
87 #define LOG3(str,a,b,c)
88 #define LOGIF(cond,str)
93 #define LOGSTR1(str,a)
94 #define LOGSTR2(str,a,b)
95 #define LOGSTR3(str,a,b,c)
99 #ifdef TYPECHECK_VERBOSE_IMPORTANT
100 #define LOGimp(str) DOLOG(log_text(str))
101 #define LOGimpSTR(str) DOLOG(log_plain(str))
102 #define LOGimpSTRu(utf) DOLOG(log_plain_utf(utf))
105 #define LOGimpSTR(str)
106 #define LOGimpSTRu(utf)
109 #if defined(TYPECHECK_VERBOSE) || defined(TYPECHECK_VERBOSE_IMPORTANT)
115 typestack_print(FILE *file,stackptr stack)
117 #ifdef TYPEINFO_DEBUG
119 typeinfo_print_stacktype(file,stack->type,&stack->typeinfo);
121 if (stack) fprintf(file," ");
128 typestate_print(FILE *file,stackptr instack,typevector *localset,int size)
130 fprintf(file,"Stack: ");
131 typestack_print(file,instack);
132 fprintf(file," Locals:");
133 typevectorset_print(file,localset,size);
138 /****************************************************************************/
140 /****************************************************************************/
142 #ifdef TYPECHECK_DEBUG
143 /*#define TYPECHECK_STATISTICS*/
146 #ifdef TYPECHECK_STATISTICS
147 #define STAT_ITERATIONS 10
148 #define STAT_BLOCKS 10
149 #define STAT_LOCALS 16
151 static int stat_typechecked = 0;
152 static int stat_typechecked_jsr = 0;
153 static int stat_iterations[STAT_ITERATIONS+1] = { 0 };
154 static int stat_reached = 0;
155 static int stat_copied = 0;
156 static int stat_merged = 0;
157 static int stat_merging_changed = 0;
158 static int stat_backwards = 0;
159 static int stat_blocks[STAT_BLOCKS+1] = { 0 };
160 static int stat_locals[STAT_LOCALS+1] = { 0 };
161 static int stat_ins = 0;
162 static int stat_ins_field = 0;
163 static int stat_ins_invoke = 0;
164 static int stat_ins_primload = 0;
165 static int stat_ins_aload = 0;
166 static int stat_ins_builtin = 0;
167 static int stat_ins_builtin_gen = 0;
168 static int stat_ins_branch = 0;
169 static int stat_ins_switch = 0;
170 static int stat_ins_unchecked = 0;
171 static int stat_handlers_reached = 0;
172 static int stat_savedstack = 0;
174 #define TYPECHECK_COUNT(cnt) (cnt)++
175 #define TYPECHECK_COUNTIF(cond,cnt) do{if(cond) (cnt)++;} while(0)
176 #define TYPECHECK_COUNT_FREQ(array,val,limit) \
178 if ((val) < (limit)) (array)[val]++; \
179 else (array)[limit]++; \
182 static void print_freq(FILE *file,int *array,int limit)
185 for (i=0; i<limit; ++i)
186 fprintf(file," %3d: %8d\n",i,array[i]);
187 fprintf(file," =>%3d: %8d\n",limit,array[limit]);
190 void typecheck_print_statistics(FILE *file) {
191 fprintf(file,"typechecked methods: %8d\n",stat_typechecked);
192 fprintf(file,"methods with JSR : %8d\n",stat_typechecked_jsr);
193 fprintf(file,"reached blocks : %8d\n",stat_reached);
194 fprintf(file,"copied states : %8d\n",stat_copied);
195 fprintf(file,"merged states : %8d\n",stat_merged);
196 fprintf(file,"merging changed : %8d\n",stat_merging_changed);
197 fprintf(file,"backwards branches : %8d\n",stat_backwards);
198 fprintf(file,"handlers reached : %8d\n",stat_handlers_reached);
199 fprintf(file,"saved stack (times): %8d\n",stat_savedstack);
200 fprintf(file,"instructions : %8d\n",stat_ins);
201 fprintf(file," field access : %8d\n",stat_ins_field);
202 fprintf(file," invocations : %8d\n",stat_ins_invoke);
203 fprintf(file," load primitive : %8d\n",stat_ins_primload);
204 fprintf(file," load address : %8d\n",stat_ins_aload);
205 fprintf(file," builtins : %8d\n",stat_ins_builtin);
206 fprintf(file," generic : %8d\n",stat_ins_builtin_gen);
207 fprintf(file," unchecked : %8d\n",stat_ins_unchecked);
208 fprintf(file," branches : %8d\n",stat_ins_branch);
209 fprintf(file," switches : %8d\n",stat_ins_switch);
210 fprintf(file,"iterations used:\n");
211 print_freq(file,stat_iterations,STAT_ITERATIONS);
212 fprintf(file,"basic blocks per method / 10:\n");
213 print_freq(file,stat_blocks,STAT_BLOCKS);
214 fprintf(file,"locals:\n");
215 print_freq(file,stat_locals,STAT_LOCALS);
220 #define TYPECHECK_COUNT(cnt)
221 #define TYPECHECK_COUNTIF(cond,cnt)
222 #define TYPECHECK_COUNT_FREQ(array,val,limit)
225 /****************************************************************************/
226 /* TYPESTACK FUNCTIONS */
227 /****************************************************************************/
229 #define TYPESTACK_IS_RETURNADDRESS(sptr) \
230 TYPE_IS_RETURNADDRESS((sptr)->type,(sptr)->typeinfo)
232 #define TYPESTACK_IS_REFERENCE(sptr) \
233 TYPE_IS_REFERENCE((sptr)->type,(sptr)->typeinfo)
235 #define TYPESTACK_RETURNADDRESSSET(sptr) \
236 ((typeinfo_retaddr_set*)TYPEINFO_RETURNADDRESS((sptr)->typeinfo))
238 #define RETURNADDRESSSET_SEEK(set,pos) \
239 do {int i; for (i=pos;i--;) set=set->alt;} while(0)
241 #define TYPESTACK_COPY(sp,copy) \
242 do {for(; sp; sp=sp->prev, copy=copy->prev) { \
243 copy->type = sp->type; \
244 TYPEINFO_COPY(sp->typeinfo,copy->typeinfo); \
248 typestack_copy(stackptr dst,stackptr y,typevector *selected)
251 typeinfo_retaddr_set *sety;
252 typeinfo_retaddr_set *new;
253 typeinfo_retaddr_set **next;
256 for (;dst; dst=dst->prev, y=y->prev) {
257 if (!y) panic("Stack depth mismatch 1");
258 if (dst->type != y->type)
259 panic("Stack type mismatch 1");
260 LOG3("copy %p -> %p (type %d)",y,dst,dst->type);
261 if (dst->type == TYPE_ADDRESS) {
262 if (TYPEINFO_IS_PRIMITIVE(y->typeinfo)) {
263 /* We copy the returnAddresses from the selected
266 LOG("copying returnAddress");
267 sety = TYPESTACK_RETURNADDRESSSET(y);
269 for (k=0,sel=selected; sel; sel=sel->alt) {
270 LOG1("selected k=%d",sel->k);
275 *next = DNEW(typeinfo_retaddr_set);
276 (*next)->addr = sety->addr;
277 next = &((*next)->alt);
280 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,new);
283 TYPEINFO_CLONE(y->typeinfo,dst->typeinfo);
287 if (y) panic("Stack depth mismatch 2");
291 typestack_put_retaddr(stackptr dst,void *retaddr,typevector *loc)
293 #ifdef TYPECHECK_DEBUG
294 if (dst->type != TYPE_ADDRESS)
295 panic("Internal error: Storing returnAddress in non-address slot");
298 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,NULL);
299 for (;loc; loc=loc->alt) {
300 typeinfo_retaddr_set *set = DNEW(typeinfo_retaddr_set);
302 set->alt = TYPESTACK_RETURNADDRESSSET(dst);
303 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,set);
308 typestack_collapse(stackptr dst)
310 for (; dst; dst = dst->prev) {
311 if (TYPESTACK_IS_RETURNADDRESS(dst))
312 TYPESTACK_RETURNADDRESSSET(dst)->alt = NULL;
317 typestack_merge(stackptr dst,stackptr y)
319 bool changed = false;
320 for (; dst; dst = dst->prev, y=y->prev) {
322 panic("Stack depth mismatch 3");
323 if (dst->type != y->type) panic("Stack type mismatch 2");
324 if (dst->type == TYPE_ADDRESS) {
325 if (TYPEINFO_IS_PRIMITIVE(dst->typeinfo)) {
326 /* dst has returnAddress type */
327 if (!TYPEINFO_IS_PRIMITIVE(y->typeinfo))
328 panic("Merging returnAddress with reference");
331 /* dst has reference type */
332 if (TYPEINFO_IS_PRIMITIVE(y->typeinfo))
333 panic("Merging reference with returnAddress");
334 changed |= typeinfo_merge(&(dst->typeinfo),&(y->typeinfo));
338 if (y) panic("Stack depth mismatch 4");
343 typestack_add(stackptr dst,stackptr y,int ky)
345 typeinfo_retaddr_set *setd;
346 typeinfo_retaddr_set *sety;
348 for (; dst; dst = dst->prev, y=y->prev) {
349 if (TYPESTACK_IS_RETURNADDRESS(dst)) {
350 setd = TYPESTACK_RETURNADDRESSSET(dst);
351 sety = TYPESTACK_RETURNADDRESSSET(y);
352 RETURNADDRESSSET_SEEK(sety,ky);
355 setd->alt = DNEW(typeinfo_retaddr_set);
356 setd->alt->addr = sety->addr;
357 setd->alt->alt = NULL;
362 /* 'a' and 'b' are assumed to have passed typestack_canmerge! */
364 typestack_separable_with(stackptr a,stackptr b,int kb)
366 typeinfo_retaddr_set *seta;
367 typeinfo_retaddr_set *setb;
369 for (; a; a = a->prev, b = b->prev) {
370 #ifdef TYPECHECK_DEBUG
371 if (!b) panic("Internal error: typestack_separable_from: different depth");
373 if (TYPESTACK_IS_RETURNADDRESS(a)) {
374 #ifdef TYPECHECK_DEBUG
375 if (!TYPESTACK_IS_RETURNADDRESS(b))
376 panic("Internal error: typestack_separable_from: unmergable stacks");
378 seta = TYPESTACK_RETURNADDRESSSET(a);
379 setb = TYPESTACK_RETURNADDRESSSET(b);
380 RETURNADDRESSSET_SEEK(setb,kb);
382 for (;seta;seta=seta->alt)
383 if (seta->addr != setb->addr) return true;
386 #ifdef TYPECHECK_DEBUG
387 if (b) panic("Internal error: typestack_separable_from: different depth");
392 /* 'a' and 'b' are assumed to have passed typestack_canmerge! */
394 typestack_separable_from(stackptr a,int ka,stackptr b,int kb)
396 typeinfo_retaddr_set *seta;
397 typeinfo_retaddr_set *setb;
399 for (; a; a = a->prev, b = b->prev) {
400 #ifdef TYPECHECK_DEBUG
401 if (!b) panic("Internal error: typestack_separable_from: different depth");
403 if (TYPESTACK_IS_RETURNADDRESS(a)) {
404 #ifdef TYPECHECK_DEBUG
405 if (!TYPESTACK_IS_RETURNADDRESS(b))
406 panic("Internal error: typestack_separable_from: unmergable stacks");
408 seta = TYPESTACK_RETURNADDRESSSET(a);
409 setb = TYPESTACK_RETURNADDRESSSET(b);
410 RETURNADDRESSSET_SEEK(seta,ka);
411 RETURNADDRESSSET_SEEK(setb,kb);
413 if (seta->addr != setb->addr) return true;
416 #ifdef TYPECHECK_DEBUG
417 if (b) panic("Internal error: typestack_separable_from: different depth");
422 /****************************************************************************/
423 /* TYPESTATE FUNCTIONS */
424 /****************************************************************************/
427 typestate_merge(stackptr deststack,typevector *destloc,
428 stackptr ystack,typevector *yloc,
429 int locsize,bool jsrencountered)
431 typevector *dvec,*yvec;
433 bool changed = false;
436 LOGSTR("dstack: "); DOLOG(typestack_print(get_logfile(),deststack)); LOGNL;
437 LOGSTR("ystack: "); DOLOG(typestack_print(get_logfile(),ystack)); LOGNL;
438 LOGSTR("dloc : "); DOLOG(typevectorset_print(get_logfile(),destloc,locsize)); LOGNL;
439 LOGSTR("yloc : "); DOLOG(typevectorset_print(get_logfile(),yloc,locsize)); LOGNL;
442 /* The stack is always merged. If there are returnAddresses on
443 * the stack they are ignored in this step. */
445 changed |= typestack_merge(deststack,ystack);
448 return typevector_merge(destloc,yloc,locsize);
450 for (yvec=yloc; yvec; yvec=yvec->alt) {
453 /* Check if the typestates (deststack,destloc) will be
454 * separable when (ystack,yvec) is added. */
456 if (!typestack_separable_with(deststack,ystack,ky)
457 && !typevectorset_separable_with(destloc,yvec,locsize))
459 /* No, the resulting set won't be separable, thus we
460 * may merge all states in (deststack,destloc) and
463 typestack_collapse(deststack);
464 typevectorset_collapse(destloc,locsize);
465 typevector_merge(destloc,yvec,locsize);
468 /* Yes, the resulting set will be separable. Thus we check
469 * if we may merge (ystack,yvec) with a single state in
470 * (deststack,destloc). */
472 for (dvec=destloc,kd=0; dvec; dvec=dvec->alt, kd++) {
473 if (!typestack_separable_from(ystack,ky,deststack,kd)
474 && !typevector_separable_from(yvec,dvec,locsize))
476 /* The typestate (ystack,yvec) is not separable from
477 * (deststack,dvec) by any returnAddress. Thus we may
478 * merge the states. */
480 changed |= typevector_merge(dvec,yvec,locsize);
486 /* The typestate (ystack,yvec) is separable from all typestates
487 * (deststack,destloc). Thus we must add this state to the
490 typestack_add(deststack,ystack,ky);
491 typevectorset_add(destloc,yvec,locsize);
500 LOGSTR("dstack: "); DOLOG(typestack_print(get_logfile(),deststack)); LOGNL;
501 LOGSTR("dloc : "); DOLOG(typevectorset_print(get_logfile(),destloc,locsize)); LOGNL;
509 typestate_reach(codegendata *cd, registerdata *rd,void *localbuf,
511 basicblock *destblock,
512 stackptr ystack,typevector *yloc,
513 int locsize,bool jsrencountered)
517 bool changed = false;
519 LOG1("reaching block L%03d",destblock->debug_nr);
520 TYPECHECK_COUNT(stat_reached);
522 destidx = destblock - cd->method->basicblocks;
523 destloc = MGET_TYPEVECTOR(localbuf,destidx,locsize);
525 /* When branching backwards we have to check for uninitialized objects */
527 if (destblock <= current) {
530 #if defined(__GNUC__)
531 #warning FIXME FOR INLINING
534 TYPECHECK_COUNT(stat_backwards);
536 for (sp = ystack; sp; sp=sp->prev)
537 if (sp->type == TYPE_ADR &&
538 TYPEINFO_IS_NEWOBJECT(sp->typeinfo)) {
539 show_icmd_method(cd->method,cd,rd);
540 printf("current: %d, dest: %d\n", current->debug_nr, destblock->debug_nr);
541 panic("Branching backwards with uninitialized object on stack");
544 for (i=0; i<locsize; ++i)
545 if (yloc->td[i].type == TYPE_ADR &&
546 TYPEINFO_IS_NEWOBJECT(yloc->td[i].info))
547 panic("Branching backwards with uninitialized object in local variable");
551 if (destblock->flags == BBTYPECHECK_UNDEF) {
552 /* The destblock has never been reached before */
554 TYPECHECK_COUNT(stat_copied);
555 LOG1("block (index %04d) reached first time",destidx);
557 typestack_copy(destblock->instack,ystack,yloc);
558 COPY_TYPEVECTORSET(yloc,destloc,locsize);
562 /* The destblock has already been reached before */
564 TYPECHECK_COUNT(stat_merged);
565 LOG1("block (index %04d) reached before",destidx);
567 changed = typestate_merge(destblock->instack,destloc,
570 TYPECHECK_COUNTIF(changed,stat_merging_changed);
575 destblock->flags = BBTYPECHECK_REACHED;
576 if (destblock <= current) {LOG("REPEAT!"); return true;}
583 typestate_ret(codegendata *cd,registerdata *rd, void *localbuf,
585 stackptr ystack,typevector *yloc,
586 int retindex,int locsize)
589 typevector *selected;
590 basicblock *destblock;
593 for (yvec=yloc; yvec; ) {
594 if (!TYPEDESC_IS_RETURNADDRESS(yvec->td[retindex]))
595 panic("Illegal instruction: RET on non-returnAddress");
597 destblock = (basicblock*) TYPEINFO_RETURNADDRESS(yvec->td[retindex].info);
599 selected = typevectorset_select(&yvec,retindex,destblock);
601 repeat |= typestate_reach(cd, rd, localbuf,current,destblock,
602 ystack,selected,locsize,true);
607 /****************************************************************************/
608 /* HELPER FUNCTIONS */
609 /****************************************************************************/
611 /* If a field is checked, definingclass == implementingclass */
613 is_accessible(int flags,classinfo *definingclass,classinfo *implementingclass, classinfo *methodclass,
616 /* check access rights */
617 if (methodclass != definingclass) {
618 switch (flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED)) {
622 /* In the cases below, definingclass cannot be an interface */
625 if (definingclass->packagename != methodclass->packagename)
629 if (definingclass->packagename != methodclass->packagename) {
630 if (!builtin_isanysubclass(methodclass,implementingclass))
633 /* For protected access of super class members in another
634 * package the instance must be a subclass of or the same
635 * as the current class. */
636 LOG("protected access into other package");
637 implementingclass = 0; /*dont't fail, don't really get it (was: methodclass)
638 This code was never triggered before, since all packagenames had been 0-pointers
643 if (definingclass != methodclass) {
644 LOG("private access");
649 panic("Invalid access flags");
654 if ((flags & ACC_STATIC) != 0) {
655 LOG("accessing STATIC member with instance");
659 if (implementingclass
660 && !TYPEINFO_IS_NULLTYPE(*instance)
661 && !TYPEINFO_IS_NEWOBJECT(*instance))
663 if (!typeinfo_is_assignable_to_classinfo(instance,
666 LOG("instance not assignable");
668 LOGSTRu(implementingclass->name); LOGNL; LOGFLUSH;
674 if ((flags & ACC_STATIC) == 0) {
675 LOG("accessing non-STATIC member without instance");
683 /****************************************************************************/
684 /* MACROS FOR LOCAL VARIABLE CHECKING */
685 /****************************************************************************/
687 #define INDEX_ONEWORD(num) \
688 do { if((num)<0 || (num)>=validlocals) \
689 panic("Invalid local variable index"); } while (0)
690 #define INDEX_TWOWORD(num) \
691 do { if((num)<0 || ((num)+1)>=validlocals) \
692 panic("Invalid local variable index"); } while (0)
694 #define STORE_ONEWORD(num,type) \
695 do {typevectorset_store(localset,num,type,NULL);} while(0)
697 #define STORE_TWOWORD(num,type) \
698 do {typevectorset_store_twoword(localset,num,type);} while(0)
701 #define WORDCHECKFAULT \
703 show_icmd_method(m, cd, rd); \
704 dolog("localset->td index: %ld\ninstruction belongs to:%s.%s, outermethod:%s.%s\n", \
705 iptr->op1,iptr->method->class->name->text, \
706 iptr->method->name->text,m->class->name->text,m->name->text); \
707 show_icmd(iptr++, false); \
708 show_icmd(iptr, false); \
712 #define CHECK_ONEWORD(num,tp) \
713 do {TYPECHECK_COUNT(stat_ins_primload); \
714 if (jsrencountered) { \
715 if (!typevectorset_checktype(localset,num,tp)) { \
717 panic("Variable type mismatch"); \
721 if (localset->td[num].type != tp) { \
722 panic("Variable type mismatch"); \
728 #define CHECK_TWOWORD(num,type) \
729 do {TYPECHECK_COUNT(stat_ins_primload); \
730 if (!typevectorset_checktype(localset,num,type)) { \
732 panic("Variable type mismatch"); \
736 /****************************************************************************/
737 /* MACROS FOR STACK TYPE CHECKING */
738 /****************************************************************************/
740 /* These macros are for basic typechecks which were not done in stack.c */
742 #define TYPECHECK_STACK(sp,tp) \
743 do { if ((sp)->type != (tp)) \
744 panic("Wrong data type on stack"); } while(0)
746 #define TYPECHECK_ADR(sp) TYPECHECK_STACK(sp,TYPE_ADR)
747 #define TYPECHECK_INT(sp) TYPECHECK_STACK(sp,TYPE_INT)
748 #define TYPECHECK_LNG(sp) TYPECHECK_STACK(sp,TYPE_LNG)
749 #define TYPECHECK_FLT(sp) TYPECHECK_STACK(sp,TYPE_FLT)
750 #define TYPECHECK_DBL(sp) TYPECHECK_STACK(sp,TYPE_DBL)
752 #define TYPECHECK_ARGS1(t1) \
753 do {TYPECHECK_STACK(curstack,t1);} while (0)
754 #define TYPECHECK_ARGS2(t1,t2) \
755 do {TYPECHECK_ARGS1(t1); \
756 TYPECHECK_STACK(curstack->prev,t2);} while (0)
757 #define TYPECHECK_ARGS3(t1,t2,t3) \
758 do {TYPECHECK_ARGS2(t1,t2); \
759 TYPECHECK_STACK(curstack->prev->prev,t3);} while (0)
761 /****************************************************************************/
763 /****************************************************************************/
765 #define COPYTYPE(source,dest) \
766 {if ((source)->type == TYPE_ADR) \
767 TYPEINFO_COPY((source)->typeinfo,(dest)->typeinfo);}
769 #define ISBUILTIN(v) (iptr->val.fp == (functionptr) (v))
771 /* TYPECHECK_REACH: executed, when the target block (tbptr) can be reached
772 * from the current block (bptr). The types of local variables and
773 * stack slots are propagated to the target block.
775 * bptr.......current block
776 * tbptr......target block
777 * dst........current output stack pointer
778 * numlocals..number of local variables
779 * localset...current local variable vectorset
780 * localbuf...local variable vectorset buffer
781 * jsrencountered...true if a JSR has been seen
783 * repeat.....changed to true if a block before the current
786 #define TYPECHECK_REACH \
788 repeat |= typestate_reach(cd,rd, localbuf,bptr,tbptr,dst, \
789 localset,numlocals,jsrencountered); \
793 /* TYPECHECK_LEAVE: executed when the method is exited non-abruptly
795 * class........class of the current method
796 * numlocals....number of local variables
797 * localset.....current local variable vectorset
798 * initmethod...true if this is an <init> method
800 #define TYPECHECK_LEAVE \
802 if (initmethod && m->class != class_java_lang_Object) { \
803 /* check the marker variable */ \
804 LOG("Checking <init> marker"); \
805 if (!typevectorset_checktype(localset,numlocals-1,TYPE_INT))\
806 panic("<init> method does not initialize 'this'"); \
810 /****************************************************************************/
812 /****************************************************************************/
814 #define MAXPARAMS 255
816 /* typecheck is called directly after analyse_stack */
818 methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd)
820 int b_count, b_index;
821 stackptr curstack; /* input stack top for current instruction */
822 stackptr srcstack; /* source stack for copying and merging */
823 int opcode; /* current opcode */
824 int i; /* temporary counter */
825 int len; /* for counting instructions, etc. */
826 bool superblockend; /* true if no fallthrough to next block */
827 bool repeat; /* if true, blocks are iterated over again */
828 instruction *iptr; /* pointer to current instruction */
829 basicblock *bptr; /* pointer to current basic block */
830 basicblock *tbptr; /* temporary for target block */
832 int numlocals; /* number of local variables */
833 int validlocals; /* number of valid local variable indices */
834 void *localbuf; /* local variable types for each block start */
835 typevector *localset; /* typevector set for local variables */
836 typevector *lset; /* temporary pointer */
837 typedescriptor *td; /* temporary pointer */
839 stackptr savedstackbuf = NULL; /* buffer for saving the stack */
840 stackptr savedstack = NULL; /* saved instack of current block */
842 stackelement excstack; /* instack for exception handlers */
844 typedescriptor returntype; /* return type of current method */
845 u1 *ptype; /* parameter types of called method */
846 typeinfo *pinfo; /* parameter typeinfos of called method */
847 int rtype; /* return type of called method */
848 typeinfo rinfo; /* typeinfo for return type of called method */
850 stackptr dst; /* output stack of current instruction */
851 basicblock **tptr; /* pointer into target list of switch instr. */
852 exceptiontable **handlers; /* active exception handlers */
853 classinfo *cls; /* temporary */
854 bool maythrow; /* true if this instruction may throw */
855 static utf *name_init; /* "<init>" */
856 bool initmethod; /* true if this is an "<init>" method */
857 builtin_descriptor *builtindesc; /* temp. descriptor of builtin */
858 bool jsrencountered = false; /* true if we there was a JSR */
862 #ifdef TYPECHECK_STATISTICS
863 int count_iterations = 0;
864 TYPECHECK_COUNT(stat_typechecked);
865 TYPECHECK_COUNT_FREQ(stat_locals,cd->maxlocals,STAT_LOCALS);
866 TYPECHECK_COUNT_FREQ(stat_blocks,m->basicblockcount/10,STAT_BLOCKS);
869 LOGSTR("\n==============================================================================\n");
870 /*DOLOG( show_icmd_method(cd->method,cd,rd));*/
871 LOGSTR("\n==============================================================================\n");
872 LOGimpSTR("Entering typecheck: ");
873 LOGimpSTRu(cd->method->name);
875 LOGimpSTRu(cd->method->descriptor);
876 LOGimpSTR(" (class ");
877 LOGimpSTRu(cd->method->class->name);
882 name_init = utf_new_char("<init>");
883 initmethod = (m->name == name_init);
885 /* Allocate buffer for method arguments */
887 ptype = DMNEW(u1,MAXPARAMS);
888 pinfo = DMNEW(typeinfo,MAXPARAMS);
890 LOG("Buffer allocated.\n");
892 /* reset all BBFINISHED blocks to BBTYPECHECK_UNDEF. */
893 b_count = m->basicblockcount;
894 bptr = m->basicblocks;
895 while (--b_count >= 0) {
896 #ifdef TYPECHECK_DEBUG
897 if (bptr->flags != BBFINISHED && bptr->flags != BBDELETED
898 && bptr->flags != BBUNDEF)
900 /*show_icmd_method(cd->method,cd,rd);*/
901 LOGSTR1("block flags: %d\n",bptr->flags); LOGFLUSH;
902 panic("Internal error: Unexpected block flags in typecheck()");
905 if (bptr->flags >= BBFINISHED) {
906 bptr->flags = BBTYPECHECK_UNDEF;
911 /* The first block is always reached */
912 if (m->basicblockcount && m->basicblocks[0].flags == BBTYPECHECK_UNDEF)
913 m->basicblocks[0].flags = BBTYPECHECK_REACHED;
915 LOG("Blocks reset.\n");
917 /* number of local variables */
919 /* In <init> methods we use an extra local variable to signal if
920 * the 'this' reference has been initialized. */
921 numlocals = cd->maxlocals;
922 validlocals = numlocals;
923 if (initmethod) numlocals++;
925 /* allocate the buffers for local variables */
926 localbuf = DMNEW_TYPEVECTOR(m->basicblockcount+1, numlocals);
927 localset = MGET_TYPEVECTOR(localbuf,m->basicblockcount,numlocals);
929 LOG("Variable buffer allocated.\n");
931 /* allocate the buffer of active exception handlers */
932 handlers = DMNEW(exceptiontable*, cd->exceptiontablelength + 1);
934 /* initialize the variable types of the first block */
935 /* to the types of the arguments */
936 lset = MGET_TYPEVECTOR(localbuf,0,numlocals);
942 /* if this is an instance method initialize the "this" ref type */
943 if (!(m->flags & ACC_STATIC)) {
945 panic("Not enough local variables for method arguments");
946 td->type = TYPE_ADDRESS;
948 TYPEINFO_INIT_NEWOBJECT(td->info,NULL);
950 TYPEINFO_INIT_CLASSINFO(td->info, m->class);
955 LOG("'this' argument set.\n");
957 /* the rest of the arguments and the return type */
958 i = typedescriptors_init_from_method_args(td, m->descriptor,
960 true, /* two word types use two slots */
963 i = numlocals - (td - lset->td);
965 td->type = TYPE_VOID;
969 LOG("Arguments set.\n");
971 /* initialize the input stack of exception handlers */
972 excstack.prev = NULL;
973 excstack.type = TYPE_ADR;
974 TYPEINFO_INIT_CLASSINFO(excstack.typeinfo,
975 class_java_lang_Throwable); /* changed later */
977 LOG("Exception handler stacks set.\n");
979 /* loop while there are still blocks to be checked */
981 TYPECHECK_COUNT(count_iterations);
985 b_count = m->basicblockcount;
986 bptr = m->basicblocks;
988 while (--b_count >= 0) {
989 LOGSTR1("---- BLOCK %04d, ",bptr->debug_nr);
990 LOGSTR1("blockflags: %d\n",bptr->flags);
993 if (bptr->flags == BBTYPECHECK_REACHED) {
994 LOGSTR1("\n---- BLOCK %04d ------------------------------------------------\n",bptr->debug_nr);
997 superblockend = false;
998 bptr->flags = BBFINISHED;
999 b_index = bptr - m->basicblocks;
1001 /* init stack at the start of this block */
1002 curstack = bptr->instack;
1004 /* determine the active exception handlers for this block */
1005 /* XXX could use a faster algorithm with sorted lists or
1008 for (i = 0; i < cd->exceptiontablelength; ++i) {
1009 if ((cd->exceptiontable[i].start <= bptr) && (cd->exceptiontable[i].end > bptr)) {
1010 LOG1("active handler L%03d", cd->exceptiontable[i].handler->debug_nr);
1011 handlers[len++] = cd->exceptiontable + i;
1014 handlers[len] = NULL;
1016 /* init variable types at the start of this block */
1017 COPY_TYPEVECTORSET(MGET_TYPEVECTOR(localbuf,b_index,numlocals),
1018 localset,numlocals);
1019 #if defined(__GNUC__)
1020 #warning FIXME FOR INLINING
1024 for (i=0; i<numlocals; ++i)
1025 if (localset->td[i].type == TYPE_ADR
1026 && TYPEINFO_IS_NEWOBJECT(localset->td[i].info)) {
1027 show_icmd_method(m, cd, rd);
1028 printf("Uninitialized variale: %d, block: %d\n", i, bptr->debug_nr);
1029 panic("Uninitialized object in local variable inside try block");
1032 DOLOG(typestate_print(get_logfile(),curstack,localset,numlocals));
1035 /* loop over the instructions */
1037 iptr = bptr->iinstr;
1038 while (--len >= 0) {
1039 TYPECHECK_COUNT(stat_ins);
1040 DOLOG(show_icmd(iptr,false)); LOGNL; LOGFLUSH;
1043 myclass = iptr->method->class;
1049 /****************************************/
1050 /* STACK MANIPULATIONS */
1052 /* We just need to copy the typeinfo */
1053 /* for slots containing addresses. */
1055 /* XXX We assume that the destination stack
1056 * slots were continuously allocated in
1057 * memory. (The current implementation in
1062 COPYTYPE(curstack,dst);
1066 COPYTYPE(curstack,dst);
1067 COPYTYPE(curstack,dst-2);
1068 COPYTYPE(curstack->prev,dst-1);
1072 COPYTYPE(curstack,dst);
1073 COPYTYPE(curstack,dst-3);
1074 COPYTYPE(curstack->prev,dst-1);
1075 COPYTYPE(curstack->prev->prev,dst-2);
1079 COPYTYPE(curstack,dst);
1080 COPYTYPE(curstack->prev,dst-1);
1084 COPYTYPE(curstack,dst);
1085 COPYTYPE(curstack->prev,dst-1);
1086 COPYTYPE(curstack,dst-3);
1087 COPYTYPE(curstack->prev,dst-4);
1088 COPYTYPE(curstack->prev->prev,dst-2);
1092 COPYTYPE(curstack,dst);
1093 COPYTYPE(curstack->prev,dst-1);
1094 COPYTYPE(curstack,dst-4);
1095 COPYTYPE(curstack->prev,dst-5);
1096 COPYTYPE(curstack->prev->prev,dst-2);
1097 COPYTYPE(curstack->prev->prev->prev,dst-3);
1101 COPYTYPE(curstack,dst-1);
1102 COPYTYPE(curstack->prev,dst);
1105 /****************************************/
1115 /* PRIMITIVE VARIABLE ACCESS */
1117 case ICMD_ILOAD: CHECK_ONEWORD(iptr->op1,TYPE_INT); break;
1118 case ICMD_FLOAD: CHECK_ONEWORD(iptr->op1,TYPE_FLOAT); break;
1119 case ICMD_IINC: CHECK_ONEWORD(iptr->op1,TYPE_INT); break;
1120 case ICMD_LLOAD: CHECK_TWOWORD(iptr->op1,TYPE_LONG); break;
1121 case ICMD_DLOAD: CHECK_TWOWORD(iptr->op1,TYPE_DOUBLE); break;
1123 case ICMD_FSTORE: STORE_ONEWORD(iptr->op1,TYPE_FLOAT); break;
1124 case ICMD_ISTORE: STORE_ONEWORD(iptr->op1,TYPE_INT); break;
1125 case ICMD_LSTORE: STORE_TWOWORD(iptr->op1,TYPE_LONG); break;
1126 case ICMD_DSTORE: STORE_TWOWORD(iptr->op1,TYPE_DOUBLE); break;
1128 /****************************************/
1129 /* LOADING ADDRESS FROM VARIABLE */
1132 TYPECHECK_COUNT(stat_ins_aload);
1134 /* loading a returnAddress is not allowed */
1135 if (jsrencountered) {
1136 if (!typevectorset_checkreference(localset,iptr->op1))
1137 panic("illegal instruction: ALOAD loading non-reference");
1139 typevectorset_copymergedtype(localset,iptr->op1,&(dst->typeinfo));
1142 if (!TYPEDESC_IS_REFERENCE(localset->td[iptr->op1])) {
1143 show_icmd_method(m, cd, rd);
1144 dolog("localset->td index: %ld\ninstruction belongs to:%s.%s, outermethod:%s.%s\n",
1145 iptr->op1,iptr->method->class->name->text,
1146 iptr->method->name->text,m->class->name->text,m->name->text);
1147 show_icmd(iptr, false);
1148 panic("illegal instruction: ALOAD loading non-reference");
1150 TYPEINFO_COPY(localset->td[iptr->op1].info,dst->typeinfo);
1154 /****************************************/
1155 /* STORING ADDRESS TO VARIABLE */
1159 TYPEINFO_IS_NEWOBJECT(curstack->typeinfo))
1160 panic("Storing uninitialized object in local variable inside try block");
1162 if (TYPESTACK_IS_RETURNADDRESS(curstack))
1163 typevectorset_store_retaddr(localset,iptr->op1,&(curstack->typeinfo));
1165 typevectorset_store(localset,iptr->op1,TYPE_ADDRESS,
1166 &(curstack->typeinfo));
1169 /****************************************/
1170 /* LOADING ADDRESS FROM ARRAY */
1173 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(curstack->prev->typeinfo))
1174 panic("illegal instruction: AALOAD on non-reference array");
1176 typeinfo_init_component(&curstack->prev->typeinfo,&dst->typeinfo);
1180 /****************************************/
1184 TYPECHECK_COUNT(stat_ins_field);
1185 if (!TYPEINFO_IS_REFERENCE(curstack->prev->typeinfo))
1186 panic("illegal instruction: PUTFIELD on non-reference");
1187 if (TYPEINFO_IS_ARRAY(curstack->prev->typeinfo))
1188 panic("illegal instruction: PUTFIELD on array");
1190 /* check if the value is assignable to the field */
1192 fieldinfo *fi = (fieldinfo*) iptr[0].val.a;
1194 if (TYPEINFO_IS_NEWOBJECT(curstack->prev->typeinfo)) {
1196 && !TYPEINFO_NEWOBJECT_INSTRUCTION(curstack->prev->typeinfo))
1198 /* uninitialized "this" instance */
1199 if (fi->class != m->class || (fi->flags & ACC_STATIC) != 0)
1200 panic("Setting unaccessible field in uninitialized object");
1203 panic("PUTFIELD on uninitialized object");
1207 if (!is_accessible(fi->flags,fi->class,fi->class, myclass,
1208 &(curstack->prev->typeinfo)))
1209 panic("PUTFIELD: field is not accessible");
1212 if (curstack->type != fi->type)
1213 panic("PUTFIELD type mismatch");
1214 if (fi->type == TYPE_ADR) {
1215 TYPEINFO_INIT_FROM_FIELDINFO(rinfo,fi);
1216 if (!typeinfo_is_assignable(&(curstack->typeinfo),
1218 panic("PUTFIELD reference type not assignable");
1224 case ICMD_PUTSTATIC:
1225 TYPECHECK_COUNT(stat_ins_field);
1226 /* check if the value is assignable to the field */
1228 fieldinfo *fi = (fieldinfo*) iptr[0].val.a;
1230 if (!is_accessible(fi->flags,fi->class,fi->class,myclass,NULL))
1231 panic("PUTSTATIC: field is not accessible");
1233 if (curstack->type != fi->type)
1234 panic("PUTSTATIC type mismatch");
1235 if (fi->type == TYPE_ADR) {
1236 TYPEINFO_INIT_FROM_FIELDINFO(rinfo,fi);
1237 if (!typeinfo_is_assignable(&(curstack->typeinfo),
1239 panic("PUTSTATIC reference type not assignable");
1246 TYPECHECK_COUNT(stat_ins_field);
1247 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1248 panic("illegal instruction: GETFIELD on non-reference");
1249 if (TYPEINFO_IS_ARRAY(curstack->typeinfo))
1250 panic("illegal instruction: GETFIELD on array");
1253 fieldinfo *fi = (fieldinfo *)(iptr->val.a);
1255 if (!is_accessible(fi->flags,fi->class,fi->class,myclass,
1256 &(curstack->typeinfo)))
1257 panic("GETFIELD: field is not accessible");
1259 if (dst->type == TYPE_ADR) {
1260 TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi);
1266 case ICMD_GETSTATIC:
1267 TYPECHECK_COUNT(stat_ins_field);
1269 fieldinfo *fi = (fieldinfo *)(iptr->val.a);
1271 if (!is_accessible(fi->flags,fi->class,fi->class,myclass,NULL)) {
1272 printf("---------\n");
1273 utf_display(fi->class->name);
1275 utf_display(myclass->name);
1279 panic("GETSTATIC: field is not accessible");
1282 if (dst->type == TYPE_ADR) {
1283 TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi);
1289 /****************************************/
1290 /* PRIMITIVE ARRAY ACCESS */
1292 case ICMD_ARRAYLENGTH:
1293 if (!TYPEINFO_MAYBE_ARRAY(curstack->typeinfo)
1294 && curstack->typeinfo.typeclass != pseudo_class_Arraystub)
1295 panic("illegal instruction: ARRAYLENGTH on non-array");
1300 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_BOOLEAN)
1301 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_BYTE))
1302 panic("Array type mismatch");
1306 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_CHAR))
1307 panic("Array type mismatch");
1311 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_DOUBLE))
1312 panic("Array type mismatch");
1316 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_FLOAT))
1317 panic("Array type mismatch");
1321 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_INT))
1322 panic("Array type mismatch");
1326 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_SHORT))
1327 panic("Array type mismatch");
1331 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_LONG))
1332 panic("Array type mismatch");
1337 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_BOOLEAN)
1338 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_BYTE))
1339 panic("Array type mismatch");
1343 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_CHAR))
1344 panic("Array type mismatch");
1348 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_DOUBLE))
1349 panic("Array type mismatch");
1353 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_FLOAT))
1354 panic("Array type mismatch");
1358 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_INT))
1359 panic("Array type mismatch");
1363 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_SHORT))
1364 panic("Array type mismatch");
1368 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_LONG))
1369 panic("Array type mismatch");
1373 case ICMD_IASTORECONST:
1374 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo, ARRAYTYPE_INT))
1375 panic("Array type mismatch");
1379 case ICMD_LASTORECONST:
1380 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo, ARRAYTYPE_LONG))
1381 panic("Array type mismatch");
1385 case ICMD_BASTORECONST:
1386 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo, ARRAYTYPE_BOOLEAN)
1387 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo, ARRAYTYPE_BYTE))
1388 panic("Array type mismatch");
1392 case ICMD_CASTORECONST:
1393 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo, ARRAYTYPE_CHAR))
1394 panic("Array type mismatch");
1398 case ICMD_SASTORECONST:
1399 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo, ARRAYTYPE_SHORT))
1400 panic("Array type mismatch");
1405 /****************************************/
1406 /* ADDRESS CONSTANTS */
1409 if (iptr->val.a == NULL)
1410 TYPEINFO_INIT_NULLTYPE(dst->typeinfo);
1412 /* string constants (or constant for builtin function) */
1413 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,class_java_lang_String);
1416 /****************************************/
1417 /* CHECKCAST AND INSTANCEOF */
1419 case ICMD_CHECKCAST:
1420 TYPECHECK_ADR(curstack);
1421 /* returnAddress is not allowed */
1422 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1423 panic("Illegal instruction: CHECKCAST on non-reference");
1425 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,(classinfo *)iptr[0].val.a);
1429 case ICMD_INSTANCEOF:
1430 TYPECHECK_ADR(curstack);
1431 /* returnAddress is not allowed */
1432 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1433 panic("Illegal instruction: INSTANCEOF on non-reference");
1436 /****************************************/
1437 /* BRANCH INSTRUCTIONS */
1440 superblockend = true;
1443 case ICMD_IFNONNULL:
1450 case ICMD_IF_ICMPEQ:
1451 case ICMD_IF_ICMPNE:
1452 case ICMD_IF_ICMPLT:
1453 case ICMD_IF_ICMPGE:
1454 case ICMD_IF_ICMPGT:
1455 case ICMD_IF_ICMPLE:
1456 case ICMD_IF_ACMPEQ:
1457 case ICMD_IF_ACMPNE:
1464 case ICMD_IF_LCMPEQ:
1465 case ICMD_IF_LCMPNE:
1466 case ICMD_IF_LCMPLT:
1467 case ICMD_IF_LCMPGE:
1468 case ICMD_IF_LCMPGT:
1469 case ICMD_IF_LCMPLE:
1470 TYPECHECK_COUNT(stat_ins_branch);
1471 tbptr = (basicblock *) iptr->target;
1473 /* propagate stack and variables to the target block */
1477 /****************************************/
1480 case ICMD_TABLESWITCH:
1481 TYPECHECK_COUNT(stat_ins_switch);
1483 s4 *s4ptr = iptr->val.a;
1484 s4ptr++; /* skip default */
1485 i = *s4ptr++; /* low */
1486 i = *s4ptr++ - i + 2; /* +1 for default target */
1488 goto switch_instruction_tail;
1490 case ICMD_LOOKUPSWITCH:
1491 TYPECHECK_COUNT(stat_ins_switch);
1493 s4 *s4ptr = iptr->val.a;
1494 s4ptr++; /* skip default */
1495 i = *s4ptr++ + 1; /* count +1 for default */
1497 switch_instruction_tail:
1498 tptr = (basicblock **)iptr->target;
1502 LOG2("target %d is block %04d",(tptr-(basicblock **)iptr->target)-1,tbptr->debug_nr);
1506 superblockend = true;
1509 /****************************************/
1510 /* RETURNS AND THROW */
1513 if (!typeinfo_is_assignable_to_classinfo(
1514 &curstack->typeinfo,class_java_lang_Throwable))
1515 panic("illegal instruction: ATHROW on non-Throwable");
1516 superblockend = true;
1521 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1522 panic("illegal instruction: ARETURN on non-reference");
1524 if (returntype.type != TYPE_ADDRESS
1525 || !typeinfo_is_assignable(&curstack->typeinfo,&(returntype.info)))
1526 panic("Return type mismatch");
1530 if (returntype.type != TYPE_INT) panic("Return type mismatch");
1534 if (returntype.type != TYPE_LONG) panic("Return type mismatch");
1538 if (returntype.type != TYPE_FLOAT) panic("Return type mismatch");
1542 if (returntype.type != TYPE_DOUBLE) panic("Return type mismatch");
1546 if (returntype.type != TYPE_VOID) panic("Return type mismatch");
1549 superblockend = true;
1553 /****************************************/
1554 /* SUBROUTINE INSTRUCTIONS */
1558 jsrencountered = true;
1560 /* This is a dirty hack. It is needed
1561 * because of the special handling of
1562 * ICMD_JSR in stack.c
1564 dst = (stackptr) iptr->val.a;
1566 tbptr = (basicblock *) iptr->target;
1567 if (bptr + 1 == (m->basicblocks + m->basicblockcount + 1))
1568 panic("Illegal instruction: JSR at end of bytecode");
1569 typestack_put_retaddr(dst,bptr+1,localset);
1570 repeat |= typestate_reach(cd, rd,localbuf,bptr,tbptr,dst,
1571 localset,numlocals,true);
1573 superblockend = true;
1577 /* check returnAddress variable */
1578 if (!typevectorset_checkretaddr(localset,iptr->op1))
1579 panic("illegal instruction: RET using non-returnAddress variable");
1581 repeat |= typestate_ret(cd,rd, localbuf,bptr,curstack,
1582 localset,iptr->op1,numlocals);
1584 superblockend = true;
1587 /****************************************/
1590 case ICMD_INVOKEVIRTUAL:
1591 case ICMD_INVOKESPECIAL:
1592 case ICMD_INVOKESTATIC:
1593 case ICMD_INVOKEINTERFACE:
1594 TYPECHECK_COUNT(stat_ins_invoke);
1596 methodinfo *mi = (methodinfo*) iptr->val.a;
1597 bool specialmethod = (mi->name->text[0] == '<');
1598 bool callinginit = (opcode == ICMD_INVOKESPECIAL && mi->name == name_init);
1600 classinfo *initclass;
1602 if (specialmethod && !callinginit)
1603 panic("Invalid invocation of special method");
1605 if (opcode == ICMD_INVOKESPECIAL) {
1606 /* XXX for INVOKESPECIAL: check if the invokation is done at all */
1608 /* (If callinginit the class is checked later.) */
1610 if (!builtin_isanysubclass(myclass,mi->class))
1611 panic("Illegal instruction: INVOKESPECIAL calling non-superclass method");
1615 /* fetch parameter types and return type */
1617 if (opcode != ICMD_INVOKESTATIC) {
1618 ptype[0] = TYPE_ADR;
1619 TYPEINFO_INIT_CLASSINFO(pinfo[0],mi->class);
1622 typeinfo_init_from_method_args(mi->descriptor,ptype+i,pinfo+i,
1626 /* check parameter types */
1627 srcstack = curstack;
1628 i = mi->paramcount; /* number of parameters including 'this'*/
1631 if (srcstack->type != ptype[i])
1632 panic("Parameter type mismatch in method invocation");
1633 if (srcstack->type == TYPE_ADR) {
1634 LOGINFO(&(srcstack->typeinfo));
1636 if (i==0 && callinginit)
1638 /* first argument to <init> method */
1639 if (!TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo))
1640 panic("Calling <init> on initialized object");
1642 /* get the address of the NEW instruction */
1643 LOGINFO(&(srcstack->typeinfo));
1644 ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(srcstack->typeinfo);
1645 initclass = (ins) ? (classinfo*)ins[-1].val.a : m->class;
1646 LOGSTR("class: "); LOGSTRu(initclass->name); LOGNL;
1649 /* (This is checked below.) */
1650 /* TYPEINFO_INIT_CLASSINFO(tempinfo,initclass); */
1651 /* if (!typeinfo_is_assignable(&tempinfo,pinfo+0)) */
1652 /* panic("Parameter reference type mismatch in <init> invocation"); */
1655 if (!typeinfo_is_assignable(&(srcstack->typeinfo),pinfo+i))
1656 panic("Parameter reference type mismatch in method invocation");
1661 if (i) srcstack = srcstack->prev;
1664 /* XXX We should resolve the method and pass its
1665 * class as implementingclass to is_accessible. */
1666 /* JOWENN: FIXME (and on other invokation places of is_accessible too) */
1667 if (!is_accessible(mi->flags,mi->class,/*NULL have to check what here should really be*/ mi->class /*dont't crash right now*/, myclass,
1668 (opcode == ICMD_INVOKESTATIC) ? NULL
1669 : &(srcstack->typeinfo)))
1670 panic("Invoking unaccessible method");
1672 LOG("checking return type");
1673 if (rtype != TYPE_VOID) {
1674 if (rtype != dst->type)
1675 panic("Return type mismatch in method invocation");
1676 TYPEINFO_COPY(rinfo,dst->typeinfo);
1680 LOG("replacing uninitialized object");
1681 /* replace uninitialized object type on stack */
1684 if (srcstack->type == TYPE_ADR
1685 && TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo)
1686 && TYPEINFO_NEWOBJECT_INSTRUCTION(srcstack->typeinfo) == ins)
1688 LOG("replacing uninitialized type on stack");
1690 /* If this stackslot is in the instack of
1691 * this basic block we must save the type(s)
1692 * we are going to replace.
1694 if (srcstack <= bptr->instack && !savedstack)
1698 LOG("saving input stack types");
1699 if (!savedstackbuf) {
1700 LOG("allocating savedstack buffer");
1701 savedstackbuf = DMNEW(stackelement, cd->maxstack);
1702 savedstackbuf->prev = NULL;
1703 for (i = 1; i < cd->maxstack; ++i)
1704 savedstackbuf[i].prev = savedstackbuf+(i-1);
1706 sp = savedstack = bptr->instack;
1707 copy = bptr->instack = savedstackbuf + (bptr->indepth-1);
1708 TYPESTACK_COPY(sp,copy);
1711 TYPEINFO_INIT_CLASSINFO(srcstack->typeinfo,initclass);
1713 srcstack = srcstack->prev;
1715 /* replace uninitialized object type in locals */
1716 typevectorset_init_object(localset,ins,initclass,numlocals);
1718 /* initializing the 'this' reference? */
1720 #ifdef TYPECHECK_DEBUG
1722 panic("Internal error: calling <init> on this in non-<init> method.");
1724 /* must be <init> of current class or direct superclass */
1725 if (mi->class != m->class && mi->class != m->class->super)
1726 panic("<init> calling <init> of the wrong class");
1728 /* set our marker variable to type int */
1729 LOG("setting <init> marker");
1730 typevectorset_store(localset,numlocals-1,TYPE_INT,NULL);
1733 /* initializing an instance created with NEW */
1734 /* XXX is this strictness ok? */
1735 if (mi->class != initclass)
1736 panic("Calling <init> method of the wrong class");
1743 case ICMD_MULTIANEWARRAY:
1745 vftbl_t *arrayvftbl;
1746 arraydescriptor *desc;
1748 /* check the array lengths on the stack */
1750 if (i<1) panic("MULTIANEWARRAY with dimensions < 1");
1751 srcstack = curstack;
1754 panic("MULTIANEWARRAY missing array length");
1755 if (srcstack->type != TYPE_INT)
1756 panic("MULTIANEWARRAY using non-int as array length");
1757 srcstack = srcstack->prev;
1760 /* check array descriptor */
1761 arrayvftbl = (vftbl_t*) iptr[0].val.a;
1763 panic("MULTIANEWARRAY with unlinked class");
1764 if ((desc = arrayvftbl->arraydesc) == NULL)
1765 panic("MULTIANEWARRAY with non-array class");
1766 if (desc->dimension < iptr[0].op1)
1767 panic("MULTIANEWARRAY dimension to high");
1769 /* set the array type of the result */
1770 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,arrayvftbl->class);
1776 TYPECHECK_COUNT(stat_ins_builtin);
1777 if (ISBUILTIN(BUILTIN_aastore)) {
1778 TYPECHECK_ADR(curstack);
1779 TYPECHECK_INT(curstack->prev);
1780 TYPECHECK_ADR(curstack->prev->prev);
1781 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(curstack->prev->prev->typeinfo))
1782 panic("illegal instruction: AASTORE to non-reference array");
1785 /* XXX put these checks in a function */
1786 TYPECHECK_COUNT(stat_ins_builtin_gen);
1787 builtindesc = builtin_desc;
1788 while (builtindesc->opcode && builtindesc->builtin
1789 != iptr->val.fp) builtindesc++;
1790 if (!builtindesc->opcode) {
1791 dolog("Builtin not in table: %s",icmd_builtin_name(iptr->val.fp));
1792 panic("Internal error: builtin not found in table");
1794 TYPECHECK_ARGS3(builtindesc->type_s3,builtindesc->type_s2,builtindesc->type_s1);
1800 TYPECHECK_COUNT(stat_ins_builtin);
1801 if (ISBUILTIN(BUILTIN_newarray))
1804 TYPECHECK_INT(curstack->prev);
1805 if (iptr[-1].opc != ICMD_ACONST)
1806 panic("illegal instruction: builtin_newarray without classinfo");
1807 vft = (vftbl_t *)iptr[-1].val.a;
1809 panic("ANEWARRAY with unlinked class");
1810 if (!vft->arraydesc)
1811 panic("ANEWARRAY with non-array class");
1812 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,vft->class);
1814 else if (ISBUILTIN(BUILTIN_arrayinstanceof))
1817 TYPECHECK_ADR(curstack->prev);
1818 if (iptr[-1].opc != ICMD_ACONST)
1819 panic("illegal instruction: builtin_arrayinstanceof without classinfo");
1820 vft = (vftbl_t *)iptr[-1].val.a;
1822 panic("INSTANCEOF with unlinked class");
1823 if (!vft->arraydesc)
1824 panic("internal error: builtin_arrayinstanceof with non-array class");
1826 else if (ISBUILTIN(BUILTIN_checkarraycast)) {
1828 TYPECHECK_ADR(curstack->prev);
1829 if (iptr[-1].opc != ICMD_ACONST)
1830 panic("illegal instruction: BUILTIN_checkarraycast without classinfo");
1831 vft = (vftbl_t *)iptr[-1].val.a;
1833 panic("CHECKCAST with unlinked class");
1834 if (!vft->arraydesc)
1835 panic("internal error: builtin_checkarraycast with non-array class");
1836 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,vft->class);
1839 TYPECHECK_COUNT(stat_ins_builtin_gen);
1840 builtindesc = builtin_desc;
1841 while (builtindesc->opcode && builtindesc->builtin
1842 != iptr->val.fp) builtindesc++;
1843 if (!builtindesc->opcode) {
1844 dolog("Builtin not in table: %s",icmd_builtin_name(iptr->val.fp));
1845 panic("Internal error: builtin not found in table");
1847 TYPECHECK_ARGS2(builtindesc->type_s2,builtindesc->type_s1);
1853 TYPECHECK_COUNT(stat_ins_builtin);
1854 if (ISBUILTIN(BUILTIN_new)) {
1856 if (iptr[-1].opc != ICMD_ACONST)
1857 panic("illegal instruction: builtin_new without classinfo");
1858 cls = (classinfo *) iptr[-1].val.a;
1860 panic("Internal error: NEW with unlinked class");
1861 /* The following check also forbids array classes and interfaces: */
1862 if ((cls->flags & ACC_ABSTRACT) != 0)
1863 panic("Invalid instruction: NEW creating instance of abstract class");
1864 TYPEINFO_INIT_NEWOBJECT(dst->typeinfo,iptr);
1866 else if (ISBUILTIN(BUILTIN_newarray_boolean)) {
1867 TYPECHECK_INT(curstack);
1868 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BOOLEAN);
1870 else if (ISBUILTIN(BUILTIN_newarray_char)) {
1871 TYPECHECK_INT(curstack);
1872 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_CHAR);
1874 else if (ISBUILTIN(BUILTIN_newarray_float)) {
1875 TYPECHECK_INT(curstack);
1876 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_FLOAT);
1878 else if (ISBUILTIN(BUILTIN_newarray_double)) {
1879 TYPECHECK_INT(curstack);
1880 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_DOUBLE);
1882 else if (ISBUILTIN(BUILTIN_newarray_byte)) {
1883 TYPECHECK_INT(curstack);
1884 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BYTE);
1886 else if (ISBUILTIN(BUILTIN_newarray_short)) {
1887 TYPECHECK_INT(curstack);
1888 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_SHORT);
1890 else if (ISBUILTIN(BUILTIN_newarray_int)) {
1891 TYPECHECK_INT(curstack);
1892 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_INT);
1894 else if (ISBUILTIN(BUILTIN_newarray_long)) {
1895 TYPECHECK_INT(curstack);
1896 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_LONG);
1899 TYPECHECK_COUNT(stat_ins_builtin_gen);
1900 builtindesc = builtin_desc;
1901 while (builtindesc->opcode && builtindesc->builtin
1902 != iptr->val.fp) builtindesc++;
1903 if (!builtindesc->opcode) {
1904 dolog("Builtin not in table: %s",icmd_builtin_name(iptr->val.fp));
1905 panic("Internal error: builtin not found in table");
1907 TYPECHECK_ARGS1(builtindesc->type_s1);
1912 /****************************************/
1913 /* SIMPLE EXCEPTION THROWING TESTS */
1915 case ICMD_CHECKASIZE:
1916 /* The argument to CHECKASIZE is typechecked by
1917 * typechecking the array creation instructions. */
1920 case ICMD_NULLCHECKPOP:
1921 /* NULLCHECKPOP just requires that the stack top
1922 * is an address. This is checked in stack.c */
1927 /****************************************/
1928 /* INSTRUCTIONS WHICH SHOULD HAVE BEEN */
1929 /* REPLACED BY OTHER OPCODES */
1931 #ifdef TYPECHECK_DEBUG
1934 case ICMD_ANEWARRAY:
1935 case ICMD_MONITORENTER:
1936 case ICMD_MONITOREXIT:
1938 LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-bptr->iinstr));
1939 LOG("Should have been converted to builtin function call.");
1940 panic("Internal error: unexpected instruction encountered");
1943 case ICMD_READONLY_ARG:
1944 case ICMD_CLEAR_ARGREN:
1945 LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-bptr->iinstr));
1946 LOG("Should have been replaced in stack.c.");
1947 panic("Internal error: unexpected pseudo instruction encountered");
1951 /****************************************/
1952 /* UNCHECKED OPERATIONS */
1954 /*********************************************
1955 * Instructions below...
1956 * *) don't operate on local variables,
1957 * *) don't operate on references,
1958 * *) don't operate on returnAddresses.
1960 * (These instructions are typechecked in
1962 ********************************************/
1964 /* Instructions which may throw a runtime exception: */
1974 /* Instructions which never throw a runtime exception: */
1975 #if defined(TYPECHECK_DEBUG) || defined(TYPECHECK_STATISTICS)
1985 case ICMD_IFEQ_ICONST:
1986 case ICMD_IFNE_ICONST:
1987 case ICMD_IFLT_ICONST:
1988 case ICMD_IFGE_ICONST:
1989 case ICMD_IFGT_ICONST:
1990 case ICMD_IFLE_ICONST:
1991 case ICMD_ELSE_ICONST:
2014 case ICMD_IREM0X10001:
2015 case ICMD_LREM0X10001:
2019 case ICMD_IADDCONST:
2020 case ICMD_ISUBCONST:
2021 case ICMD_IMULCONST:
2022 case ICMD_IANDCONST:
2024 case ICMD_IXORCONST:
2025 case ICMD_ISHLCONST:
2026 case ICMD_ISHRCONST:
2027 case ICMD_IUSHRCONST:
2029 case ICMD_LADDCONST:
2030 case ICMD_LSUBCONST:
2031 case ICMD_LMULCONST:
2032 case ICMD_LANDCONST:
2034 case ICMD_LXORCONST:
2035 case ICMD_LSHLCONST:
2036 case ICMD_LSHRCONST:
2037 case ICMD_LUSHRCONST:
2054 case ICMD_INT2SHORT:
2057 case ICMD_LCMPCONST:
2077 /*What shall we do with the following ?*/
2078 case ICMD_CHECKEXCEPTION:
2079 case ICMD_AASTORECONST:
2080 TYPECHECK_COUNT(stat_ins_unchecked);
2083 /****************************************/
2086 LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-bptr->iinstr));
2087 panic("Missing ICMD code during typecheck");
2091 /* the output of this instruction becomes the current stack */
2094 /* reach exception handlers for this instruction */
2096 LOG("reaching exception handlers");
2098 while (handlers[i]) {
2099 TYPECHECK_COUNT(stat_handlers_reached);
2100 cls = handlers[i]->catchtype;
2101 excstack.typeinfo.typeclass = (cls) ? cls
2102 : class_java_lang_Throwable;
2103 repeat |= typestate_reach(cd,rd, localbuf,bptr,
2104 handlers[i]->handler,
2113 } /* while instructions */
2115 LOG("instructions done");
2116 LOGSTR("RESULT=> ");
2117 DOLOG(typestate_print(get_logfile(),curstack,localset,numlocals));
2120 /* propagate stack and variables to the following block */
2121 if (!superblockend) {
2122 LOG("reaching following block");
2124 while (tbptr->flags == BBDELETED) {
2126 #ifdef TYPECHECK_DEBUG
2127 if ((tbptr->debug_nr) >= m->basicblockcount)
2128 panic("Control flow falls off the last block");
2134 /* We may have to restore the types of the instack slots. They
2135 * have been saved if an <init> call inside the block has
2136 * modified the instack types. (see INVOKESPECIAL) */
2139 stackptr sp = bptr->instack;
2140 stackptr copy = savedstack;
2141 TYPECHECK_COUNT(stat_savedstack);
2142 LOG("restoring saved instack");
2143 TYPESTACK_COPY(sp,copy);
2144 bptr->instack = savedstack;
2148 } /* if block has to be checked */
2150 } /* while blocks */
2152 LOGIF(repeat,"repeat=true");
2155 #ifdef TYPECHECK_STATISTICS
2156 dolog("Typechecker did %4d iterations",count_iterations);
2157 TYPECHECK_COUNT_FREQ(stat_iterations,count_iterations,STAT_ITERATIONS);
2158 TYPECHECK_COUNTIF(jsrencountered,stat_typechecked_jsr);
2161 #ifdef TYPECHECK_DEBUG
2162 for (i=0; i<m->basicblockcount; ++i) {
2163 if (m->basicblocks[i].flags != BBDELETED
2164 && m->basicblocks[i].flags != BBUNDEF
2165 && m->basicblocks[i].flags != BBFINISHED
2166 && m->basicblocks[i].flags != BBTYPECHECK_UNDEF) /* typecheck may never reach
2167 * some exception handlers,
2170 LOG2("block L%03d has invalid flags after typecheck: %d",
2171 m->basicblocks[i].debug_nr,m->basicblocks[i].flags);
2172 panic("Invalid block flags after typecheck");
2177 /* Reset blocks we never reached */
2178 for (i=0; i<m->basicblockcount; ++i) {
2179 if (m->basicblocks[i].flags == BBTYPECHECK_UNDEF)
2180 m->basicblocks[i].flags = BBFINISHED;
2183 LOGimp("exiting typecheck");
2185 /* just return methodinfo* to signal everything was ok */
2192 #endif /* CACAO_TYPECHECK */
2195 * These are local overrides for various environment variables in Emacs.
2196 * Please do not remove this and leave it at the end of the file, where
2197 * Emacs will automagically detect them.
2198 * ---------------------------------------------------------------------
2201 * indent-tabs-mode: t