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 822 2003-12-31 16:00:58Z 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);
154 typeinfo_print_blocks(FILE *file,int vnum,u1 *vtype,typeinfo *vinfo)
159 for (bi=0; bi<block_count; ++bi) {
160 fprintf(file,"%04d: (%3d) ",bi,block[bi].flags);
161 typeinfo_print_block(file,block[bi].instack,
162 vnum,vtype+vnum*bi,vinfo+vnum*bi,NULL);
165 /* for (j=0; j<block[bi].icount; ++j) { */
166 /* fprintf(file,"\t%s\n",icmd_names[block[bi].iinstr[j].opc]); */
169 show_icmd_block(block+bi);
176 /****************************************************************************/
177 /* HELPER FUNCTIONS */
178 /****************************************************************************/
180 /* If a field is checked, definingclass == implementingclass */
182 is_accessible(int flags,classinfo *definingclass,classinfo *implementingclass,
185 /* check access rights */
186 if (class != definingclass) {
187 switch (flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED)) {
191 /* In the cases below, definingclass cannot be an interface */
194 /* XXX check package access */
197 /* XXX check package access and superclass access */
200 if (definingclass != class) {
201 LOG("private access");
205 /* XXX check package access */
207 panic("Invalid access flags");
212 if ((flags & ACC_STATIC) != 0) {
213 LOG("accessing STATIC member with instance");
217 if (implementingclass
218 && !TYPEINFO_IS_NULLTYPE(*instance)
219 && !TYPEINFO_IS_NEWOBJECT(*instance))
223 if (((flags & ACC_PROTECTED) != 0)
224 && builtin_isanysubclass(class,implementingclass))
226 /* For protected access of super class members
227 * the instance must be a subclass of or the same
228 * as the current class. */
230 /* XXX maybe we only are allowed to do this, if we
231 * don't have package access? */
232 /* implementingclass = class; */ /* XXX does not work */
235 /* XXX use classinfo directly? */
236 TYPEINFO_INIT_CLASSINFO(tempinfo,implementingclass);
237 if (!typeinfo_is_assignable(instance,&tempinfo)) {
238 LOG("instance not assignable");
246 if ((flags & ACC_STATIC) == 0) {
247 LOG("accessing non-STATIC member without instance");
255 /****************************************************************************/
257 /****************************************************************************/
259 #ifdef TYPECHECK_DEBUG
260 /*#define TYPECHECK_STATISTICS*/
263 #ifdef TYPECHECK_STATISTICS
264 #define TYPECHECK_COUNT(cnt) (cnt)++
266 #define TYPECHECK_COUNT(cnt)
269 /****************************************************************************/
270 /* INTERNAL DATA STRUCTURES */
271 /****************************************************************************/
273 typedef struct jsr_record jsr_record;
276 * For each basic block we store the chain of JSR instructions which
277 * were used to reach the block (usually zero or one). For more
278 * details on verifying JSR and RET instructions see the Java VM
281 * CAUTION: The fields starting with sbr_ are only valid for the
282 * jsr_record of the first block of the subroutine.
285 basicblock *target; /* target of the JSR instruction (first block of subroutine) */
286 jsr_record *next; /* for chaining in nested try ... finally */ /* XXX make it sbr_next? */
287 u1 *sbr_touched; /* specifies which variables the subroutine touches */
288 u1 *sbr_vtype; /* Types of local variables after RET */
289 typeinfo *sbr_vinfo; /* Types of local variables after RET */
290 u1 touched[1]; /* touched flags for local variables */
293 /****************************************************************************/
294 /* MACROS USED INTERNALLY IN typecheck() */
295 /****************************************************************************/
297 #define TOUCH_VARIABLE(num) \
298 do {if (jsrchain) touched[num] = TOUCHED_YES;} while (0)
299 #define TOUCH_TWOWORD(num) \
300 do {TOUCH_VARIABLE(num);TOUCH_VARIABLE((num)+1);} while (0)
302 #define INDEX_ONEWORD(num) \
303 do { if((num)<0 || (num)>=validlocals) \
304 panic("Invalid local variable index"); } while (0)
305 #define INDEX_TWOWORD(num) \
306 do { if((num)<0 || ((num)+1)>=validlocals) \
307 panic("Invalid local variable index"); } while (0)
309 #define SET_VARIABLE(num,type) \
310 do {vtype[num] = (type); \
311 if ((num)>0 && IS_2_WORD_TYPE(vtype[(num)-1])) { \
312 vtype[(num)-1] = TYPE_VOID; \
313 TOUCH_VARIABLE((num)-1); \
315 TOUCH_VARIABLE(num);} while(0)
317 #define STORE_ONEWORD(num,type) \
318 do {INDEX_ONEWORD(num); \
319 SET_VARIABLE(num,type);} while(0)
321 #define STORE_TWOWORD(num,type) \
322 do {INDEX_TWOWORD(num); \
323 SET_VARIABLE(num,type); \
324 vtype[(num)+1] = TYPE_VOID; \
325 TOUCH_VARIABLE((num)+1);} while(0)
327 #define CHECK_ONEWORD(num,type) \
328 do {INDEX_ONEWORD(num); \
329 if (vtype[(num)] != (type)) panic("Variable type mismatch"); \
330 TOUCH_VARIABLE(num);} while(0)
332 #define CHECK_TWOWORD(num,type) \
333 do {INDEX_TWOWORD(num); \
334 if (vtype[(num)] != (type)) panic("Variable type mismatch"); \
335 TOUCH_VARIABLE(num); \
336 TOUCH_VARIABLE((num)+1);} while(0)
338 /* XXX maybe it's faster to copy always */
339 #define COPYTYPE(source,dest) \
340 {if ((source)->type == TYPE_ADR) \
341 TYPEINFO_COPY((source)->typeinfo,(dest)->typeinfo);}
343 #define ISBUILTIN(v) (iptr->val.a == (functionptr)(v))
345 #define TYPECHECK_STACK(sp,tp) \
346 do { if ((sp)->type != (tp)) \
347 panic("Wrong data type on stack"); } while(0)
349 #define TYPECHECK_ADR(sp) TYPECHECK_STACK(sp,TYPE_ADR)
350 #define TYPECHECK_INT(sp) TYPECHECK_STACK(sp,TYPE_INT)
351 #define TYPECHECK_LNG(sp) TYPECHECK_STACK(sp,TYPE_LNG)
352 #define TYPECHECK_FLT(sp) TYPECHECK_STACK(sp,TYPE_FLT)
353 #define TYPECHECK_DBL(sp) TYPECHECK_STACK(sp,TYPE_DBL)
355 #define TYPECHECK_ARGS1(t1) \
356 do {TYPECHECK_STACK(curstack,t1);} while (0)
357 #define TYPECHECK_ARGS2(t1,t2) \
358 do {TYPECHECK_ARGS1(t1); \
359 TYPECHECK_STACK(curstack->prev,t2);} while (0)
360 #define TYPECHECK_ARGS3(t1,t2,t3) \
361 do {TYPECHECK_ARGS2(t1,t2); \
362 TYPECHECK_STACK(curstack->prev->prev,t3);} while (0)
364 /* TYPECHECK_COPYVARS: copy the types and typeinfos of the current local
365 * variables to the local variables of the target block.
367 * vtype......current local variable types
368 * vinfo......current local variable typeinfos
369 * ttype......local variable types of target block
370 * tinfo......local variable typeinfos of target block
371 * numlocals..number of local variables
375 #define TYPECHECK_COPYVARS \
377 LOG("TYPECHECK_COPYVARS"); \
378 for (macro_i=0; macro_i<numlocals; ++macro_i) { \
379 if ((ttype[macro_i] = vtype[macro_i]) == TYPE_ADR) \
380 TYPEINFO_CLONE(vinfo[macro_i],tinfo[macro_i]); \
383 /* TYPECHECK_MERGEVARS: merge the local variables of the target block
384 * with the current local variables.
386 * vtype......current local variable types
387 * vinfo......current local variable typeinfos
388 * ttype......local variable types of target block
389 * tinfo......local variable typeinfos of target block
390 * numlocals..number of local variables
392 * changed....set to true if any typeinfo has changed
396 #define TYPECHECK_MERGEVARS \
398 LOG("TYPECHECK_MERGEVARS"); \
399 for (macro_i=0; macro_i<numlocals; ++macro_i) { \
400 if ((ttype[macro_i] != TYPE_VOID) && (vtype[macro_i] != ttype[macro_i])) { \
401 LOG3("var %d: type %d + type %d = void",macro_i,ttype[macro_i],vtype[macro_i]); \
402 ttype[macro_i] = TYPE_VOID; \
404 } else if (ttype[macro_i] == TYPE_ADR) { \
405 if ( ((TYPEINFO_IS_PRIMITIVE(tinfo[macro_i])) ? 1 : 0) \
407 ((TYPEINFO_IS_PRIMITIVE(vinfo[macro_i])) ? 1 : 0)) { \
408 LOG1("var %d: primitive + reference merge",macro_i); \
409 ttype[macro_i] = TYPE_VOID; \
413 LOG1("var %d:",macro_i); \
414 LOGINFO(tinfo+macro_i); \
415 LOGINFO(vinfo+macro_i); \
416 changed |= typeinfo_merge(tinfo+macro_i,vinfo+macro_i); \
417 LOGINFO(tinfo+macro_i); \
418 LOGIF(changed,"vars have changed"); \
423 /* TYPECHECK_MERGEJSR:
427 * tbptr......target block
428 * changed....set to true if any typeinfo has changed
429 * numlocals..number of local variables
430 * touched....current touched flags of local variables
432 * macro_i, jsrtemp, jsrtemp2
434 #define TYPECHECK_MERGEJSR \
436 LOG("TYPECHECK_MERGEJSR"); \
437 jsrtemp = jsrbuffer[tbptr-block]; \
438 jsrtemp2 = jsrchain; \
439 while (jsrtemp || jsrtemp2) { \
440 if (!jsrtemp || !jsrtemp2) \
441 panic("Merging JSR subroutines of different depth"); \
442 if (jsrtemp->target != jsrtemp2->target) \
443 panic("Merging different JSR subroutines"); \
444 jsrtemp = jsrtemp->next; \
445 jsrtemp2 = jsrtemp2->next; \
447 jsrtemp = jsrbuffer[tbptr-block]; \
449 for (macro_i=0; macro_i<numlocals; ++macro_i) { \
450 jsrtemp->touched[i] |= touched[i]; \
453 /* TYPECHECK_COPYSTACK: copy the typeinfos of the current stack to
454 * the input stack of the target block.
456 * srcstack...current stack
457 * dststack...input stack of target block
459 #define TYPECHECK_COPYSTACK \
461 LOG("TYPECHECK_COPYSTACK"); \
463 LOG1("copy %d",srcstack->type); \
464 if (!dststack) panic("Stack depth mismatch"); \
465 if (srcstack->type != dststack->type) \
466 panic("Type mismatch on stack"); \
467 if (srcstack->type == TYPE_ADR) { \
468 TYPEINFO_CLONE(srcstack->typeinfo,dststack->typeinfo); \
470 dststack = dststack->prev; \
471 srcstack = srcstack->prev; \
473 if (dststack) panic("Stack depth mismatch"); \
476 /* TYPECHECK_MERGESTACK: merge the input stack of the target block
477 * with the current stack.
479 * srcstack...current stack
480 * dststack...input stack of target block
482 * changed....set to true if any typeinfo has changed
484 #define TYPECHECK_MERGESTACK \
486 LOG("TYPECHECK_MERGESTACK"); \
488 if (!dststack) panic("Stack depth mismatch"); \
489 if (srcstack->type != dststack->type) \
490 panic("Type mismatch on stack"); \
491 if (srcstack->type == TYPE_ADR) { \
492 LOGINFO(&dststack->typeinfo); \
493 LOGINFO(&srcstack->typeinfo); LOGFLUSH; \
494 changed |= typeinfo_merge(&dststack->typeinfo, \
495 &srcstack->typeinfo); \
496 LOGINFO(&dststack->typeinfo); \
497 LOG((changed)?"CHANGED!\n":"not changed.\n"); \
499 dststack = dststack->prev; \
500 srcstack = srcstack->prev; \
502 if (dststack) panic("Stack depth mismatch"); \
506 /* TYPECHECK_CHECK_JSR_CHAIN: checks if the target block is reached by
507 * the same JSR targets on all control paths.
510 * tbptr......target block
511 * jsrchain...current JSR target chain
512 * jsrbuffer..JSR target chain for each basic block
514 * panic if the JSR target chains don't match
518 #define TYPECHECK_CHECK_JSR_CHAIN \
520 jsrtemp = jsrbuffer[tbptr-block]; \
521 if (!jsrtemp) panic("non-subroutine called by JSR"); \
522 if (jsrtemp->target != tbptr) \
523 panic("Merging different JSR subroutines"); \
524 jsrtemp = jsrtemp->next; \
525 jsrtemp2 = jsrchain; \
526 while (jsrtemp || jsrtemp2) { \
527 if (!jsrtemp || !jsrtemp2) \
528 panic("Merging JSR subroutines of different depth"); \
529 if (jsrtemp->target != jsrtemp2->target) \
530 panic("Merging different JSR subroutines"); \
531 jsrtemp = jsrtemp->next; \
532 jsrtemp2 = jsrtemp2->next; \
535 /* TYPECHECK_ADD_JSR: add a JSR target to the current JSR target chain
536 * and store the resulting chain in the target block.
539 * jsrchain...current JSR target chain
540 * tbptr.....the basic block targeted by the JSR
541 * numlocals..number of local variables
542 * jsrbuffer..JSR target chain for each basic block
546 #define TYPECHECK_ADD_JSR \
548 LOG1("adding JSR to block %04d",(tbptr)-block); \
549 jsrtemp = jsrchain; \
551 if (jsrtemp->target == tbptr) \
552 panic("recursive JSR call"); \
553 jsrtemp = jsrtemp->next; \
555 jsrtemp = (jsr_record *) dump_alloc(sizeof(jsr_record)+(numlocals-1)*sizeof(u1)); \
556 jsrtemp->target = (tbptr); \
557 jsrtemp->next = jsrchain; \
558 jsrtemp->sbr_touched = NULL; \
559 memset(&jsrtemp->touched,TOUCHED_NO,sizeof(u1)*numlocals); \
560 jsrbuffer[tbptr-block] = jsrtemp; \
563 /* TYPECHECK_COPYJSR: copy the current JSR chain to the target block.
566 * chain......current JSR target chain
567 * tbptr.....the basic block targeted by the JSR
568 * numlocals..number of local variables
569 * jsrbuffer..JSR target chain for each basic block
570 * touched....current touched flags of local variables
574 #define TYPECHECK_COPYJSR(chain) \
576 LOG("TYPECHECK_COPYJSR"); \
578 jsrtemp = (jsr_record *) dump_alloc(sizeof(jsr_record)+(numlocals-1)*sizeof(u1)); \
579 jsrtemp->target = (chain)->target; \
580 jsrtemp->next = (chain)->next; \
581 jsrtemp->sbr_touched = NULL; \
582 memcpy(&jsrtemp->touched,touched,sizeof(u1)*numlocals); \
583 jsrbuffer[tbptr-block] = jsrtemp; \
586 jsrbuffer[tbptr-block] = NULL; \
589 /* TYPECHECK_BRANCH_BACKWARDS: executed when control flow moves
590 * backwards. Checks if there are uninitialized objects on the
591 * stack or in local variables.
593 * dst........current output stack pointer (not needed for REACH_THROW)
594 * vtype......current local variable types
595 * vinfo......current local variable typeinfos
599 #define TYPECHECK_BRANCH_BACKWARDS \
604 if (srcstack->type == TYPE_ADR && \
605 TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo)) \
606 panic("Branching backwards with uninitialized object on stack"); \
607 srcstack = srcstack->prev; \
609 for (macro_i=0; macro_i<numlocals; ++macro_i) \
610 if (vtype[macro_i] == TYPE_ADR && \
611 TYPEINFO_IS_NEWOBJECT(vinfo[macro_i])) \
612 panic("Branching backwards with uninitialized object in local variable"); \
615 /* XXX convert this into a function */
616 /* TYPECHECK_REACH: executed, when the target block (tbptr) can be reached
617 * from the current block (bptr). The types of local variables and
618 * stack slots are propagated to the target block.
620 * bptr.......current block
621 * tbptr......target block
622 * dst........current output stack pointer (not needed for REACH_THROW)
623 * numlocals..number of local variables
624 * vtype......current local variable types
625 * vinfo......current local variable typeinfos
626 * jsrchain...current JSR target chain
627 * jsrbuffer..JSR target chain for each basic block
628 * way........in which way the block is reached (REACH_ constant)
629 * touched....current touched flags of local variables
631 * repeat.....changed to true if a block before the current
634 * ttype, tinfo, srcstack, dststack, changed, macro_i
636 #define TYPECHECK_REACH(way) \
638 LOG2("reaching block %04d (%d)",tbptr-block,way); \
639 if (tbptr <= bptr && way != REACH_THROW) \
640 TYPECHECK_BRANCH_BACKWARDS; \
642 dststack = tbptr->instack; \
643 ttype = vartype + numlocals*(tbptr-block); \
644 tinfo = vartypeinfo + numlocals*(tbptr-block); \
645 if (tbptr->flags == BBTYPECHECK_UNDEF) { \
646 /* This block is reached for the first time */ \
647 if (way == REACH_JSR) { \
649 TYPECHECK_COPYVARS; \
652 if (way != REACH_THROW) TYPECHECK_COPYJSR(jsrchain); \
653 TYPECHECK_COPYVARS; \
655 if (way != REACH_THROW) TYPECHECK_COPYSTACK; \
658 /* This block has been reached before */ \
660 if (way == REACH_JSR) \
661 TYPECHECK_CHECK_JSR_CHAIN; \
662 else if (way != REACH_THROW) \
663 TYPECHECK_MERGEJSR; \
664 TYPECHECK_MERGEVARS; \
665 if (way != REACH_THROW) TYPECHECK_MERGESTACK; \
669 tbptr->flags = BBTYPECHECK_REACHED; \
670 if (tbptr <= bptr) {repeat = true; LOG("REPEAT!");} \
675 /* TYPECHECK_LEAVE: executed when the method is exited non-abruptly
677 * class........class of the current method
678 * numlocals....number of local variables
679 * vtype........current local variable types
680 * vinfo........current local variable typeinfos
681 * initmethod...true if this is an <init> method
683 #define TYPECHECK_LEAVE \
685 if (initmethod && class != class_java_lang_Object) { \
686 /* check the marker variable */ \
687 LOG("Checking <init> marker"); \
688 if (vtype[numlocals-1] == TYPE_VOID) \
689 panic("<init> method does not initialize 'this'"); \
693 /****************************************************************************/
695 /****************************************************************************/
697 #define MAXPARAMS 255
699 /* typecheck is called directly after analyse_stack */
703 int b_count, b_index;
704 stackptr curstack; /* input stack top for current instruction */
705 stackptr srcstack; /* source stack for copying and merging */
706 stackptr dststack; /* target stack for copying and merging */
707 int opcode; /* current opcode */
708 int macro_i, i; /* temporary counters */
709 int len; /* for counting instructions, etc. */
710 bool superblockend; /* true if no fallthrough to next block */
711 bool repeat; /* if true, blocks are iterated over again */
712 bool changed; /* used in macros */
713 instruction *iptr; /* pointer to current instruction */
714 basicblock *bptr; /* pointer to current basic block */
715 basicblock *tbptr; /* temporary for target block */
716 int numlocals; /* number of local variables */
717 int validlocals; /* number of valid local variable indices */
718 u1 *vartype; /* type of each local for each basic block */
719 typeinfo *vartypeinfo; /* type of each local for each basic block */
720 u1 *vtype; /* type of each local for current instruction */
721 typeinfo *vinfo; /* type of each local for current instruction */
722 u1 *ttype; /* temporary pointer */
723 typeinfo *tinfo; /* temporary pointer */
724 typeinfo tempinfo; /* temporary */
725 int returntype; /* return type of current method */
726 typeinfo returntypeinfo; /* typeinfo for return type */
727 u1 *ptype; /* parameter types of called method */
728 typeinfo *pinfo; /* parameter typeinfos of called method */
729 int rtype; /* return type of called method */
730 typeinfo rinfo; /* typeinfo for return type of called method */
731 stackptr dst; /* output stack of current instruction */
732 basicblock **tptr; /* pointer into target list of switch instructions */
733 jsr_record **jsrbuffer; /* JSR target chain for each basic block */
734 jsr_record *jsrchain; /* JSR chain for current block */
735 jsr_record *jsrtemp,*jsrtemp2; /* temporary variables */
736 jsr_record *subroutine; /* jsr_record of the current subroutine */
737 u1 *touched; /* touched flags for local variables */
738 xtable **handlers; /* active exception handlers */
739 classinfo *cls; /* temporary */
740 bool maythrow; /* true if this instruction may throw */
741 utf *name_init; /* "<init>" */
742 bool initmethod; /* true if this is an "<init>" method */
743 builtin_descriptor *builtindesc;
745 #ifdef TYPECHECK_STATISTICS
746 int count_iterations = 0;
749 LOGSTR("\n==============================================================================\n");
750 DOLOG(show_icmd_method());
751 LOGSTR("\n==============================================================================\n");
752 LOGimpSTR("Entering typecheck: ");
753 LOGimpSTRu(method->name);
755 LOGimpSTRu(method->descriptor);
756 LOGimpSTR(" (class ");
757 LOGimpSTRu(method->class->name);
760 name_init = utf_new_char("<init>");
761 initmethod = (method->name == name_init);
763 ptype = DMNEW(u1,MAXPARAMS);
764 pinfo = DMNEW(typeinfo,MAXPARAMS);
766 LOG("Buffer allocated.\n");
768 /* reset all BBFINISHED blocks to BBTYPECHECK_UNDEF. */
769 b_count = block_count;
771 while (--b_count >= 0) {
772 #ifdef TYPECHECK_DEBUG
773 if (bptr->flags != BBFINISHED && bptr->flags != BBDELETED
774 && bptr->flags != BBUNDEF)
777 LOGSTR1("block flags: %d\n",bptr->flags); LOGFLUSH;
778 panic("Internal error: Unexpected block flags in typecheck()");
781 if (bptr->flags >= BBFINISHED) {
782 bptr->flags = BBTYPECHECK_UNDEF;
787 /* The first block is always reached */
788 if (block_count && block[0].flags == BBTYPECHECK_UNDEF)
789 block[0].flags = BBTYPECHECK_REACHED;
791 LOG("Blocks reset.\n");
793 /* number of local variables */
795 /* In <init> methods we use an extra local variable to signal if
796 * the 'this' reference has been initialized. */
797 numlocals = maxlocals;
798 validlocals = numlocals;
799 if (initmethod) numlocals++;
801 /* allocate the buffers for local variables */
802 vartype = DMNEW(u1,numlocals * (block_count+1));
803 vartypeinfo = DMNEW(typeinfo,numlocals * (block_count+1));
804 touched = DMNEW(u1,numlocals);
805 vtype = vartype + numlocals * block_count;
806 vinfo = vartypeinfo + numlocals * block_count;
807 memset(vartype,TYPE_VOID,numlocals * (block_count+1) * sizeof(u1));
808 memset(vartypeinfo,0,numlocals * (block_count+1) * sizeof(typeinfo));
810 LOG("Variable buffer initialized.\n");
812 /* allocate the buffer for storing JSR target chains */
813 jsrbuffer = DMNEW(jsr_record*,block_count);
814 memset(jsrbuffer,0,block_count * sizeof(jsr_record*));
817 LOG("jsrbuffer initialized.\n");
819 /* allocate the buffer of active exception handlers */
820 handlers = DMNEW(xtable*,method->exceptiontablelength + 1);
822 /* initialize the variable types of the first block */
823 /* to the types of the arguments */
827 /* if this is an instance method initialize the "this" ref type */
828 if (!(method->flags & ACC_STATIC)) {
829 *ttype++ = TYPE_ADDRESS;
831 TYPEINFO_INIT_NEWOBJECT(*tinfo,NULL);
833 TYPEINFO_INIT_CLASSINFO(*tinfo,class);
837 LOG("'this' argument set.\n");
839 /* the rest of the arguments and the return type */
840 typeinfo_init_from_method_args(method->descriptor,ttype,tinfo,
841 numlocals - (tinfo-vartypeinfo),
842 true, /* two word types use two slots */
843 &returntype,&returntypeinfo);
845 LOG("Arguments set.\n");
847 /* initialize the input stack of exception handlers */
848 for (i=0; i<method->exceptiontablelength; ++i) {
849 cls = extable[i].catchtype;
850 if (!cls) cls = class_java_lang_Throwable;
851 LOGSTR1("handler %i: ",i); LOGSTRu(cls->name); LOGNL;
852 TYPEINFO_INIT_CLASSINFO(extable[i].handler->instack->typeinfo,cls);
855 LOG("Exception handler stacks set.\n");
857 /* loop while there are still blocks to be checked */
859 TYPECHECK_COUNT(count_iterations);
863 b_count = block_count;
866 while (--b_count >= 0) {
867 LOGSTR1("---- BLOCK %04d, ",bptr-block);
868 LOGSTR1("blockflags: %d\n",bptr->flags);
871 if (bptr->flags == BBTYPECHECK_REACHED) {
872 LOGSTR1("\n---- BLOCK %04d ------------------------------------------------\n",bptr-block);
875 superblockend = false;
876 bptr->flags = BBFINISHED;
877 b_index = bptr - block;
879 /* init stack at the start of this block */
880 curstack = bptr->instack;
882 /* determine the active exception handlers for this block */
883 /* XXX could use a faster algorithm with sorted lists or
886 for (i=0; i<method->exceptiontablelength; ++i) {
887 if ((extable[i].start <= bptr) && (extable[i].end > bptr)) {
888 LOG1("active handler L%03d",extable[i].handler->debug_nr);
889 handlers[len++] = extable + i;
892 handlers[len] = NULL;
894 /* init variable types at the start of this block */
895 for (i=0; i<numlocals; ++i) {
896 vtype[i] = vartype[numlocals*b_index + i];
897 TYPEINFO_COPY(vartypeinfo[numlocals*b_index + i],vinfo[i]);
900 vtype[i] == TYPE_ADR && TYPEINFO_IS_NEWOBJECT(vinfo[i]))
901 panic("Uninitialized object in local variable inside try block");
904 /* init JSR target chain */
905 if ((jsrchain = jsrbuffer[b_index]) != NULL) {
906 #ifdef TYPECHECK_VERBOSE
907 if (typecheckverbose) {
908 LOGSTR("jsr chain:");
911 LOGSTR1(" L%03d",jsrtemp->target->debug_nr);
912 jsrtemp = jsrtemp->next;
919 subroutine = jsrbuffer[jsrchain->target - block];
920 memcpy(touched,jsrchain->touched,sizeof(u1)*numlocals);
924 #ifdef TYPECHECK_VERBOSE
925 if (typecheckverbose) {
926 if (subroutine) {LOGSTR1("subroutine L%03d\n",subroutine->target->debug_nr);LOGFLUSH;}
927 typeinfo_print_block(get_logfile(),curstack,numlocals,vtype,vinfo,(jsrchain) ? touched : NULL);
932 /* loop over the instructions */
936 DOLOG(show_icmd(iptr,false));
946 /****************************************/
947 /* STACK MANIPULATIONS */
949 /* We just need to copy the typeinfo */
950 /* for slots containing addresses. */
952 /* XXX We assume that the destination stack
953 * slots were continuously allocated in
954 * memory. (The current implementation in
959 COPYTYPE(curstack,dst);
963 COPYTYPE(curstack,dst);
964 COPYTYPE(curstack,dst-2);
965 COPYTYPE(curstack->prev,dst-1);
969 COPYTYPE(curstack,dst);
970 COPYTYPE(curstack,dst-3);
971 COPYTYPE(curstack->prev,dst-1);
972 COPYTYPE(curstack->prev->prev,dst-2);
976 COPYTYPE(curstack,dst);
977 COPYTYPE(curstack->prev,dst-1);
981 COPYTYPE(curstack,dst);
982 COPYTYPE(curstack->prev,dst-1);
983 COPYTYPE(curstack,dst-3);
984 COPYTYPE(curstack->prev,dst-4);
985 COPYTYPE(curstack->prev->prev,dst-2);
989 COPYTYPE(curstack,dst);
990 COPYTYPE(curstack->prev,dst-1);
991 COPYTYPE(curstack,dst-4);
992 COPYTYPE(curstack->prev,dst-5);
993 COPYTYPE(curstack->prev->prev,dst-2);
994 COPYTYPE(curstack->prev->prev->prev,dst-3);
998 COPYTYPE(curstack,dst-1);
999 COPYTYPE(curstack->prev,dst);
1002 /****************************************/
1003 /* LOADING ADDRESS FROM VARIABLE */
1006 CHECK_ONEWORD(iptr->op1,TYPE_ADR);
1008 /* loading a returnAddress is not allowed */
1009 if (TYPEINFO_IS_PRIMITIVE(vinfo[iptr->op1]))
1010 panic("illegal instruction: ALOAD loading returnAddress");
1012 TYPEINFO_COPY(vinfo[iptr->op1],dst->typeinfo);
1015 /****************************************/
1016 /* STORING ADDRESS TO VARIABLE */
1020 TYPEINFO_IS_NEWOBJECT(curstack->typeinfo))
1021 panic("Storing uninitialized object in local variable inside try block");
1023 STORE_ONEWORD(iptr->op1,TYPE_ADDRESS);
1024 TYPEINFO_COPY(curstack->typeinfo,vinfo[iptr->op1]);
1027 /****************************************/
1028 /* LOADING ADDRESS FROM ARRAY */
1031 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(curstack->prev->typeinfo))
1032 panic("illegal instruction: AALOAD on non-reference array");
1034 typeinfo_init_component(&curstack->prev->typeinfo,&dst->typeinfo);
1038 /****************************************/
1042 if (!TYPEINFO_IS_REFERENCE(curstack->prev->typeinfo))
1043 panic("illegal instruction: PUTFIELD on non-reference");
1044 if (TYPEINFO_IS_ARRAY(curstack->prev->typeinfo)) /* XXX arraystub */
1045 panic("illegal instruction: PUTFIELD on array");
1047 /* check if the value is assignable to the field */
1049 fieldinfo *fi = (fieldinfo*) iptr[0].val.a;
1051 if (TYPEINFO_IS_NEWOBJECT(curstack->prev->typeinfo)) {
1053 && !TYPEINFO_NEWOBJECT_INSTRUCTION(curstack->prev->typeinfo))
1055 /* uninitialized "this" instance */
1056 if (fi->class != class || (fi->flags & ACC_STATIC) != 0)
1057 panic("Setting unaccessible field in uninitialized object");
1060 panic("PUTFIELD on uninitialized object");
1064 if (!is_accessible(fi->flags,fi->class,fi->class,
1065 &(curstack->prev->typeinfo)))
1066 panic("PUTFIELD: field is not accessible");
1069 /* XXX ---> unify with ICMD_PUTSTATIC? */
1071 if (curstack->type != fi->type)
1072 panic("PUTFIELD type mismatch");
1073 if (fi->type == TYPE_ADR) {
1074 TYPEINFO_INIT_FROM_FIELDINFO(rinfo,fi);
1075 if (!typeinfo_is_assignable(&(curstack->typeinfo),
1077 panic("PUTFIELD reference type not assignable");
1083 case ICMD_PUTSTATIC:
1084 /* check if the value is assignable to the field */
1086 fieldinfo *fi = (fieldinfo*) iptr[0].val.a;
1088 if (!is_accessible(fi->flags,fi->class,fi->class,NULL))
1089 panic("PUTSTATIC: field is not accessible");
1091 if (curstack->type != fi->type)
1092 panic("PUTSTATIC type mismatch");
1093 if (fi->type == TYPE_ADR) {
1094 TYPEINFO_INIT_FROM_FIELDINFO(rinfo,fi);
1095 if (!typeinfo_is_assignable(&(curstack->typeinfo),
1097 panic("PUTSTATIC reference type not assignable");
1104 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1105 panic("illegal instruction: GETFIELD on non-reference");
1106 if (TYPEINFO_IS_ARRAY(curstack->typeinfo))
1107 panic("illegal instruction: GETFIELD on array");
1110 fieldinfo *fi = (fieldinfo *)(iptr->val.a);
1112 if (!is_accessible(fi->flags,fi->class,fi->class,
1113 &(curstack->typeinfo)))
1114 panic("GETFIELD: field is not accessible");
1116 if (dst->type == TYPE_ADR) {
1117 TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi);
1120 /* XXX check field type? */
1121 TYPEINFO_INIT_PRIMITIVE(dst->typeinfo);
1127 case ICMD_GETSTATIC:
1129 fieldinfo *fi = (fieldinfo *)(iptr->val.a);
1131 if (!is_accessible(fi->flags,fi->class,fi->class,NULL))
1132 panic("GETSTATIC: field is not accessible");
1134 if (dst->type == TYPE_ADR) {
1135 TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi);
1138 /* XXX check field type? */
1139 TYPEINFO_INIT_PRIMITIVE(dst->typeinfo);
1145 /****************************************/
1146 /* PRIMITIVE ARRAY ACCESS */
1148 case ICMD_ARRAYLENGTH:
1149 /* XXX should this also work on arraystubs? */
1150 if (!TYPEINFO_MAYBE_ARRAY(curstack->typeinfo))
1151 panic("illegal instruction: ARRAYLENGTH on non-array");
1156 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_BOOLEAN)
1157 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_BYTE))
1158 panic("Array type mismatch");
1162 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_CHAR))
1163 panic("Array type mismatch");
1167 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_DOUBLE))
1168 panic("Array type mismatch");
1172 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_FLOAT))
1173 panic("Array type mismatch");
1177 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_INT))
1178 panic("Array type mismatch");
1182 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_SHORT))
1183 panic("Array type mismatch");
1187 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_LONG))
1188 panic("Array type mismatch");
1193 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_BOOLEAN)
1194 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_BYTE))
1195 panic("Array type mismatch");
1199 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_CHAR))
1200 panic("Array type mismatch");
1204 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_DOUBLE))
1205 panic("Array type mismatch");
1209 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_FLOAT))
1210 panic("Array type mismatch");
1214 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_INT))
1215 panic("Array type mismatch");
1219 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_SHORT))
1220 panic("Array type mismatch");
1224 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_LONG))
1225 panic("Array type mismatch");
1229 /****************************************/
1230 /* OPERATIONS WITH UNCHECKED INPUT */
1232 case ICMD_CHECKCAST:
1233 TYPECHECK_ADR(curstack);
1234 /* returnAddress is not allowed */
1235 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1236 panic("Illegal instruction: CHECKCAST on non-reference");
1238 /* XXX check if the cast can be done statically */
1239 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,(classinfo *)iptr[0].val.a);
1244 case ICMD_INSTANCEOF:
1245 TYPECHECK_ADR(curstack);
1246 /* returnAddress is not allowed */
1247 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1248 panic("Illegal instruction: INSTANCEOF on non-reference");
1250 /* XXX optimize statically? */
1254 if (iptr->val.a == NULL)
1255 TYPEINFO_INIT_NULLTYPE(dst->typeinfo);
1257 /* XXX constants for builtin functions */
1258 /* string constants */
1259 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,class_java_lang_String);
1262 /****************************************/
1263 /* BRANCH INSTRUCTIONS */
1266 superblockend = true;
1269 case ICMD_IFNONNULL:
1276 case ICMD_IF_ICMPEQ:
1277 case ICMD_IF_ICMPNE:
1278 case ICMD_IF_ICMPLT:
1279 case ICMD_IF_ICMPGE:
1280 case ICMD_IF_ICMPGT:
1281 case ICMD_IF_ICMPLE:
1282 case ICMD_IF_ACMPEQ:
1283 case ICMD_IF_ACMPNE:
1290 case ICMD_IF_LCMPEQ:
1291 case ICMD_IF_LCMPNE:
1292 case ICMD_IF_LCMPLT:
1293 case ICMD_IF_LCMPGE:
1294 case ICMD_IF_LCMPGT:
1295 case ICMD_IF_LCMPLE:
1296 tbptr = (basicblock *) iptr->target;
1298 /* propagate stack and variables to the target block */
1299 TYPECHECK_REACH(REACH_STD);
1303 /****************************************/
1306 case ICMD_TABLESWITCH:
1308 s4 *s4ptr = iptr->val.a;
1309 s4ptr++; /* skip default */
1310 i = *s4ptr++; /* low */
1311 i = *s4ptr++ - i + 2; /* +1 for default target */
1313 goto switch_instruction_tail;
1315 case ICMD_LOOKUPSWITCH:
1317 s4 *s4ptr = iptr->val.a;
1318 s4ptr++; /* skip default */
1319 i = *s4ptr++ + 1; /* count +1 for default target */
1321 switch_instruction_tail:
1322 tptr = (basicblock **)iptr->target;
1326 LOG2("target %d is block %04d",(tptr-(basicblock **)iptr->target)-1,tbptr-block);
1327 TYPECHECK_REACH(REACH_STD);
1330 superblockend = true;
1333 /****************************************/
1334 /* RETURNS AND THROW */
1337 TYPEINFO_INIT_CLASSINFO(tempinfo,class_java_lang_Throwable);
1338 if (!typeinfo_is_assignable(&curstack->typeinfo,&tempinfo))
1339 panic("illegal instruction: ATHROW on non-Throwable");
1340 superblockend = true;
1345 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1346 panic("illegal instruction: ARETURN on non-reference");
1348 if (returntype != TYPE_ADDRESS
1349 || !typeinfo_is_assignable(&curstack->typeinfo,&returntypeinfo))
1350 panic("Return type mismatch");
1354 if (returntype != TYPE_INT) panic("Return type mismatch");
1358 if (returntype != TYPE_LONG) panic("Return type mismatch");
1362 if (returntype != TYPE_FLOAT) panic("Return type mismatch");
1366 if (returntype != TYPE_DOUBLE) panic("Return type mismatch");
1370 if (returntype != TYPE_VOID) panic("Return type mismatch");
1373 superblockend = true;
1377 /****************************************/
1378 /* SUBROUTINE INSTRUCTIONS */
1383 /* XXX This is a dirty hack. It is needed
1384 * because of the special handling of ICMD_JSR in stack.c
1386 dst = (stackptr) iptr->val.a;
1388 /* push return address */
1389 TYPEINFO_INIT_PRIMITIVE(dst->typeinfo);
1391 LOG("reaching block...");
1393 /* add the target to the JSR target chain and */
1394 /* propagate stack and variables to the target block */
1395 tbptr = (basicblock *) iptr->target;
1396 TYPECHECK_REACH(REACH_JSR);
1398 /* set dst to the stack after the subroutine execution */
1399 /* XXX We assume (as in stack.c) that the
1400 * subroutine returns the stack as it was
1401 * before the JSR instruction. Is this
1406 /* Find the jsr_record of the called subroutine */
1407 jsrtemp = jsrbuffer[tbptr - block];
1409 /* Check if we already calculated (at least
1410 * for one RET) which variables the
1411 * subroutine touches.
1413 if (jsrtemp->sbr_touched) {
1414 /* Calculate the local variables after the subroutine call */
1415 for (i=0; i<numlocals; ++i)
1416 if (jsrtemp->sbr_touched[i] != TOUCHED_NO) {
1418 if ((vtype[i] = jsrtemp->sbr_vtype[i]) == TYPE_ADR)
1419 TYPEINFO_CLONE(jsrtemp->sbr_vinfo[i],vinfo[i]);
1422 /* continue after the JSR call */
1423 superblockend = false;
1426 /* We cannot proceed until the subroutine has been typechecked. */
1427 /* XXX actually we would not have to check this block again */
1428 bptr->flags = BBTYPECHECK_REACHED;
1430 superblockend = true;
1432 /* XXX may throw? I don't think. */
1436 /* check returnAddress variable */
1437 CHECK_ONEWORD(iptr->op1,TYPE_ADR);
1439 if (!TYPEINFO_IS_PRIMITIVE(vinfo[iptr->op1]))
1440 panic("illegal instruction: RET using non-returnAddress variable");
1442 /* check if we are inside a subroutine */
1444 panic("RET outside of subroutine");
1446 /* determine which variables are touched by this subroutine */
1447 /* and their types */
1448 if (subroutine->sbr_touched) {
1449 for (i=0; i<numlocals; ++i)
1450 subroutine->sbr_touched[i] |= touched[i];
1451 ttype = subroutine->sbr_vtype;
1452 tinfo = subroutine->sbr_vinfo;
1453 TYPECHECK_MERGEVARS;
1456 subroutine->sbr_touched = DMNEW(u1,numlocals);
1457 memcpy(subroutine->sbr_touched,touched,sizeof(u1)*numlocals);
1458 subroutine->sbr_vtype = DMNEW(u1,numlocals);
1459 memcpy(subroutine->sbr_vtype,vtype,sizeof(u1)*numlocals);
1460 subroutine->sbr_vinfo = DMNEW(typeinfo,numlocals);
1461 for (i=0; i<numlocals; ++i)
1462 if (vtype[i] == TYPE_ADR)
1463 TYPEINFO_CLONE(vinfo[i],subroutine->sbr_vinfo[i]);
1465 /* XXX check if subroutine changed types? */
1467 LOGSTR("subroutine touches:");
1468 DOLOG(typeinfo_print_locals(get_logfile(),subroutine->sbr_vtype,subroutine->sbr_vinfo,
1469 subroutine->sbr_touched,numlocals));
1472 /* reach blocks after JSR statements */
1473 for (i=0; i<block_count; ++i) {
1475 LOG1("block L%03d",tbptr->debug_nr);
1476 if (tbptr->iinstr[tbptr->icount - 1].opc != ICMD_JSR)
1478 LOG("ends with JSR");
1479 if ((basicblock*) tbptr->iinstr[tbptr->icount - 1].target != subroutine->target)
1483 LOG1("RET reaches block %04d",tbptr-block);
1485 /*TYPECHECK_REACH(REACH_RET);*/
1488 superblockend = true;
1491 /****************************************/
1494 case ICMD_INVOKEVIRTUAL:
1495 case ICMD_INVOKESPECIAL:
1496 case ICMD_INVOKESTATIC:
1497 case ICMD_INVOKEINTERFACE:
1499 methodinfo *mi = (methodinfo*) iptr->val.a;
1500 bool specialmethod = (mi->name->text[0] == '<');
1501 bool callinginit = (opcode == ICMD_INVOKESPECIAL && mi->name == name_init);
1503 classinfo *initclass;
1505 if (specialmethod && !callinginit)
1506 panic("Invalid invocation of special method");
1508 if (opcode == ICMD_INVOKESPECIAL) {
1509 /* XXX for INVOKESPECIAL: check if the invokation is done at all */
1511 /* (If callinginit the class is checked later.) */
1513 if (!builtin_isanysubclass(class,mi->class))
1514 panic("Illegal instruction: INVOKESPECIAL calling non-superclass method");
1518 /* fetch parameter types and return type */
1519 /* XXX might use dst->typeinfo directly if non void */
1521 if (opcode != ICMD_INVOKESTATIC) {
1522 ptype[0] = TYPE_ADR;
1523 TYPEINFO_INIT_CLASSINFO(pinfo[0],mi->class);
1526 typeinfo_init_from_method_args(mi->descriptor,ptype+i,pinfo+i,
1530 /* check parameter types */
1531 srcstack = curstack;
1532 i = mi->paramcount; /* number of parameters including 'this'*/
1535 if (srcstack->type != ptype[i])
1536 panic("Parameter type mismatch in method invocation");
1537 if (srcstack->type == TYPE_ADR) {
1538 LOGINFO(&(srcstack->typeinfo));
1540 if (i==0 && callinginit)
1542 /* typeinfo tempinfo; */
1544 /* first argument to <init> method */
1545 if (!TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo))
1546 panic("Calling <init> on initialized object");
1548 /* get the address of the NEW instruction */
1549 LOGINFO(&(srcstack->typeinfo));
1550 ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(srcstack->typeinfo);
1551 initclass = (ins) ? (classinfo*)ins[-1].val.a : method->class;
1552 LOGSTR("class: "); LOGSTRu(initclass->name); LOGNL;
1555 /* (This is checked below.) */
1556 /* TYPEINFO_INIT_CLASSINFO(tempinfo,initclass); */
1557 /* if (!typeinfo_is_assignable(&tempinfo,pinfo+0)) */
1558 /* panic("Parameter reference type mismatch in <init> invocation"); */
1561 if (!typeinfo_is_assignable(&(srcstack->typeinfo),pinfo+i))
1562 panic("Parameter reference type mismatch in method invocation");
1567 if (i) srcstack = srcstack->prev;
1570 /* XXX We should resolve the method and pass its
1571 * class as implementingclass to is_accessible. */
1572 if (!is_accessible(mi->flags,mi->class,NULL,
1573 (opcode == ICMD_INVOKESTATIC) ? NULL
1574 : &(srcstack->typeinfo)))
1575 panic("Invoking unaccessible method");
1577 LOG("checking return type");
1578 if (rtype != TYPE_VOID) {
1579 if (rtype != dst->type)
1580 panic("Return type mismatch in method invocation");
1581 TYPEINFO_COPY(rinfo,dst->typeinfo);
1585 LOG("replacing uninitialized object");
1586 /* replace uninitialized object type on stack */
1589 if (srcstack->type == TYPE_ADR
1590 && TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo)
1591 && TYPEINFO_NEWOBJECT_INSTRUCTION(srcstack->typeinfo) == ins)
1593 LOG("replacing uninitialized type on stack");
1594 TYPEINFO_INIT_CLASSINFO(srcstack->typeinfo,initclass);
1596 srcstack = srcstack->prev;
1598 /* replace uninitialized object type in locals */
1599 for (i=0; i<numlocals; ++i) {
1600 if (vtype[i] == TYPE_ADR
1601 && TYPEINFO_IS_NEWOBJECT(vinfo[i])
1602 && TYPEINFO_NEWOBJECT_INSTRUCTION(vinfo[i]) == ins)
1604 LOG1("replacing uninitialized type in local %d",i);
1605 TYPEINFO_INIT_CLASSINFO(vinfo[i],initclass);
1609 /* initializing the 'this' reference? */
1611 #ifdef TYPECHECK_DEBUG
1613 panic("Internal error: calling <init> on this in non-<init> method.");
1615 /* must be <init> of current class or direct superclass */
1616 if (mi->class != class && mi->class != class->super)
1617 panic("<init> calling <init> of the wrong class");
1619 /* set our marker variable to type int */
1620 LOG("setting <init> marker");
1621 vtype[numlocals-1] = TYPE_INT;
1624 /* initializing an instance created with NEW */
1625 /* XXX is this strictness ok? */
1626 if (mi->class != initclass)
1627 panic("Calling <init> method of the wrong class");
1634 case ICMD_MULTIANEWARRAY:
1637 arraydescriptor *desc;
1639 /* check the array lengths on the stack */
1641 if (i<1) panic("MULTIANEWARRAY with dimensions < 1");
1642 srcstack = curstack;
1645 panic("MULTIANEWARRAY missing array length");
1646 if (srcstack->type != TYPE_INT)
1647 panic("MULTIANEWARRAY using non-int as array length");
1648 srcstack = srcstack->prev;
1651 /* check array descriptor */
1652 arrayvftbl = (vftbl*) iptr[0].val.a;
1654 panic("MULTIANEWARRAY with unlinked class");
1655 if ((desc = arrayvftbl->arraydesc) == NULL)
1656 panic("MULTIANEWARRAY with non-array class");
1657 if (desc->dimension < iptr[0].op1)
1658 panic("MULTIANEWARRAY dimension to high");
1660 /* set the array type of the result */
1661 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,arrayvftbl->class);
1667 if (ISBUILTIN(BUILTIN_aastore)) {
1668 TYPECHECK_ADR(curstack);
1669 TYPECHECK_INT(curstack->prev);
1670 TYPECHECK_ADR(curstack->prev->prev);
1671 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(curstack->prev->prev->typeinfo))
1672 panic("illegal instruction: AASTORE to non-reference array");
1676 typeinfo_init_component(&curstack->prev->prev->typeinfo,&tempinfo);
1677 if (!typeinfo_is_assignable(&curstack->typeinfo,&tempinfo))
1678 panic("illegal instruction: AASTORE to incompatible type");
1682 /* XXX put these checks in a function */
1683 builtindesc = builtin_desc;
1684 while (builtindesc->opcode && builtindesc->builtin
1685 != (functionptr) iptr->val.a) builtindesc++;
1686 if (!builtindesc->opcode) {
1687 dolog("Builtin not in table: %s",icmd_builtin_name((functionptr) iptr->val.a));
1688 panic("Internal error: builtin not found in table");
1690 TYPECHECK_ARGS3(builtindesc->type_s3,builtindesc->type_s2,builtindesc->type_s1);
1692 maythrow = true; /* XXX better safe than sorry */
1696 if (ISBUILTIN(BUILTIN_newarray))
1699 TYPECHECK_INT(curstack->prev);
1700 if (iptr[-1].opc != ICMD_ACONST)
1701 panic("illegal instruction: builtin_newarray without classinfo");
1702 vft = (vftbl *)iptr[-1].val.a;
1704 panic("ANEWARRAY with unlinked class");
1705 if (!vft->arraydesc)
1706 panic("ANEWARRAY with non-array class");
1707 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,vft->class);
1709 else if (ISBUILTIN(BUILTIN_arrayinstanceof))
1712 TYPECHECK_ADR(curstack->prev);
1713 if (iptr[-1].opc != ICMD_ACONST)
1714 panic("illegal instruction: builtin_arrayinstanceof without classinfo");
1715 vft = (vftbl *)iptr[-1].val.a;
1717 panic("INSTANCEOF with unlinked class");
1718 if (!vft->arraydesc)
1719 panic("internal error: builtin_arrayinstanceof with non-array class");
1721 else if (ISBUILTIN(BUILTIN_checkarraycast)) {
1723 TYPECHECK_ADR(curstack->prev);
1724 if (iptr[-1].opc != ICMD_ACONST)
1725 panic("illegal instruction: BUILTIN_checkarraycast without classinfo");
1726 vft = (vftbl *)iptr[-1].val.a;
1728 panic("CHECKCAST with unlinked class");
1729 if (!vft->arraydesc)
1730 panic("internal error: builtin_checkarraycast with non-array class");
1731 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,vft->class);
1734 builtindesc = builtin_desc;
1735 while (builtindesc->opcode && builtindesc->builtin
1736 != (functionptr) iptr->val.a) builtindesc++;
1737 if (!builtindesc->opcode) {
1738 dolog("Builtin not in table: %s",icmd_builtin_name((functionptr) iptr->val.a));
1739 panic("Internal error: builtin not found in table");
1741 TYPECHECK_ARGS2(builtindesc->type_s2,builtindesc->type_s1);
1743 maythrow = true; /* XXX better safe than sorry */
1747 if (ISBUILTIN(BUILTIN_new)) {
1749 if (iptr[-1].opc != ICMD_ACONST)
1750 panic("illegal instruction: builtin_new without classinfo");
1751 cls = (classinfo *) iptr[-1].val.a;
1753 panic("Internal error: NEW with unlinked class");
1754 /* The following check also forbids array classes and interfaces: */
1755 if ((cls->flags & ACC_ABSTRACT) != 0)
1756 panic("Invalid instruction: NEW creating instance of abstract class");
1757 TYPEINFO_INIT_NEWOBJECT(dst->typeinfo,iptr);
1759 /* XXX unify the following cases */
1760 else if (ISBUILTIN(BUILTIN_newarray_boolean)) {
1761 TYPECHECK_INT(curstack);
1762 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BOOLEAN);
1764 else if (ISBUILTIN(BUILTIN_newarray_char)) {
1765 TYPECHECK_INT(curstack);
1766 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_CHAR);
1768 else if (ISBUILTIN(BUILTIN_newarray_float)) {
1769 TYPECHECK_INT(curstack);
1770 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_FLOAT);
1772 else if (ISBUILTIN(BUILTIN_newarray_double)) {
1773 TYPECHECK_INT(curstack);
1774 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_DOUBLE);
1776 else if (ISBUILTIN(BUILTIN_newarray_byte)) {
1777 TYPECHECK_INT(curstack);
1778 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BYTE);
1780 else if (ISBUILTIN(BUILTIN_newarray_short)) {
1781 TYPECHECK_INT(curstack);
1782 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_SHORT);
1784 else if (ISBUILTIN(BUILTIN_newarray_int)) {
1785 TYPECHECK_INT(curstack);
1786 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_INT);
1788 else if (ISBUILTIN(BUILTIN_newarray_long)) {
1789 TYPECHECK_INT(curstack);
1790 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_LONG);
1793 builtindesc = builtin_desc;
1794 while (builtindesc->opcode && builtindesc->builtin
1795 != (functionptr) iptr->val.a) builtindesc++;
1796 if (!builtindesc->opcode) {
1797 dolog("Builtin not in table: %s",icmd_builtin_name((functionptr) iptr->val.a));
1798 panic("Internal error: builtin not found in table");
1800 TYPECHECK_ARGS1(builtindesc->type_s1);
1802 maythrow = true; /* XXX better safe than sorry */
1805 /****************************************/
1806 /* PRIMITIVE VARIABLE ACCESS */
1808 case ICMD_ILOAD: CHECK_ONEWORD(iptr->op1,TYPE_INT); break;
1809 case ICMD_FLOAD: CHECK_ONEWORD(iptr->op1,TYPE_FLOAT); break;
1810 case ICMD_IINC: CHECK_ONEWORD(iptr->op1,TYPE_INT); break;
1811 case ICMD_LLOAD: CHECK_TWOWORD(iptr->op1,TYPE_LONG); break;
1812 case ICMD_DLOAD: CHECK_TWOWORD(iptr->op1,TYPE_DOUBLE); break;
1814 case ICMD_FSTORE: STORE_ONEWORD(iptr->op1,TYPE_FLOAT); break;
1815 case ICMD_ISTORE: STORE_ONEWORD(iptr->op1,TYPE_INT); break;
1816 case ICMD_LSTORE: STORE_TWOWORD(iptr->op1,TYPE_LONG); break;
1817 case ICMD_DSTORE: STORE_TWOWORD(iptr->op1,TYPE_DOUBLE); break;
1819 /****************************************/
1820 /* INSTRUCTIONS WHICH SHOULD HAVE BEEN */
1821 /* REPLACED BY BUILTIN CALLS */
1825 case ICMD_ANEWARRAY:
1826 case ICMD_MONITORENTER:
1827 case ICMD_MONITOREXIT:
1829 /* XXX only check this in debug mode? */
1830 LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
1831 LOG("Should have been converted to builtin function call.");
1832 panic("Internal error: unexpected instruction encountered");
1835 /****************************************/
1836 /* UNCHECKED OPERATIONS */
1838 /* These ops have no input or output to be checked */
1839 /* (apart from the checks done in analyse_stack). */
1840 /* XXX only add cases for them in debug mode? */
1845 case ICMD_READONLY_ARG: /* XXX ? */
1846 case ICMD_CLEAR_ARGREN: /* XXX ? */
1849 case ICMD_CHECKASIZE:
1850 case ICMD_NULLCHECKPOP:
1854 /****************************************/
1855 /* ARITHMETIC AND CONVERSION */
1856 /* (These instructions are typechecked in analyse_stack.) */
1858 /* The following instructions may throw a runtime exception: */
1868 /* The following instructions never throw a runtime exception: */
1869 /* XXX only add cases for them in debug mode? */
1876 case ICMD_IFEQ_ICONST:
1877 case ICMD_IFNE_ICONST:
1878 case ICMD_IFLT_ICONST:
1879 case ICMD_IFGE_ICONST:
1880 case ICMD_IFGT_ICONST:
1881 case ICMD_IFLE_ICONST:
1882 case ICMD_ELSE_ICONST:
1904 case ICMD_IREM0X10001:
1905 case ICMD_LREM0X10001:
1908 case ICMD_IADDCONST:
1909 case ICMD_ISUBCONST:
1910 case ICMD_IMULCONST:
1911 case ICMD_IANDCONST:
1913 case ICMD_IXORCONST:
1914 case ICMD_ISHLCONST:
1915 case ICMD_ISHRCONST:
1916 case ICMD_IUSHRCONST:
1918 case ICMD_LADDCONST:
1919 case ICMD_LSUBCONST:
1920 case ICMD_LMULCONST:
1921 case ICMD_LANDCONST:
1923 case ICMD_LXORCONST:
1924 case ICMD_LSHLCONST:
1925 case ICMD_LSHRCONST:
1926 case ICMD_LUSHRCONST:
1943 case ICMD_INT2SHORT:
1946 case ICMD_LCMPCONST:
1967 /****************************************/
1970 LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
1971 panic("Missing ICMD code during typecheck");
1974 /* the output of this instruction becomes the current stack */
1977 /* reach exception handlers for this instruction */
1979 LOG("reaching exception handlers");
1981 while (handlers[i]) {
1982 tbptr = handlers[i]->handler;
1983 TYPECHECK_REACH(REACH_THROW); /* XXX jsr chain? */
1989 DOLOG(typeinfo_print_block(get_logfile(),curstack,numlocals,vtype,vinfo,(jsrchain) ? touched : NULL));
1994 } /* while instructions */
1996 LOG("instructions done");
1997 LOGSTR("RESULT=> ");
1998 DOLOG(typeinfo_print_block(get_logfile(),curstack,numlocals,vtype,vinfo,(jsrchain) ? touched : NULL));
2001 /* propagate stack and variables to the following block */
2002 if (!superblockend) {
2003 LOG("reaching following block");
2005 while (tbptr->flags == BBDELETED) {
2007 #ifdef TYPECHECK_DEBUG
2008 if ((tbptr-block) >= block_count)
2009 panic("Control flow falls off the last block");
2012 TYPECHECK_REACH(REACH_STD);
2015 } /* if block has to be checked */
2017 } /* while blocks */
2019 LOGIF(repeat,"repeat=true");
2022 #ifdef TYPECHECK_STATISTICS
2023 dolog("Typechecker did %4d iterations",count_iterations);
2026 #ifdef TYPECHECK_DEBUG
2027 for (i=0; i<block_count; ++i) {
2028 if (block[i].flags != BBDELETED
2029 && block[i].flags != BBUNDEF
2030 && block[i].flags != BBFINISHED
2031 && block[i].flags != BBTYPECHECK_UNDEF) /* typecheck may never reach
2032 * some exception handlers,
2035 LOG2("block L%03d has invalid flags after typecheck: %d",
2036 block[i].debug_nr,block[i].flags);
2037 panic("Invalid block flags after typecheck");
2042 /* Reset blocks we never reached */
2043 for (i=0; i<block_count; ++i) {
2044 if (block[i].flags == BBTYPECHECK_UNDEF)
2045 block[i].flags = BBFINISHED;
2048 LOGimp("exiting typecheck");
2053 #endif /* CACAO_TYPECHECK */
2056 * These are local overrides for various environment variables in Emacs.
2057 * Please do not remove this and leave it at the end of the file, where
2058 * Emacs will automagically detect them.
2059 * ---------------------------------------------------------------------
2062 * indent-tabs-mode: t