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 788 2003-12-15 18:45:28Z 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 /****************************************************************************/
178 /****************************************************************************/
180 #ifdef TYPECHECK_DEBUG
181 /*#define TYPECHECK_STATISTICS*/
184 #ifdef TYPECHECK_STATISTICS
185 #define TYPECHECK_COUNT(cnt) (cnt)++
187 #define TYPECHECK_COUNT(cnt)
190 /****************************************************************************/
191 /* INTERNAL DATA STRUCTURES */
192 /****************************************************************************/
194 typedef struct jsr_record jsr_record;
197 * For each basic block we store the chain of JSR instructions which
198 * were used to reach the block (usually zero or one). For more
199 * details on verifying JSR and RET instructions see the Java VM
202 * CAUTION: The fields starting with sbr_ are only valid for the
203 * jsr_record of the first block of the subroutine.
206 basicblock *target; /* target of the JSR instruction (first block of subroutine) */
207 jsr_record *next; /* for chaining in nested try ... finally */ /* XXX make it sbr_next? */
208 u1 *sbr_touched; /* specifies which variables the subroutine touches */
209 u1 *sbr_vtype; /* Types of local variables after RET */
210 typeinfo *sbr_vinfo; /* Types of local variables after RET */
211 u1 touched[1]; /* touched flags for local variables */
214 /****************************************************************************/
215 /* MACROS USED INTERNALLY IN typecheck() */
216 /****************************************************************************/
218 #define TOUCH_VARIABLE(num) \
219 do {if (jsrchain) touched[num] = TOUCHED_YES;} while (0)
220 #define TOUCH_TWOWORD(num) \
221 do {TOUCH_VARIABLE(num);TOUCH_VARIABLE((num)+1);} while (0)
223 #define INDEX_ONEWORD(num) \
224 do { if((num)<0 || (num)>=validlocals) \
225 panic("Invalid local variable index"); } while (0)
226 #define INDEX_TWOWORD(num) \
227 do { if((num)<0 || ((num)+1)>=validlocals) \
228 panic("Invalid local variable index"); } while (0)
230 #define SET_VARIABLE(num,type) \
231 do {vtype[num] = (type); \
232 if ((num)>0 && IS_2_WORD_TYPE(vtype[(num)-1])) { \
233 vtype[(num)-1] = TYPE_VOID; \
234 TOUCH_VARIABLE((num)-1); \
236 TOUCH_VARIABLE(num);} while(0)
238 #define STORE_ONEWORD(num,type) \
239 do {INDEX_ONEWORD(num); \
240 SET_VARIABLE(num,type);} while(0)
242 #define STORE_TWOWORD(num,type) \
243 do {INDEX_TWOWORD(num); \
244 SET_VARIABLE(num,type); \
245 vtype[(num)+1] = TYPE_VOID; \
246 TOUCH_VARIABLE((num)+1);} while(0)
248 #define CHECK_ONEWORD(num,type) \
249 do {INDEX_ONEWORD(num); \
250 if (vtype[(num)] != (type)) panic("Variable type mismatch"); \
251 TOUCH_VARIABLE(num);} while(0)
253 #define CHECK_TWOWORD(num,type) \
254 do {INDEX_TWOWORD(num); \
255 if (vtype[(num)] != (type)) panic("Variable type mismatch"); \
256 TOUCH_VARIABLE(num); \
257 TOUCH_VARIABLE((num)+1);} while(0)
259 /* XXX maybe it's faster to copy always */
260 #define COPYTYPE(source,dest) \
261 {if ((source)->type == TYPE_ADR) \
262 TYPEINFO_COPY((source)->typeinfo,(dest)->typeinfo);}
264 #define ISBUILTIN(v) (iptr->val.a == (functionptr)(v))
266 #define TYPECHECK_STACK(sp,tp) \
267 do { if ((sp)->type != (tp)) \
268 panic("Wrong data type on stack"); } while(0)
270 #define TYPECHECK_ADR(sp) TYPECHECK_STACK(sp,TYPE_ADR)
271 #define TYPECHECK_INT(sp) TYPECHECK_STACK(sp,TYPE_INT)
272 #define TYPECHECK_LNG(sp) TYPECHECK_STACK(sp,TYPE_LNG)
273 #define TYPECHECK_FLT(sp) TYPECHECK_STACK(sp,TYPE_FLT)
274 #define TYPECHECK_DBL(sp) TYPECHECK_STACK(sp,TYPE_DBL)
276 #define TYPECHECK_ARGS1(t1) \
277 do {TYPECHECK_STACK(curstack,t1);} while (0)
278 #define TYPECHECK_ARGS2(t1,t2) \
279 do {TYPECHECK_ARGS1(t1); \
280 TYPECHECK_STACK(curstack->prev,t2);} while (0)
281 #define TYPECHECK_ARGS3(t1,t2,t3) \
282 do {TYPECHECK_ARGS2(t1,t2); \
283 TYPECHECK_STACK(curstack->prev->prev,t3);} while (0)
285 /* TYPECHECK_COPYVARS: copy the types and typeinfos of the current local
286 * variables to the local variables of the target block.
288 * vtype......current local variable types
289 * vinfo......current local variable typeinfos
290 * ttype......local variable types of target block
291 * tinfo......local variable typeinfos of target block
292 * numlocals..number of local variables
296 #define TYPECHECK_COPYVARS \
298 LOG("TYPECHECK_COPYVARS"); \
299 for (macro_i=0; macro_i<numlocals; ++macro_i) { \
300 if ((ttype[macro_i] = vtype[macro_i]) == TYPE_ADR) \
301 TYPEINFO_CLONE(vinfo[macro_i],tinfo[macro_i]); \
304 /* TYPECHECK_MERGEVARS: merge the local variables of the target block
305 * with the current local variables.
307 * vtype......current local variable types
308 * vinfo......current local variable typeinfos
309 * ttype......local variable types of target block
310 * tinfo......local variable typeinfos of target block
311 * numlocals..number of local variables
313 * changed....set to true if any typeinfo has changed
317 #define TYPECHECK_MERGEVARS \
319 LOG("TYPECHECK_MERGEVARS"); \
320 for (macro_i=0; macro_i<numlocals; ++macro_i) { \
321 if ((ttype[macro_i] != TYPE_VOID) && (vtype[macro_i] != ttype[macro_i])) { \
322 LOG3("var %d: type %d + type %d = void",macro_i,ttype[macro_i],vtype[macro_i]); \
323 ttype[macro_i] = TYPE_VOID; \
325 } else if (ttype[macro_i] == TYPE_ADR) { \
326 if ( ((TYPEINFO_IS_PRIMITIVE(tinfo[macro_i])) ? 1 : 0) \
328 ((TYPEINFO_IS_PRIMITIVE(vinfo[macro_i])) ? 1 : 0)) { \
329 LOG1("var %d: primitive + reference merge",macro_i); \
330 ttype[macro_i] = TYPE_VOID; \
334 LOG1("var %d:",macro_i); \
335 LOGINFO(tinfo+macro_i); \
336 LOGINFO(vinfo+macro_i); \
337 changed |= typeinfo_merge(tinfo+macro_i,vinfo+macro_i); \
338 LOGINFO(tinfo+macro_i); \
339 LOGIF(changed,"vars have changed"); \
344 /* TYPECHECK_MERGEJSR:
348 * tbptr......target block
349 * changed....set to true if any typeinfo has changed
350 * numlocals..number of local variables
351 * touched....current touched flags of local variables
353 * macro_i, jsrtemp, jsrtemp2
355 #define TYPECHECK_MERGEJSR \
357 LOG("TYPECHECK_MERGEJSR"); \
358 jsrtemp = jsrbuffer[tbptr-block]; \
359 jsrtemp2 = jsrchain; \
360 while (jsrtemp || jsrtemp2) { \
361 if (!jsrtemp || !jsrtemp2) \
362 panic("Merging JSR subroutines of different depth"); \
363 if (jsrtemp->target != jsrtemp2->target) \
364 panic("Merging different JSR subroutines"); \
365 jsrtemp = jsrtemp->next; \
366 jsrtemp2 = jsrtemp2->next; \
368 jsrtemp = jsrbuffer[tbptr-block]; \
370 for (macro_i=0; macro_i<numlocals; ++macro_i) { \
371 jsrtemp->touched[i] |= touched[i]; \
374 /* TYPECHECK_COPYSTACK: copy the typeinfos of the current stack to
375 * the input stack of the target block.
377 * srcstack...current stack
378 * dststack...input stack of target block
380 #define TYPECHECK_COPYSTACK \
382 LOG("TYPECHECK_COPYSTACK"); \
384 LOG1("copy %d",srcstack->type); \
385 if (!dststack) panic("Stack depth mismatch"); \
386 if (srcstack->type != dststack->type) \
387 panic("Type mismatch on stack"); \
388 if (srcstack->type == TYPE_ADR) { \
389 TYPEINFO_CLONE(srcstack->typeinfo,dststack->typeinfo); \
391 dststack = dststack->prev; \
392 srcstack = srcstack->prev; \
394 if (dststack) panic("Stack depth mismatch"); \
397 /* TYPECHECK_MERGESTACK: merge the input stack of the target block
398 * with the current stack.
400 * srcstack...current stack
401 * dststack...input stack of target block
403 * changed....set to true if any typeinfo has changed
405 #define TYPECHECK_MERGESTACK \
407 LOG("TYPECHECK_MERGESTACK"); \
409 if (!dststack) panic("Stack depth mismatch"); \
410 if (srcstack->type != dststack->type) \
411 panic("Type mismatch on stack"); \
412 if (srcstack->type == TYPE_ADR) { \
413 LOGINFO(&dststack->typeinfo); \
414 LOGINFO(&srcstack->typeinfo); LOGFLUSH; \
415 changed |= typeinfo_merge(&dststack->typeinfo, \
416 &srcstack->typeinfo); \
417 LOGINFO(&dststack->typeinfo); \
418 LOG((changed)?"CHANGED!\n":"not changed.\n"); \
420 dststack = dststack->prev; \
421 srcstack = srcstack->prev; \
423 if (dststack) panic("Stack depth mismatch"); \
427 /* TYPECHECK_CHECK_JSR_CHAIN: checks if the target block is reached by
428 * the same JSR targets on all control paths.
431 * tbptr......target block
432 * jsrchain...current JSR target chain
433 * jsrbuffer..JSR target chain for each basic block
435 * panic if the JSR target chains don't match
439 #define TYPECHECK_CHECK_JSR_CHAIN \
441 jsrtemp = jsrbuffer[tbptr-block]; \
442 if (!jsrtemp) panic("non-subroutine called by JSR"); \
443 if (jsrtemp->target != tbptr) \
444 panic("Merging different JSR subroutines"); \
445 jsrtemp = jsrtemp->next; \
446 jsrtemp2 = jsrchain; \
447 while (jsrtemp || jsrtemp2) { \
448 if (!jsrtemp || !jsrtemp2) \
449 panic("Merging JSR subroutines of different depth"); \
450 if (jsrtemp->target != jsrtemp2->target) \
451 panic("Merging different JSR subroutines"); \
452 jsrtemp = jsrtemp->next; \
453 jsrtemp2 = jsrtemp2->next; \
456 /* TYPECHECK_ADD_JSR: add a JSR target to the current JSR target chain
457 * and store the resulting chain in the target block.
460 * jsrchain...current JSR target chain
461 * tbptr.....the basic block targeted by the JSR
462 * numlocals..number of local variables
463 * jsrbuffer..JSR target chain for each basic block
467 #define TYPECHECK_ADD_JSR \
469 LOG1("adding JSR to block %04d",(tbptr)-block); \
470 jsrtemp = (jsr_record *) dump_alloc(sizeof(jsr_record)+(numlocals-1)*sizeof(u1)); \
471 jsrtemp->target = (tbptr); \
472 jsrtemp->next = jsrchain; \
473 jsrtemp->sbr_touched = NULL; \
474 memset(&jsrtemp->touched,TOUCHED_NO,sizeof(u1)*numlocals); \
475 jsrbuffer[tbptr-block] = jsrtemp; \
478 /* TYPECHECK_COPYJSR: copy the current JSR chain to the target block.
481 * chain......current JSR target chain
482 * tbptr.....the basic block targeted by the JSR
483 * numlocals..number of local variables
484 * jsrbuffer..JSR target chain for each basic block
485 * touched....current touched flags of local variables
489 #define TYPECHECK_COPYJSR(chain) \
491 LOG("TYPECHECK_COPYJSR"); \
493 jsrtemp = (jsr_record *) dump_alloc(sizeof(jsr_record)+(numlocals-1)*sizeof(u1)); \
494 jsrtemp->target = (chain)->target; \
495 jsrtemp->next = (chain)->next; \
496 jsrtemp->sbr_touched = NULL; \
497 memcpy(&jsrtemp->touched,touched,sizeof(u1)*numlocals); \
498 jsrbuffer[tbptr-block] = jsrtemp; \
501 jsrbuffer[tbptr-block] = NULL; \
504 /* TYPECHECK_BRANCH_BACKWARDS: executed when control flow moves
505 * backwards. Checks if there are uninitialized objects on the
506 * stack or in local variables.
508 * dst........current output stack pointer (not needed for REACH_THROW)
509 * vtype......current local variable types
510 * vinfo......current local variable typeinfos
514 #define TYPECHECK_BRANCH_BACKWARDS \
519 if (srcstack->type == TYPE_ADR && \
520 TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo)) \
521 panic("Branching backwards with uninitialized object on stack"); \
522 srcstack = srcstack->prev; \
524 for (macro_i=0; macro_i<numlocals; ++macro_i) \
525 if (vtype[macro_i] == TYPE_ADR && \
526 TYPEINFO_IS_NEWOBJECT(vinfo[macro_i])) \
527 panic("Branching backwards with uninitialized object in local variable"); \
530 /* TYPECHECK_REACH: executed, when the target block (tbptr) can be reached
531 * from the current block (bptr). The types of local variables and
532 * stack slots are propagated to the target block.
534 * bptr.......current block
535 * tbptr......target block
536 * dst........current output stack pointer (not needed for REACH_THROW)
537 * numlocals..number of local variables
538 * vtype......current local variable types
539 * vinfo......current local variable typeinfos
540 * jsrchain...current JSR target chain
541 * jsrbuffer..JSR target chain for each basic block
542 * way........in which way the block is reached (REACH_ constant)
543 * touched....current touched flags of local variables
545 * repeat.....changed to true if a block before the current
548 * ttype, tinfo, srcstack, dststack, changed, macro_i
550 #define TYPECHECK_REACH(way) \
552 LOG2("reaching block %04d (%d)",tbptr-block,way); \
553 if (tbptr <= bptr && way != REACH_THROW) \
554 TYPECHECK_BRANCH_BACKWARDS; \
556 dststack = tbptr->instack; \
557 ttype = vartype + numlocals*(tbptr-block); \
558 tinfo = vartypeinfo + numlocals*(tbptr-block); \
559 if (tbptr->flags == BBTYPECHECK_UNDEF) { \
560 /* This block is reached for the first time */ \
561 if (way == REACH_JSR) { \
563 TYPECHECK_COPYVARS; \
566 if (way != REACH_THROW) TYPECHECK_COPYJSR(jsrchain); \
567 TYPECHECK_COPYVARS; \
569 if (way != REACH_THROW) TYPECHECK_COPYSTACK; \
572 /* This block has been reached before */ \
574 if (way == REACH_JSR) \
575 TYPECHECK_CHECK_JSR_CHAIN; \
576 else if (way != REACH_THROW) \
577 TYPECHECK_MERGEJSR; \
578 TYPECHECK_MERGEVARS; \
579 if (way != REACH_THROW) TYPECHECK_MERGESTACK; \
583 tbptr->flags = BBTYPECHECK_REACHED; \
584 if (tbptr <= bptr) {repeat = true; LOG("REPEAT!");} \
589 /* TYPECHECK_LEAVE: executed when the method is exited non-abruptly
591 * class........class of the current method
592 * numlocals....number of local variables
593 * vtype........current local variable types
594 * vinfo........current local variable typeinfos
595 * initmethod...true if this is an <init> method
597 #define TYPECHECK_LEAVE \
599 if (initmethod && class != class_java_lang_Object) { \
600 /* check the marker variable */ \
601 LOG("Checking <init> marker"); \
602 if (vtype[numlocals-1] == TYPE_VOID) \
603 panic("<init> method does not initialize 'this'"); \
607 /****************************************************************************/
609 /****************************************************************************/
611 #define MAXPARAMS 255
613 /* typecheck is called directly after analyse_stack */
617 int b_count, b_index;
618 stackptr curstack; /* input stack top for current instruction */
619 stackptr srcstack; /* source stack for copying and merging */
620 stackptr dststack; /* target stack for copying and merging */
621 int opcode; /* current opcode */
622 int macro_i, i; /* temporary counters */
623 int len; /* for counting instructions, etc. */
624 bool superblockend; /* true if no fallthrough to next block */
625 bool repeat; /* if true, blocks are iterated over again */
626 bool changed; /* used in macros */
627 instruction *iptr; /* pointer to current instruction */
628 basicblock *bptr; /* pointer to current basic block */
629 basicblock *tbptr; /* temporary for target block */
630 int numlocals; /* number of local variables */
631 int validlocals; /* number of valid local variable indices */
632 u1 *vartype; /* type of each local for each basic block */
633 typeinfo *vartypeinfo; /* type of each local for each basic block */
634 u1 *vtype; /* type of each local for current instruction */
635 typeinfo *vinfo; /* type of each local for current instruction */
636 u1 *ttype; /* temporary pointer */
637 typeinfo *tinfo; /* temporary pointer */
638 typeinfo tempinfo; /* temporary */
639 int returntype; /* return type of current method */
640 typeinfo returntypeinfo; /* typeinfo for return type */
641 u1 *ptype; /* parameter types of called method */
642 typeinfo *pinfo; /* parameter typeinfos of called method */
643 int rtype; /* return type of called method */
644 typeinfo rinfo; /* typeinfo for return type of called method */
645 stackptr dst; /* output stack of current instruction */
646 basicblock **tptr; /* pointer into target list of switch instructions */
647 jsr_record **jsrbuffer; /* JSR target chain for each basic block */
648 jsr_record *jsrchain; /* JSR chain for current block */
649 jsr_record *jsrtemp,*jsrtemp2; /* temporary variables */
650 jsr_record *subroutine; /* jsr_record of the current subroutine */
651 u1 *touched; /* touched flags for local variables */
652 xtable **handlers; /* active exception handlers */
653 classinfo *cls; /* temporary */
654 bool maythrow; /* true if this instruction may throw */
655 utf *name_init; /* "<init>" */
656 bool initmethod; /* true if this is an "<init>" method */
657 builtin_descriptor *builtindesc;
659 #ifdef TYPECHECK_STATISTICS
660 int count_iterations = 0;
663 LOGSTR("\n==============================================================================\n");
664 DOLOG(show_icmd_method());
665 LOGSTR("\n==============================================================================\n");
666 LOGimpSTR("Entering typecheck: ");
667 LOGimpSTRu(method->name);
669 LOGimpSTRu(method->descriptor);
670 LOGimpSTR(" (class ");
671 LOGimpSTRu(method->class->name);
674 name_init = utf_new_char("<init>");
675 initmethod = (method->name == name_init);
677 ptype = DMNEW(u1,MAXPARAMS);
678 pinfo = DMNEW(typeinfo,MAXPARAMS);
680 LOG("Buffer allocated.\n");
682 /* reset all BBFINISHED blocks to BBTYPECHECK_UNDEF. */
683 b_count = block_count;
685 while (--b_count >= 0) {
686 #ifdef TYPECHECK_DEBUG
687 if (bptr->flags != BBFINISHED && bptr->flags != BBDELETED
688 && bptr->flags != BBUNDEF)
691 LOGSTR1("block flags: %d\n",bptr->flags); LOGFLUSH;
692 panic("Internal error: Unexpected block flags in typecheck()");
695 if (bptr->flags >= BBFINISHED) {
696 bptr->flags = BBTYPECHECK_UNDEF;
701 /* The first block is always reached */
702 if (block_count && block[0].flags == BBTYPECHECK_UNDEF)
703 block[0].flags = BBTYPECHECK_REACHED;
705 LOG("Blocks reset.\n");
707 /* number of local variables */
709 /* In <init> methods we use an extra local variable to signal if
710 * the 'this' reference has been initialized. */
711 numlocals = maxlocals;
712 validlocals = numlocals;
713 if (initmethod) numlocals++;
715 /* allocate the buffers for local variables */
716 vartype = DMNEW(u1,numlocals * (block_count+1));
717 vartypeinfo = DMNEW(typeinfo,numlocals * (block_count+1));
718 touched = DMNEW(u1,numlocals);
719 vtype = vartype + numlocals * block_count;
720 vinfo = vartypeinfo + numlocals * block_count;
721 memset(vartype,TYPE_VOID,numlocals * (block_count+1) * sizeof(u1));
722 memset(vartypeinfo,0,numlocals * (block_count+1) * sizeof(typeinfo));
724 LOG("Variable buffer initialized.\n");
726 /* allocate the buffer for storing JSR target chains */
727 jsrbuffer = DMNEW(jsr_record*,block_count);
728 memset(jsrbuffer,0,block_count * sizeof(jsr_record*));
731 LOG("jsrbuffer initialized.\n");
733 /* allocate the buffer of active exception handlers */
734 handlers = DMNEW(xtable*,method->exceptiontablelength + 1);
736 /* initialize the variable types of the first block */
737 /* to the types of the arguments */
741 /* if this is an instance method initialize the "this" ref type */
742 if (!(method->flags & ACC_STATIC)) {
743 *ttype++ = TYPE_ADDRESS;
745 TYPEINFO_INIT_NEWOBJECT(*tinfo,NULL);
747 TYPEINFO_INIT_CLASSINFO(*tinfo,class);
751 LOG("'this' argument set.\n");
753 /* the rest of the arguments and the return type */
754 typeinfo_init_from_method_args(method->descriptor,ttype,tinfo,
755 numlocals - (tinfo-vartypeinfo),
756 true, /* two word types use two slots */
757 &returntype,&returntypeinfo);
759 LOG("Arguments set.\n");
761 /* initialize the input stack of exception handlers */
762 for (i=0; i<method->exceptiontablelength; ++i) {
763 cls = extable[i].catchtype;
764 if (!cls) cls = class_java_lang_Throwable;
765 LOGSTR1("handler %i: ",i); LOGSTRu(cls->name); LOGNL;
766 TYPEINFO_INIT_CLASSINFO(extable[i].handler->instack->typeinfo,cls);
769 LOG("Exception handler stacks set.\n");
771 /* loop while there are still blocks to be checked */
773 TYPECHECK_COUNT(count_iterations);
777 b_count = block_count;
780 while (--b_count >= 0) {
781 LOGSTR1("---- BLOCK %04d, ",bptr-block);
782 LOGSTR1("blockflags: %d\n",bptr->flags);
785 if (bptr->flags == BBTYPECHECK_REACHED) {
786 LOGSTR1("\n---- BLOCK %04d ------------------------------------------------\n",bptr-block);
789 superblockend = false;
790 bptr->flags = BBFINISHED;
791 b_index = bptr - block;
793 /* init stack at the start of this block */
794 curstack = bptr->instack;
796 /* determine the active exception handlers for this block */
797 /* XXX could use a faster algorithm with sorted lists or
800 for (i=0; i<method->exceptiontablelength; ++i) {
801 if ((extable[i].start <= bptr) && (extable[i].end > bptr)) {
802 LOG1("active handler L%03d",extable[i].handler->debug_nr);
803 handlers[len++] = extable + i;
806 handlers[len] = NULL;
808 /* init variable types at the start of this block */
809 for (i=0; i<numlocals; ++i) {
810 vtype[i] = vartype[numlocals*b_index + i];
811 TYPEINFO_COPY(vartypeinfo[numlocals*b_index + i],vinfo[i]);
814 vtype[i] == TYPE_ADR && TYPEINFO_IS_NEWOBJECT(vinfo[i]))
815 panic("Uninitialized object in local variable inside try block");
818 /* init JSR target chain */
819 if ((jsrchain = jsrbuffer[b_index]) != NULL) {
820 #ifdef TYPECHECK_VERBOSE
821 if (typecheckverbose) {
822 LOGSTR("jsr chain:");
825 LOGSTR1(" L%03d",jsrtemp->target->debug_nr);
826 jsrtemp = jsrtemp->next;
833 subroutine = jsrbuffer[jsrchain->target - block];
834 memcpy(touched,jsrchain->touched,sizeof(u1)*numlocals);
838 #ifdef TYPECHECK_VERBOSE
839 if (typecheckverbose) {
840 if (subroutine) {LOGSTR1("subroutine L%03d\n",subroutine->target->debug_nr);LOGFLUSH;}
841 typeinfo_print_block(get_logfile(),curstack,numlocals,vtype,vinfo,(jsrchain) ? touched : NULL);
846 /* loop over the instructions */
850 DOLOG(show_icmd(iptr,false));
860 /****************************************/
861 /* STACK MANIPULATIONS */
863 /* We just need to copy the typeinfo */
864 /* for slots containing addresses. */
866 /* XXX We assume that the destination stack
867 * slots were continuously allocated in
868 * memory. (The current implementation in
873 COPYTYPE(curstack,dst);
877 COPYTYPE(curstack,dst);
878 COPYTYPE(curstack,dst-2);
879 COPYTYPE(curstack->prev,dst-1);
883 COPYTYPE(curstack,dst);
884 COPYTYPE(curstack,dst-3);
885 COPYTYPE(curstack->prev,dst-1);
886 COPYTYPE(curstack->prev->prev,dst-2);
890 COPYTYPE(curstack,dst);
891 COPYTYPE(curstack->prev,dst-1);
895 COPYTYPE(curstack,dst);
896 COPYTYPE(curstack->prev,dst-1);
897 COPYTYPE(curstack,dst-3);
898 COPYTYPE(curstack->prev,dst-4);
899 COPYTYPE(curstack->prev->prev,dst-2);
903 COPYTYPE(curstack,dst);
904 COPYTYPE(curstack->prev,dst-1);
905 COPYTYPE(curstack,dst-4);
906 COPYTYPE(curstack->prev,dst-5);
907 COPYTYPE(curstack->prev->prev,dst-2);
908 COPYTYPE(curstack->prev->prev->prev,dst-3);
912 COPYTYPE(curstack,dst-1);
913 COPYTYPE(curstack->prev,dst);
916 /****************************************/
917 /* LOADING ADDRESS FROM VARIABLE */
920 CHECK_ONEWORD(iptr->op1,TYPE_ADR);
922 /* loading a returnAddress is not allowed */
923 if (TYPEINFO_IS_PRIMITIVE(vinfo[iptr->op1]))
924 panic("illegal instruction: ALOAD loading returnAddress");
926 TYPEINFO_COPY(vinfo[iptr->op1],dst->typeinfo);
929 /****************************************/
930 /* STORING ADDRESS TO VARIABLE */
934 TYPEINFO_IS_NEWOBJECT(curstack->typeinfo))
935 panic("Storing uninitialized object in local variable inside try block");
937 STORE_ONEWORD(iptr->op1,TYPE_ADDRESS);
938 TYPEINFO_COPY(curstack->typeinfo,vinfo[iptr->op1]);
941 /****************************************/
942 /* LOADING ADDRESS FROM ARRAY */
945 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(curstack->prev->typeinfo))
946 panic("illegal instruction: AALOAD on non-reference array");
948 typeinfo_init_component(&curstack->prev->typeinfo,&dst->typeinfo);
952 /****************************************/
956 if (!TYPEINFO_IS_REFERENCE(curstack->prev->typeinfo))
957 panic("illegal instruction: PUTFIELD on non-reference");
958 if (TYPEINFO_IS_ARRAY(curstack->prev->typeinfo)) /* XXX arraystub */
959 panic("illegal instruction: PUTFIELD on array");
961 /* check if the value is assignable to the field */
963 fieldinfo *fi = (fieldinfo*) iptr[0].val.a;
965 if (!TYPEINFO_IS_NULLTYPE(curstack->prev->typeinfo)) {
967 /* XXX treat uinitialized objects specially? */
968 if (!class_issubclass(curstack->prev->typeinfo.typeclass,
970 panic("PUTFIELD reference type does not support field");
973 /* XXX check flags */
975 /* XXX ---> unify with ICMD_PUTSTATIC? */
977 /* XXX check access rights */
979 if (curstack->type != fi->type)
980 panic("PUTFIELD type mismatch");
981 if (fi->type == TYPE_ADR) {
982 TYPEINFO_INIT_FROM_FIELDINFO(rinfo,fi);
983 if (!typeinfo_is_assignable(&(curstack->typeinfo),
985 panic("PUTFIELD reference type not assignable");
992 /* check if the value is assignable to the field */
994 fieldinfo *fi = (fieldinfo*) iptr[0].val.a;
997 /* XXX check access rights */
999 if (curstack->type != fi->type)
1000 panic("PUTSTATIC type mismatch");
1001 if (fi->type == TYPE_ADR) {
1002 TYPEINFO_INIT_FROM_FIELDINFO(rinfo,fi);
1003 if (!typeinfo_is_assignable(&(curstack->typeinfo),
1005 panic("PUTSTATIC reference type not assignable");
1012 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1013 panic("illegal instruction: GETFIELD on non-reference");
1014 if (TYPEINFO_IS_ARRAY(curstack->typeinfo))
1015 panic("illegal instruction: GETFIELD on array");
1018 fieldinfo *fi = (fieldinfo *)(iptr->val.a);
1020 if (!TYPEINFO_IS_NULLTYPE(curstack->typeinfo)) {
1022 if (!class_issubclass(curstack->typeinfo.typeclass,
1024 panic("GETFIELD reference type does not support field");
1027 /* XXX check flags */
1028 /* XXX check access rights */
1029 if (dst->type == TYPE_ADR) {
1030 TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi);
1033 /* XXX check field type? */
1034 TYPEINFO_INIT_PRIMITIVE(dst->typeinfo);
1040 case ICMD_GETSTATIC:
1042 fieldinfo *fi = (fieldinfo *)(iptr->val.a);
1043 /* XXX check flags */
1044 /* XXX check access rights */
1045 if (dst->type == TYPE_ADR) {
1046 TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi);
1049 /* XXX check field type? */
1050 TYPEINFO_INIT_PRIMITIVE(dst->typeinfo);
1056 /****************************************/
1057 /* PRIMITIVE ARRAY ACCESS */
1059 case ICMD_ARRAYLENGTH:
1060 /* XXX should this also work on arraystubs? */
1061 if (!TYPEINFO_MAYBE_ARRAY(curstack->typeinfo))
1062 panic("illegal instruction: ARRAYLENGTH on non-array");
1067 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_BOOLEAN)
1068 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_BYTE))
1069 panic("Array type mismatch");
1073 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_CHAR))
1074 panic("Array type mismatch");
1078 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_DOUBLE))
1079 panic("Array type mismatch");
1083 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_FLOAT))
1084 panic("Array type mismatch");
1088 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_INT))
1089 panic("Array type mismatch");
1093 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_SHORT))
1094 panic("Array type mismatch");
1098 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_LONG))
1099 panic("Array type mismatch");
1104 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_BOOLEAN)
1105 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_BYTE))
1106 panic("Array type mismatch");
1110 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_CHAR))
1111 panic("Array type mismatch");
1115 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_DOUBLE))
1116 panic("Array type mismatch");
1120 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_FLOAT))
1121 panic("Array type mismatch");
1125 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_INT))
1126 panic("Array type mismatch");
1130 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_SHORT))
1131 panic("Array type mismatch");
1135 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_LONG))
1136 panic("Array type mismatch");
1140 /****************************************/
1141 /* OPERATIONS WITH UNCHECKED INPUT */
1143 case ICMD_CHECKCAST:
1144 TYPECHECK_ADR(curstack);
1145 /* returnAddress is not allowed */
1146 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1147 panic("Illegal instruction: CHECKCAST on non-reference");
1149 /* XXX check if the cast can be done statically */
1150 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,(classinfo *)iptr[0].val.a);
1155 case ICMD_INSTANCEOF:
1156 TYPECHECK_ADR(curstack);
1157 /* returnAddress is not allowed */
1158 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1159 panic("Illegal instruction: INSTANCEOF on non-reference");
1161 /* XXX optimize statically? */
1165 if (iptr->val.a == NULL)
1166 TYPEINFO_INIT_NULLTYPE(dst->typeinfo);
1168 /* XXX constants for builtin functions */
1169 /* string constants */
1170 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,class_java_lang_String);
1173 /****************************************/
1174 /* BRANCH INSTRUCTIONS */
1177 superblockend = true;
1180 case ICMD_IFNONNULL:
1187 case ICMD_IF_ICMPEQ:
1188 case ICMD_IF_ICMPNE:
1189 case ICMD_IF_ICMPLT:
1190 case ICMD_IF_ICMPGE:
1191 case ICMD_IF_ICMPGT:
1192 case ICMD_IF_ICMPLE:
1193 case ICMD_IF_ACMPEQ:
1194 case ICMD_IF_ACMPNE:
1201 case ICMD_IF_LCMPEQ:
1202 case ICMD_IF_LCMPNE:
1203 case ICMD_IF_LCMPLT:
1204 case ICMD_IF_LCMPGE:
1205 case ICMD_IF_LCMPGT:
1206 case ICMD_IF_LCMPLE:
1207 tbptr = (basicblock *) iptr->target;
1209 /* propagate stack and variables to the target block */
1210 TYPECHECK_REACH(REACH_STD);
1214 /****************************************/
1217 case ICMD_TABLESWITCH:
1219 s4 *s4ptr = iptr->val.a;
1220 s4ptr++; /* skip default */
1221 i = *s4ptr++; /* low */
1222 i = *s4ptr++ - i + 2; /* +1 for default target */
1224 goto switch_instruction_tail;
1226 case ICMD_LOOKUPSWITCH:
1228 s4 *s4ptr = iptr->val.a;
1229 s4ptr++; /* skip default */
1230 i = *s4ptr++ + 1; /* count +1 for default target */
1232 switch_instruction_tail:
1233 tptr = (basicblock **)iptr->target;
1237 LOG2("target %d is block %04d",(tptr-(basicblock **)iptr->target)-1,tbptr-block);
1238 TYPECHECK_REACH(REACH_STD);
1241 superblockend = true;
1244 /****************************************/
1245 /* RETURNS AND THROW */
1248 TYPEINFO_INIT_CLASSINFO(tempinfo,class_java_lang_Throwable);
1249 if (!typeinfo_is_assignable(&curstack->typeinfo,&tempinfo))
1250 panic("illegal instruction: ATHROW on non-Throwable");
1251 superblockend = true;
1256 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1257 panic("illegal instruction: ARETURN on non-reference");
1259 if (returntype != TYPE_ADDRESS
1260 || !typeinfo_is_assignable(&curstack->typeinfo,&returntypeinfo))
1261 panic("Return type mismatch");
1265 if (returntype != TYPE_INT) panic("Return type mismatch");
1269 if (returntype != TYPE_LONG) panic("Return type mismatch");
1273 if (returntype != TYPE_FLOAT) panic("Return type mismatch");
1277 if (returntype != TYPE_DOUBLE) panic("Return type mismatch");
1281 if (returntype != TYPE_VOID) panic("Return type mismatch");
1284 superblockend = true;
1288 /****************************************/
1289 /* SUBROUTINE INSTRUCTIONS */
1294 /* XXX This is a dirty hack. It is needed
1295 * because of the special handling of ICMD_JSR in stack.c
1297 dst = (stackptr) iptr->val.a;
1299 /* push return address */
1300 TYPEINFO_INIT_PRIMITIVE(dst->typeinfo);
1302 LOG("reaching block...");
1304 /* add the target to the JSR target chain and */
1305 /* propagate stack and variables to the target block */
1306 tbptr = (basicblock *) iptr->target;
1307 TYPECHECK_REACH(REACH_JSR);
1309 /* set dst to the stack after the subroutine execution */
1310 /* XXX We assume (as in stack.c) that the
1311 * subroutine returns the stack as it was
1312 * before the JSR instruction. Is this
1317 /* Find the jsr_record of the called subroutine */
1318 jsrtemp = jsrbuffer[tbptr - block];
1320 /* Check if we already calculated (at least
1321 * for one RET) which variables the
1322 * subroutine touches.
1324 if (jsrtemp->sbr_touched) {
1325 /* Calculate the local variables after the subroutine call */
1326 for (i=0; i<numlocals; ++i)
1327 if (jsrtemp->sbr_touched[i] != TOUCHED_NO) {
1329 if ((vtype[i] = jsrtemp->sbr_vtype[i]) == TYPE_ADR)
1330 TYPEINFO_CLONE(jsrtemp->sbr_vinfo[i],vinfo[i]);
1333 /* continue after the JSR call */
1334 superblockend = false;
1337 /* We cannot proceed until the subroutine has been typechecked. */
1338 /* XXX actually we would not have to check this block again */
1339 bptr->flags = BBTYPECHECK_REACHED;
1341 superblockend = true;
1343 /* XXX may throw? I don't think. */
1347 /* check returnAddress variable */
1348 CHECK_ONEWORD(iptr->op1,TYPE_ADR);
1350 if (!TYPEINFO_IS_PRIMITIVE(vinfo[iptr->op1]))
1351 panic("illegal instruction: RET using non-returnAddress variable");
1353 /* check if we are inside a subroutine */
1355 panic("RET outside of subroutine");
1357 /* determine which variables are touched by this subroutine */
1358 /* and their types */
1359 if (subroutine->sbr_touched) {
1360 for (i=0; i<numlocals; ++i)
1361 subroutine->sbr_touched[i] |= touched[i];
1362 ttype = subroutine->sbr_vtype;
1363 tinfo = subroutine->sbr_vinfo;
1364 TYPECHECK_MERGEVARS;
1367 subroutine->sbr_touched = DMNEW(u1,numlocals);
1368 memcpy(subroutine->sbr_touched,touched,sizeof(u1)*numlocals);
1369 subroutine->sbr_vtype = DMNEW(u1,numlocals);
1370 memcpy(subroutine->sbr_vtype,vtype,sizeof(u1)*numlocals);
1371 subroutine->sbr_vinfo = DMNEW(typeinfo,numlocals);
1372 for (i=0; i<numlocals; ++i)
1373 if (vtype[i] == TYPE_ADR)
1374 TYPEINFO_CLONE(vinfo[i],subroutine->sbr_vinfo[i]);
1376 /* XXX check if subroutine changed types? */
1378 LOGSTR("subroutine touches:");
1379 DOLOG(typeinfo_print_locals(get_logfile(),subroutine->sbr_vtype,subroutine->sbr_vinfo,
1380 subroutine->sbr_touched,numlocals));
1383 /* reach blocks after JSR statements */
1384 for (i=0; i<block_count; ++i) {
1386 LOG1("block L%03d",tbptr->debug_nr);
1387 if (tbptr->iinstr[tbptr->icount - 1].opc != ICMD_JSR)
1389 LOG("ends with JSR");
1390 if ((basicblock*) tbptr->iinstr[tbptr->icount - 1].target != subroutine->target)
1394 LOG1("RET reaches block %04d",tbptr-block);
1396 /*TYPECHECK_REACH(REACH_RET);*/
1399 superblockend = true;
1402 /****************************************/
1405 case ICMD_INVOKEVIRTUAL:
1406 case ICMD_INVOKESPECIAL:
1407 case ICMD_INVOKESTATIC:
1408 case ICMD_INVOKEINTERFACE:
1410 /* XXX check if this opcode may invoke this method */
1411 /* XXX check access rights */
1413 methodinfo *mi = (methodinfo*) iptr->val.a;
1414 bool callinginit = (opcode == ICMD_INVOKESPECIAL && mi->name == name_init);
1416 classinfo *initclass;
1418 /* XXX for INVOKESPECIAL: check if the invokation is done at all */
1420 /* fetch parameter types and return type */
1421 /* XXX might use dst->typeinfo directly if non void */
1423 if (opcode != ICMD_INVOKESTATIC) {
1424 ptype[0] = TYPE_ADR;
1425 TYPEINFO_INIT_CLASSINFO(pinfo[0],mi->class);
1428 typeinfo_init_from_method_args(mi->descriptor,ptype+i,pinfo+i,
1432 /* check parameter types */
1433 srcstack = curstack;
1434 i = mi->paramcount; /* number of parameters including 'this'*/
1437 if (srcstack->type != ptype[i])
1438 panic("Parameter type mismatch in method invocation");
1439 if (srcstack->type == TYPE_ADR) {
1440 LOGINFO(&(srcstack->typeinfo));
1442 if (i==0 && callinginit)
1444 /* first argument to <init> method */
1445 if (!TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo))
1446 panic("Calling <init> on initialized object");
1448 /* get the address of the NEW instruction */
1449 LOGINFO(&(srcstack->typeinfo));
1450 ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(srcstack->typeinfo);
1451 initclass = (ins) ? (classinfo*)ins[-1].val.a : method->class;
1452 LOGSTR("class: "); LOGSTRu(initclass->name); LOGNL;
1454 /* XXX check type */
1457 if (!typeinfo_is_assignable(&(srcstack->typeinfo),pinfo+i))
1458 panic("Parameter reference type mismatch in method invocation");
1463 srcstack = srcstack->prev;
1466 LOG("checking return type");
1467 if (rtype != TYPE_VOID) {
1468 if (rtype != dst->type)
1469 panic("Return type mismatch in method invocation");
1470 TYPEINFO_COPY(rinfo,dst->typeinfo);
1474 LOG("replacing uninitialized object");
1475 /* replace uninitialized object type on stack */
1478 if (srcstack->type == TYPE_ADR
1479 && TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo)
1480 && TYPEINFO_NEWOBJECT_INSTRUCTION(srcstack->typeinfo) == ins)
1482 LOG("replacing uninitialized type on stack");
1483 TYPEINFO_INIT_CLASSINFO(srcstack->typeinfo,initclass);
1485 srcstack = srcstack->prev;
1487 /* replace uninitialized object type in locals */
1488 for (i=0; i<numlocals; ++i) {
1489 if (vtype[i] == TYPE_ADR
1490 && TYPEINFO_IS_NEWOBJECT(vinfo[i])
1491 && TYPEINFO_NEWOBJECT_INSTRUCTION(vinfo[i]) == ins)
1493 LOG1("replacing uninitialized type in local %d",i);
1494 TYPEINFO_INIT_CLASSINFO(vinfo[i],initclass);
1498 /* initializing the 'this' reference? */
1499 if (initmethod && !ins) {
1500 /* set our marker variable to type int */
1501 LOG("setting <init> marker");
1502 vtype[numlocals-1] = TYPE_INT;
1509 case ICMD_MULTIANEWARRAY:
1512 arraydescriptor *desc;
1514 /* check the array lengths on the stack */
1516 if (i<1) panic("MULTIANEWARRAY with dimensions < 1");
1517 srcstack = curstack;
1520 panic("MULTIANEWARRAY missing array length");
1521 if (srcstack->type != TYPE_INT)
1522 panic("MULTIANEWARRAY using non-int as array length");
1523 srcstack = srcstack->prev;
1526 /* check array descriptor */
1527 arrayvftbl = (vftbl*) iptr[0].val.a;
1529 panic("MULTIANEWARRAY with unlinked class");
1530 if ((desc = arrayvftbl->arraydesc) == NULL)
1531 panic("MULTIANEWARRAY with non-array class");
1532 if (desc->dimension < iptr[0].op1)
1533 panic("MULTIANEWARRAY dimension to high");
1535 /* set the array type of the result */
1536 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,arrayvftbl->class);
1542 if (ISBUILTIN(BUILTIN_aastore)) {
1543 TYPECHECK_ADR(curstack);
1544 TYPECHECK_INT(curstack->prev);
1545 TYPECHECK_ADR(curstack->prev->prev);
1546 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(curstack->prev->prev->typeinfo))
1547 panic("illegal instruction: AASTORE to non-reference array");
1551 typeinfo_init_component(&curstack->prev->prev->typeinfo,&tempinfo);
1552 if (!typeinfo_is_assignable(&curstack->typeinfo,&tempinfo))
1553 panic("illegal instruction: AASTORE to incompatible type");
1557 builtindesc = builtin_desc;
1558 while (builtindesc->opcode && builtindesc->builtin
1559 != (functionptr) iptr->val.a) builtindesc++;
1560 if (!builtindesc->opcode) {
1561 dolog("Builtin not in table: %s",icmd_builtin_name((functionptr) iptr->val.a));
1562 panic("Internal error: builtin not found in table");
1564 TYPECHECK_ARGS3(builtindesc->type_s3,builtindesc->type_s2,builtindesc->type_s1);
1566 maythrow = true; /* XXX better safe than sorry */
1570 /* XXX use BUILTIN_ macros */
1571 if (ISBUILTIN(BUILTIN_newarray))
1574 TYPECHECK_INT(curstack->prev);
1575 if (iptr[-1].opc != ICMD_ACONST)
1576 panic("illegal instruction: builtin_newarray without classinfo");
1577 vft = (vftbl *)iptr[-1].val.a;
1579 panic("ANEWARRAY with unlinked class");
1580 if (!vft->arraydesc)
1581 panic("ANEWARRAY with non-array class");
1582 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,vft->class);
1584 else if (ISBUILTIN(BUILTIN_arrayinstanceof))
1587 TYPECHECK_ADR(curstack->prev);
1588 if (iptr[-1].opc != ICMD_ACONST)
1589 panic("illegal instruction: builtin_arrayinstanceof without classinfo");
1590 vft = (vftbl *)iptr[-1].val.a;
1592 panic("INSTANCEOF with unlinked class");
1593 if (!vft->arraydesc)
1594 panic("internal error: builtin_arrayinstanceof with non-array class");
1596 else if (ISBUILTIN(BUILTIN_checkarraycast)) {
1598 TYPECHECK_ADR(curstack->prev);
1599 if (iptr[-1].opc != ICMD_ACONST)
1600 panic("illegal instruction: BUILTIN_checkarraycast without classinfo");
1601 vft = (vftbl *)iptr[-1].val.a;
1603 panic("CHECKCAST with unlinked class");
1604 if (!vft->arraydesc)
1605 panic("internal error: builtin_checkarraycast with non-array class");
1606 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,vft->class);
1609 builtindesc = builtin_desc;
1610 while (builtindesc->opcode && builtindesc->builtin
1611 != (functionptr) iptr->val.a) builtindesc++;
1612 if (!builtindesc->opcode) {
1613 dolog("Builtin not in table: %s",icmd_builtin_name((functionptr) iptr->val.a));
1614 panic("Internal error: builtin not found in table");
1616 TYPECHECK_ARGS2(builtindesc->type_s2,builtindesc->type_s1);
1618 maythrow = true; /* XXX better safe than sorry */
1622 if (ISBUILTIN(BUILTIN_new)) {
1623 if (iptr[-1].opc != ICMD_ACONST)
1624 panic("illegal instruction: builtin_new without classinfo");
1625 TYPEINFO_INIT_NEWOBJECT(dst->typeinfo,iptr);
1627 /* XXX unify the following cases */
1628 else if (ISBUILTIN(BUILTIN_newarray_boolean)) {
1629 TYPECHECK_INT(curstack);
1630 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BOOLEAN);
1632 else if (ISBUILTIN(BUILTIN_newarray_char)) {
1633 TYPECHECK_INT(curstack);
1634 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_CHAR);
1636 else if (ISBUILTIN(BUILTIN_newarray_float)) {
1637 TYPECHECK_INT(curstack);
1638 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_FLOAT);
1640 else if (ISBUILTIN(BUILTIN_newarray_double)) {
1641 TYPECHECK_INT(curstack);
1642 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_DOUBLE);
1644 else if (ISBUILTIN(BUILTIN_newarray_byte)) {
1645 TYPECHECK_INT(curstack);
1646 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BYTE);
1648 else if (ISBUILTIN(BUILTIN_newarray_short)) {
1649 TYPECHECK_INT(curstack);
1650 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_SHORT);
1652 else if (ISBUILTIN(BUILTIN_newarray_int)) {
1653 TYPECHECK_INT(curstack);
1654 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_INT);
1656 else if (ISBUILTIN(BUILTIN_newarray_long)) {
1657 TYPECHECK_INT(curstack);
1658 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_LONG);
1661 builtindesc = builtin_desc;
1662 while (builtindesc->opcode && builtindesc->builtin
1663 != (functionptr) iptr->val.a) builtindesc++;
1664 if (!builtindesc->opcode) {
1665 dolog("Builtin not in table: %s",icmd_builtin_name((functionptr) iptr->val.a));
1666 panic("Internal error: builtin not found in table");
1668 TYPECHECK_ARGS1(builtindesc->type_s1);
1670 maythrow = true; /* XXX better safe than sorry */
1673 /****************************************/
1674 /* PRIMITIVE VARIABLE ACCESS */
1676 case ICMD_ILOAD: CHECK_ONEWORD(iptr->op1,TYPE_INT); break;
1677 case ICMD_FLOAD: CHECK_ONEWORD(iptr->op1,TYPE_FLOAT); break;
1678 case ICMD_IINC: CHECK_ONEWORD(iptr->op1,TYPE_INT); break;
1679 case ICMD_LLOAD: CHECK_TWOWORD(iptr->op1,TYPE_LONG); break;
1680 case ICMD_DLOAD: CHECK_TWOWORD(iptr->op1,TYPE_DOUBLE); break;
1682 case ICMD_FSTORE: STORE_ONEWORD(iptr->op1,TYPE_FLOAT); break;
1683 case ICMD_ISTORE: STORE_ONEWORD(iptr->op1,TYPE_INT); break;
1684 case ICMD_LSTORE: STORE_TWOWORD(iptr->op1,TYPE_LONG); break;
1685 case ICMD_DSTORE: STORE_TWOWORD(iptr->op1,TYPE_DOUBLE); break;
1687 /****************************************/
1688 /* INSTRUCTIONS WHICH SHOULD HAVE BEEN */
1689 /* REPLACED BY BUILTIN CALLS */
1693 case ICMD_ANEWARRAY:
1694 case ICMD_MONITORENTER:
1695 case ICMD_MONITOREXIT:
1697 /* XXX only check this in debug mode? */
1698 LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
1699 LOG("Should have been converted to builtin function call.");
1700 panic("Internal error: unexpected instruction encountered");
1703 /****************************************/
1704 /* UNCHECKED OPERATIONS */
1706 /* These ops have no input or output to be checked */
1707 /* (apart from the checks done in analyse_stack). */
1708 /* XXX only add cases for them in debug mode? */
1713 case ICMD_READONLY_ARG: /* XXX ? */
1714 case ICMD_CLEAR_ARGREN: /* XXX ? */
1717 case ICMD_CHECKASIZE:
1718 case ICMD_NULLCHECKPOP:
1722 /****************************************/
1723 /* ARITHMETIC AND CONVERSION */
1724 /* (These instructions are typechecked in analyse_stack.) */
1726 /* The following instructions may throw a runtime exception: */
1736 /* The following instructions never throw a runtime exception: */
1737 /* XXX only add cases for them in debug mode? */
1744 case ICMD_IFEQ_ICONST:
1745 case ICMD_IFNE_ICONST:
1746 case ICMD_IFLT_ICONST:
1747 case ICMD_IFGE_ICONST:
1748 case ICMD_IFGT_ICONST:
1749 case ICMD_IFLE_ICONST:
1750 case ICMD_ELSE_ICONST:
1772 case ICMD_IREM0X10001:
1773 case ICMD_LREM0X10001:
1776 case ICMD_IADDCONST:
1777 case ICMD_ISUBCONST:
1778 case ICMD_IMULCONST:
1779 case ICMD_IANDCONST:
1781 case ICMD_IXORCONST:
1782 case ICMD_ISHLCONST:
1783 case ICMD_ISHRCONST:
1784 case ICMD_IUSHRCONST:
1786 case ICMD_LADDCONST:
1787 case ICMD_LSUBCONST:
1788 case ICMD_LMULCONST:
1789 case ICMD_LANDCONST:
1791 case ICMD_LXORCONST:
1792 case ICMD_LSHLCONST:
1793 case ICMD_LSHRCONST:
1794 case ICMD_LUSHRCONST:
1811 case ICMD_INT2SHORT:
1814 case ICMD_LCMPCONST:
1835 /****************************************/
1838 LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
1839 panic("Missing ICMD code during typecheck");
1842 /* the output of this instruction becomes the current stack */
1845 /* reach exception handlers for this instruction */
1847 LOG("reaching exception handlers");
1849 while (handlers[i]) {
1850 tbptr = handlers[i]->handler;
1851 TYPECHECK_REACH(REACH_THROW); /* XXX jsr chain? */
1857 DOLOG(typeinfo_print_block(get_logfile(),curstack,numlocals,vtype,vinfo,(jsrchain) ? touched : NULL));
1862 } /* while instructions */
1864 LOG("instructions done");
1865 LOGSTR("RESULT=> ");
1866 DOLOG(typeinfo_print_block(get_logfile(),curstack,numlocals,vtype,vinfo,(jsrchain) ? touched : NULL));
1869 /* propagate stack and variables to the following block */
1870 if (!superblockend) {
1871 LOG("reaching following block");
1873 while (tbptr->flags == BBDELETED) {
1875 #ifdef TYPECHECK_DEBUG
1876 if ((tbptr-block) >= block_count)
1877 panic("Control flow falls off the last block");
1880 TYPECHECK_REACH(REACH_STD);
1883 } /* if block has to be checked */
1885 } /* while blocks */
1887 LOGIF(repeat,"repeat=true");
1890 #ifdef TYPECHECK_STATISTICS
1891 dolog("Typechecker did %4d iterations",count_iterations);
1894 #ifdef TYPECHECK_DEBUG
1895 for (i=0; i<block_count; ++i) {
1896 if (block[i].flags != BBDELETED
1897 && block[i].flags != BBUNDEF
1898 && block[i].flags != BBFINISHED
1899 && block[i].flags != BBTYPECHECK_UNDEF) /* typecheck may never reach
1900 * some exception handlers,
1903 LOG2("block L%03d has invalid flags after typecheck: %d",
1904 block[i].debug_nr,block[i].flags);
1905 panic("Invalid block flags after typecheck");
1910 /* Reset blocks we never reached */
1911 for (i=0; i<block_count; ++i) {
1912 if (block[i].flags == BBTYPECHECK_UNDEF)
1913 block[i].flags = BBFINISHED;
1916 LOGimp("exiting typecheck");
1921 #endif /* CACAO_TYPECHECK */
1924 * These are local overrides for various environment variables in Emacs.
1925 * Please do not remove this and leave it at the end of the file, where
1926 * Emacs will automagically detect them.
1927 * ---------------------------------------------------------------------
1930 * indent-tabs-mode: t