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 727 2003-12-11 10:52:40Z 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(dolog_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(dolog_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);
153 typeinfo_print_blocks(FILE *file,int vnum,u1 *vtype,typeinfo *vinfo)
158 for (bi=0; bi<block_count; ++bi) {
159 fprintf(file,"%04d: (%3d) ",bi,block[bi].flags);
160 typeinfo_print_block(file,block[bi].instack,
161 vnum,vtype+vnum*bi,vinfo+vnum*bi,NULL);
164 /* for (j=0; j<block[bi].icount; ++j) { */
165 /* fprintf(file,"\t%s\n",icmd_names[block[bi].iinstr[j].opc]); */
168 show_icmd_block(block+bi);
174 /****************************************************************************/
176 /****************************************************************************/
178 #ifdef TYPECHECK_DEBUG
179 /*#define TYPECHECK_STATISTICS*/
182 #ifdef TYPECHECK_STATISTICS
183 #define TYPECHECK_COUNT(cnt) (cnt)++
185 #define TYPECHECK_COUNT(cnt)
188 /****************************************************************************/
189 /* INTERNAL DATA STRUCTURES */
190 /****************************************************************************/
192 typedef struct jsr_record jsr_record;
195 * For each basic block we store the chain of JSR instructions which
196 * were used to reach the block (usually zero or one). For more
197 * details on verifying JSR and RET instructions see the Java VM
200 * CAUTION: The fields starting with sbr_ are only valid for the
201 * jsr_record of the first block of the subroutine.
204 basicblock *target; /* target of the JSR instruction (first block of subroutine) */
205 jsr_record *next; /* for chaining in nested try ... finally */ /* XXX make it sbr_next? */
206 u1 *sbr_touched; /* specifies which variables the subroutine touches */
207 u1 *sbr_vtype; /* Types of local variables after RET */
208 typeinfo *sbr_vinfo; /* Types of local variables after RET */
209 u1 touched[1]; /* touched flags for local variables */
212 /****************************************************************************/
213 /* MACROS USED INTERNALLY IN typecheck() */
214 /****************************************************************************/
216 #define TOUCH_VARIABLE(num) \
217 do {if (jsrchain) touched[num] = TOUCHED_YES;} while (0)
218 #define TOUCH_TWOWORD(num) \
219 do {TOUCH_VARIABLE(num);TOUCH_VARIABLE((num)+1);} while (0)
221 #define INDEX_ONEWORD(num) \
222 do { if((num)<0 || (num)>=validlocals) \
223 panic("Invalid local variable index"); } while (0)
224 #define INDEX_TWOWORD(num) \
225 do { if((num)<0 || ((num)+1)>=validlocals) \
226 panic("Invalid local variable index"); } while (0)
228 #define SET_VARIABLE(num,type) \
229 do {vtype[num] = (type); \
230 if ((num)>0 && IS_2_WORD_TYPE(vtype[(num)-1])) { \
231 vtype[(num)-1] = TYPE_VOID; \
232 TOUCH_VARIABLE((num)-1); \
234 TOUCH_VARIABLE(num);} while(0)
236 #define STORE_ONEWORD(num,type) \
237 do {INDEX_ONEWORD(num); \
238 SET_VARIABLE(num,type);} while(0)
240 #define STORE_TWOWORD(num,type) \
241 do {INDEX_TWOWORD(num); \
242 SET_VARIABLE(num,type); \
243 vtype[(num)+1] = TYPE_VOID; \
244 TOUCH_VARIABLE((num)+1);} while(0)
246 #define CHECK_ONEWORD(num,type) \
247 do {INDEX_ONEWORD(num); \
248 if (vtype[(num)] != (type)) panic("Variable type mismatch"); \
249 TOUCH_VARIABLE(num);} while(0)
251 #define CHECK_TWOWORD(num,type) \
252 do {INDEX_TWOWORD(num); \
253 if (vtype[(num)] != (type)) panic("Variable type mismatch"); \
254 TOUCH_VARIABLE(num); \
255 TOUCH_VARIABLE((num)+1);} while(0)
257 /* XXX maybe it's faster to copy always */
258 #define COPYTYPE(source,dest) \
259 {if ((source)->type == TYPE_ADR) \
260 TYPEINFO_COPY((source)->typeinfo,(dest)->typeinfo);}
262 #define ISBUILTIN(v) (iptr->val.a == (functionptr)(v))
264 #define TYPECHECK_STACK(sp,tp) \
265 do { if ((sp)->type != (tp)) \
266 panic("Wrong data type on stack"); } while(0)
268 #define TYPECHECK_ADR(sp) TYPECHECK_STACK(sp,TYPE_ADR)
269 #define TYPECHECK_INT(sp) TYPECHECK_STACK(sp,TYPE_INT)
270 #define TYPECHECK_LNG(sp) TYPECHECK_STACK(sp,TYPE_LNG)
271 #define TYPECHECK_FLT(sp) TYPECHECK_STACK(sp,TYPE_FLT)
272 #define TYPECHECK_DBL(sp) TYPECHECK_STACK(sp,TYPE_DBL)
274 #define TYPECHECK_ARGS1(t1) \
275 do {TYPECHECK_STACK(curstack,t1);} while (0)
276 #define TYPECHECK_ARGS2(t1,t2) \
277 do {TYPECHECK_ARGS1(t1); \
278 TYPECHECK_STACK(curstack->prev,t2);} while (0)
279 #define TYPECHECK_ARGS3(t1,t2,t3) \
280 do {TYPECHECK_ARGS2(t1,t2); \
281 TYPECHECK_STACK(curstack->prev->prev,t3);} while (0)
283 /* TYPECHECK_COPYVARS: copy the types and typeinfos of the current local
284 * variables to the local variables of the target block.
286 * vtype......current local variable types
287 * vinfo......current local variable typeinfos
288 * ttype......local variable types of target block
289 * tinfo......local variable typeinfos of target block
290 * numlocals..number of local variables
294 #define TYPECHECK_COPYVARS \
296 LOG("TYPECHECK_COPYVARS"); \
297 for (macro_i=0; macro_i<numlocals; ++macro_i) { \
298 if ((ttype[macro_i] = vtype[macro_i]) == TYPE_ADR) \
299 TYPEINFO_CLONE(vinfo[macro_i],tinfo[macro_i]); \
302 /* TYPECHECK_MERGEVARS: merge the local variables of the target block
303 * with the current local variables.
305 * vtype......current local variable types
306 * vinfo......current local variable typeinfos
307 * ttype......local variable types of target block
308 * tinfo......local variable typeinfos of target block
309 * numlocals..number of local variables
311 * changed....set to true if any typeinfo has changed
315 #define TYPECHECK_MERGEVARS \
317 LOG("TYPECHECK_MERGEVARS"); \
318 for (macro_i=0; macro_i<numlocals; ++macro_i) { \
319 if ((ttype[macro_i] != TYPE_VOID) && (vtype[macro_i] != ttype[macro_i])) { \
320 LOG3("var %d: type %d + type %d = void",macro_i,ttype[macro_i],vtype[macro_i]); \
321 ttype[macro_i] = TYPE_VOID; \
323 } else if (ttype[macro_i] == TYPE_ADR) { \
324 if ( ((TYPEINFO_IS_PRIMITIVE(tinfo[macro_i])) ? 1 : 0) \
326 ((TYPEINFO_IS_PRIMITIVE(vinfo[macro_i])) ? 1 : 0)) { \
327 LOG1("var %d: primitive + reference merge",macro_i); \
328 ttype[macro_i] = TYPE_VOID; \
332 LOG1("var %d:",macro_i); \
333 LOGINFO(tinfo+macro_i); \
334 LOGINFO(vinfo+macro_i); \
335 changed |= typeinfo_merge(tinfo+macro_i,vinfo+macro_i); \
336 LOGINFO(tinfo+macro_i); \
337 LOGIF(changed,"vars have changed"); \
342 /* TYPECHECK_MERGEJSR:
346 * tbptr......target block
347 * changed....set to true if any typeinfo has changed
348 * numlocals..number of local variables
349 * touched....current touched flags of local variables
351 * macro_i, jsrtemp, jsrtemp2
353 #define TYPECHECK_MERGEJSR \
355 LOG("TYPECHECK_MERGEJSR"); \
356 jsrtemp = jsrbuffer[tbptr-block]; \
357 jsrtemp2 = jsrchain; \
358 while (jsrtemp || jsrtemp2) { \
359 if (!jsrtemp || !jsrtemp2) \
360 panic("Merging JSR subroutines of different depth"); \
361 if (jsrtemp->target != jsrtemp2->target) \
362 panic("Merging different JSR subroutines"); \
363 jsrtemp = jsrtemp->next; \
364 jsrtemp2 = jsrtemp2->next; \
366 jsrtemp = jsrbuffer[tbptr-block]; \
368 for (macro_i=0; macro_i<numlocals; ++macro_i) { \
369 jsrtemp->touched[i] |= touched[i]; \
372 /* TYPECHECK_COPYSTACK: copy the typeinfos of the current stack to
373 * the input stack of the target block.
375 * srcstack...current stack
376 * dststack...input stack of target block
378 #define TYPECHECK_COPYSTACK \
380 LOG("TYPECHECK_COPYSTACK"); \
382 LOG1("copy %d",srcstack->type); \
383 if (!dststack) panic("Stack depth mismatch"); \
384 if (srcstack->type != dststack->type) \
385 panic("Type mismatch on stack"); \
386 if (srcstack->type == TYPE_ADR) { \
387 TYPEINFO_CLONE(srcstack->typeinfo,dststack->typeinfo); \
389 dststack = dststack->prev; \
390 srcstack = srcstack->prev; \
392 if (dststack) panic("Stack depth mismatch"); \
395 /* TYPECHECK_MERGESTACK: merge the input stack of the target block
396 * with the current stack.
398 * srcstack...current stack
399 * dststack...input stack of target block
401 * changed....set to true if any typeinfo has changed
403 #define TYPECHECK_MERGESTACK \
405 LOG("TYPECHECK_MERGESTACK"); \
407 if (!dststack) panic("Stack depth mismatch"); \
408 if (srcstack->type != dststack->type) \
409 panic("Type mismatch on stack"); \
410 if (srcstack->type == TYPE_ADR) { \
411 LOGINFO(&dststack->typeinfo); \
412 LOGINFO(&srcstack->typeinfo); LOGFLUSH; \
413 changed |= typeinfo_merge(&dststack->typeinfo, \
414 &srcstack->typeinfo); \
415 LOGINFO(&dststack->typeinfo); \
416 LOG((changed)?"CHANGED!\n":"not changed.\n"); \
418 dststack = dststack->prev; \
419 srcstack = srcstack->prev; \
421 if (dststack) panic("Stack depth mismatch"); \
425 /* TYPECHECK_CHECK_JSR_CHAIN: checks if the target block is reached by
426 * the same JSR targets on all control paths.
429 * tbptr......target block
430 * jsrchain...current JSR target chain
431 * jsrbuffer..JSR target chain for each basic block
433 * panic if the JSR target chains don't match
437 #define TYPECHECK_CHECK_JSR_CHAIN \
439 jsrtemp = jsrbuffer[tbptr-block]; \
440 if (!jsrtemp) panic("non-subroutine called by JSR"); \
441 if (jsrtemp->target != tbptr) \
442 panic("Merging different JSR subroutines"); \
443 jsrtemp = jsrtemp->next; \
444 jsrtemp2 = jsrchain; \
445 while (jsrtemp || jsrtemp2) { \
446 if (!jsrtemp || !jsrtemp2) \
447 panic("Merging JSR subroutines of different depth"); \
448 if (jsrtemp->target != jsrtemp2->target) \
449 panic("Merging different JSR subroutines"); \
450 jsrtemp = jsrtemp->next; \
451 jsrtemp2 = jsrtemp2->next; \
454 /* TYPECHECK_ADD_JSR: add a JSR target to the current JSR target chain
455 * and store the resulting chain in the target block.
458 * jsrchain...current JSR target chain
459 * tbptr.....the basic block targeted by the JSR
460 * numlocals..number of local variables
461 * jsrbuffer..JSR target chain for each basic block
465 #define TYPECHECK_ADD_JSR \
467 LOG1("adding JSR to block %04d",(tbptr)-block); \
468 jsrtemp = (jsr_record *) dump_alloc(sizeof(jsr_record)+(numlocals-1)*sizeof(u1)); \
469 jsrtemp->target = (tbptr); \
470 jsrtemp->next = jsrchain; \
471 jsrtemp->sbr_touched = NULL; \
472 memset(&jsrtemp->touched,TOUCHED_NO,sizeof(u1)*numlocals); \
473 jsrbuffer[tbptr-block] = jsrtemp; \
476 /* TYPECHECK_COPYJSR: copy the current JSR chain to the target block.
479 * chain......current JSR target chain
480 * tbptr.....the basic block targeted by the JSR
481 * numlocals..number of local variables
482 * jsrbuffer..JSR target chain for each basic block
483 * touched....current touched flags of local variables
487 #define TYPECHECK_COPYJSR(chain) \
489 LOG("TYPECHECK_COPYJSR"); \
491 jsrtemp = (jsr_record *) dump_alloc(sizeof(jsr_record)+(numlocals-1)*sizeof(u1)); \
492 jsrtemp->target = (chain)->target; \
493 jsrtemp->next = (chain)->next; \
494 jsrtemp->sbr_touched = NULL; \
495 memcpy(&jsrtemp->touched,touched,sizeof(u1)*numlocals); \
496 jsrbuffer[tbptr-block] = jsrtemp; \
499 jsrbuffer[tbptr-block] = NULL; \
502 /* TYPECHECK_BRANCH_BACKWARDS: executed when control flow moves
503 * backwards. Checks if there are uninitialized objects on the
504 * stack or in local variables.
506 * dst........current output stack pointer (not needed for REACH_THROW)
507 * vtype......current local variable types
508 * vinfo......current local variable typeinfos
512 #define TYPECHECK_BRANCH_BACKWARDS \
517 if (srcstack->type == TYPE_ADR && \
518 TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo)) \
519 panic("Branching backwards with uninitialized object on stack"); \
520 srcstack = srcstack->prev; \
522 for (macro_i=0; macro_i<numlocals; ++macro_i) \
523 if (vtype[macro_i] == TYPE_ADR && \
524 TYPEINFO_IS_NEWOBJECT(vinfo[macro_i])) \
525 panic("Branching backwards with uninitialized object in local variable"); \
528 /* TYPECHECK_REACH: executed, when the target block (tbptr) can be reached
529 * from the current block (bptr). The types of local variables and
530 * stack slots are propagated to the target block.
532 * bptr.......current block
533 * tbptr......target block
534 * dst........current output stack pointer (not needed for REACH_THROW)
535 * numlocals..number of local variables
536 * vtype......current local variable types
537 * vinfo......current local variable typeinfos
538 * jsrchain...current JSR target chain
539 * jsrbuffer..JSR target chain for each basic block
540 * way........in which way the block is reached (REACH_ constant)
541 * touched....current touched flags of local variables
543 * repeat.....changed to true if a block before the current
546 * ttype, tinfo, srcstack, dststack, changed, macro_i
548 #define TYPECHECK_REACH(way) \
550 LOG2("reaching block %04d (%d)",tbptr-block,way); \
551 if (tbptr <= bptr && way != REACH_THROW) \
552 TYPECHECK_BRANCH_BACKWARDS; \
554 dststack = tbptr->instack; \
555 ttype = vartype + numlocals*(tbptr-block); \
556 tinfo = vartypeinfo + numlocals*(tbptr-block); \
557 if (tbptr->flags == BBTYPECHECK_UNDEF) { \
558 /* This block is reached for the first time */ \
559 if (way == REACH_JSR) { \
561 TYPECHECK_COPYVARS; \
564 TYPECHECK_COPYJSR(jsrchain); \
565 TYPECHECK_COPYVARS; \
567 if (way != REACH_THROW) TYPECHECK_COPYSTACK; \
570 /* This block has been reached before */ \
572 if (way == REACH_JSR) \
573 TYPECHECK_CHECK_JSR_CHAIN; \
575 TYPECHECK_MERGEJSR; \
576 TYPECHECK_MERGEVARS; \
577 if (way != REACH_THROW) TYPECHECK_MERGESTACK; \
581 tbptr->flags = BBTYPECHECK_REACHED; \
582 if (tbptr <= bptr) {repeat = true; LOG("REPEAT!");} \
587 /* TYPECHECK_LEAVE: executed when the method is exited non-abruptly
589 * class........class of the current method
590 * numlocals....number of local variables
591 * vtype........current local variable types
592 * vinfo........current local variable typeinfos
593 * initmethod...true if this is an <init> method
595 #define TYPECHECK_LEAVE \
597 if (initmethod && class != class_java_lang_Object) { \
598 /* check the marker variable */ \
599 LOG("Checking <init> marker"); \
600 if (vtype[numlocals-1] == TYPE_VOID) \
601 panic("<init> method does not initialize 'this'"); \
605 /****************************************************************************/
607 /****************************************************************************/
609 #define MAXPARAMS 255
611 /* typecheck is called directly after analyse_stack */
615 int b_count, b_index;
616 stackptr curstack; /* input stack top for current instruction */
617 stackptr srcstack; /* source stack for copying and merging */
618 stackptr dststack; /* target stack for copying and merging */
619 int opcode; /* current opcode */
620 int macro_i, i; /* temporary counters */
621 int len; /* for counting instructions, etc. */
622 bool superblockend; /* true if no fallthrough to next block */
623 bool repeat; /* if true, blocks are iterated over again */
624 bool changed; /* used in macros */
625 instruction *iptr; /* pointer to current instruction */
626 basicblock *bptr; /* pointer to current basic block */
627 basicblock *tbptr; /* temporary for target block */
628 int numlocals; /* number of local variables */
629 int validlocals; /* number of valid local variable indices */
630 u1 *vartype; /* type of each local for each basic block */
631 typeinfo *vartypeinfo; /* type of each local for each basic block */
632 u1 *vtype; /* type of each local for current instruction */
633 typeinfo *vinfo; /* type of each local for current instruction */
634 u1 *ttype; /* temporary pointer */
635 typeinfo *tinfo; /* temporary pointer */
636 typeinfo tempinfo; /* temporary */
637 int returntype; /* return type of current method */
638 typeinfo returntypeinfo; /* typeinfo for return type */
639 u1 *ptype; /* parameter types of called method */
640 typeinfo *pinfo; /* parameter typeinfos of called method */
641 int rtype; /* return type of called method */
642 typeinfo rinfo; /* typeinfo for return type of called method */
643 stackptr dst; /* output stack of current instruction */
644 basicblock **tptr; /* pointer into target list of switch instructions */
645 jsr_record **jsrbuffer; /* JSR target chain for each basic block */
646 jsr_record *jsrchain; /* JSR chain for current block */
647 jsr_record *jsrtemp,*jsrtemp2; /* temporary variables */
648 jsr_record *subroutine; /* jsr_record of the current subroutine */
649 u1 *touched; /* touched flags for local variables */
650 xtable **handlers; /* active exception handlers */
651 classinfo *cls; /* temporary */
652 bool maythrow; /* true if this instruction may throw */
653 utf *name_init; /* "<init>" */
654 bool initmethod; /* true if this is an "<init>" method */
655 builtin_descriptor *builtindesc;
657 #ifdef TYPECHECK_STATISTICS
658 int count_iterations = 0;
661 LOGSTR("\n==============================================================================\n");
662 DOLOG(show_icmd_method());
663 LOGSTR("\n==============================================================================\n");
664 LOGimpSTR("Entering typecheck: ");
665 LOGimpSTRu(method->name);
667 LOGimpSTRu(method->descriptor);
668 LOGimpSTR(" (class ");
669 LOGimpSTRu(method->class->name);
672 name_init = utf_new_char("<init>");
673 initmethod = (method->name == name_init);
675 ptype = DMNEW(u1,MAXPARAMS);
676 pinfo = DMNEW(typeinfo,MAXPARAMS);
678 LOG("Buffer allocated.\n");
680 /* reset all BBFINISHED blocks to BBTYPECHECK_UNDEF. */
681 b_count = block_count;
683 while (--b_count >= 0) {
684 #ifdef TYPECHECK_DEBUG
685 if (bptr->flags != BBFINISHED && bptr->flags != BBDELETED
686 && bptr->flags != BBUNDEF)
689 LOGSTR1("block flags: %d\n",bptr->flags); LOGFLUSH;
690 panic("Internal error: Unexpected block flags in typecheck()");
693 if (bptr->flags >= BBFINISHED) {
694 bptr->flags = BBTYPECHECK_UNDEF;
699 /* The first block is always reached */
700 if (block_count && block[0].flags == BBTYPECHECK_UNDEF)
701 block[0].flags = BBTYPECHECK_REACHED;
703 LOG("Blocks reset.\n");
705 /* number of local variables */
707 /* In <init> methods we use an extra local variable to signal if
708 * the 'this' reference has been initialized. */
709 numlocals = maxlocals;
710 validlocals = numlocals;
711 if (initmethod) numlocals++;
713 /* allocate the buffers for local variables */
714 vartype = DMNEW(u1,numlocals * (block_count+1));
715 vartypeinfo = DMNEW(typeinfo,numlocals * (block_count+1));
716 touched = DMNEW(u1,numlocals);
717 vtype = vartype + numlocals * block_count;
718 vinfo = vartypeinfo + numlocals * block_count;
719 memset(vartype,TYPE_VOID,numlocals * (block_count+1) * sizeof(typeinfo));
720 memset(vartypeinfo,0,numlocals * (block_count+1) * sizeof(typeinfo));
722 LOG("Variable buffer initialized.\n");
724 /* allocate the buffer for storing JSR target chains */
725 jsrbuffer = DMNEW(jsr_record*,block_count);
726 memset(jsrbuffer,0,block_count * sizeof(jsr_record*));
729 LOG("jsrbuffer initialized.\n");
731 /* allocate the buffer of active exception handlers */
732 handlers = DMNEW(xtable*,method->exceptiontablelength + 1);
734 /* initialize the variable types of the first block */
735 /* to the types of the arguments */
739 /* if this is an instance method initialize the "this" ref type */
740 if (!(method->flags & ACC_STATIC)) {
741 *ttype++ = TYPE_ADDRESS;
743 TYPEINFO_INIT_NEWOBJECT(*tinfo,NULL);
745 TYPEINFO_INIT_CLASSINFO(*tinfo,class);
749 LOG("'this' argument set.\n");
751 /* the rest of the arguments and the return type */
752 typeinfo_init_from_method_args(method->descriptor,ttype,tinfo,
753 numlocals - (tinfo-vartypeinfo),
754 true, /* two word types use two slots */
755 &returntype,&returntypeinfo);
757 LOG("Arguments set.\n");
759 /* initialize the input stack of exception handlers */
760 for (i=0; i<method->exceptiontablelength; ++i) {
761 cls = extable[i].catchtype;
762 if (!cls) cls = class_java_lang_Throwable;
763 LOGSTR1("handler %i: ",i); LOGSTRu(cls->name); LOGNL;
764 TYPEINFO_INIT_CLASSINFO(extable[i].handler->instack->typeinfo,cls);
767 LOG("Exception handler stacks set.\n");
769 /* loop while there are still blocks to be checked */
771 TYPECHECK_COUNT(count_iterations);
775 b_count = block_count;
778 while (--b_count >= 0) {
779 LOGSTR1("---- BLOCK %04d, ",bptr-block);
780 LOGSTR1("blockflags: %d\n",bptr->flags);
783 if (bptr->flags == BBTYPECHECK_REACHED) {
784 LOGSTR1("\n---- BLOCK %04d ------------------------------------------------\n",bptr-block);
787 superblockend = false;
788 bptr->flags = BBFINISHED;
789 b_index = bptr - block;
791 /* init stack at the start of this block */
792 curstack = bptr->instack;
794 /* determine the active exception handlers for this block */
795 /* XXX could use a faster algorithm with sorted lists or
798 for (i=0; i<method->exceptiontablelength; ++i) {
799 if ((extable[i].start <= bptr) && (extable[i].end > bptr)) {
800 LOG1("active handler L%03d",extable[i].handler->debug_nr);
801 handlers[len++] = extable + i;
804 handlers[len] = NULL;
806 /* init variable types at the start of this block */
807 for (i=0; i<numlocals; ++i) {
808 vtype[i] = vartype[numlocals*b_index + i];
809 TYPEINFO_COPY(vartypeinfo[numlocals*b_index + i],vinfo[i]);
812 vtype[i] == TYPE_ADR && TYPEINFO_IS_NEWOBJECT(vinfo[i]))
813 panic("Uninitialized object in local variable inside try block");
816 /* init JSR target chain */
817 if ((jsrchain = jsrbuffer[b_index]) != NULL) {
818 #ifdef TYPECHECK_VERBOSE
819 if (typecheckverbose) {
820 LOGSTR("jsr chain:");
823 LOGSTR1(" L%03d",jsrtemp->target->debug_nr);
824 jsrtemp = jsrtemp->next;
831 subroutine = jsrbuffer[jsrchain->target - block];
832 memcpy(touched,jsrchain->touched,sizeof(u1)*numlocals);
836 #ifdef TYPECHECK_VERBOSE
837 if (typecheckverbose) {
838 if (subroutine) {LOGSTR1("subroutine L%03d\n",subroutine->target->debug_nr);LOGFLUSH;}
839 typeinfo_print_block(get_logfile(),curstack,numlocals,vtype,vinfo,(jsrchain) ? touched : NULL);
844 /* loop over the instructions */
848 DOLOG(show_icmd(iptr,false));
858 /****************************************/
859 /* STACK MANIPULATIONS */
861 /* We just need to copy the typeinfo */
862 /* for slots containing addresses. */
864 /* XXX We assume that the destination stack
865 * slots were continuously allocated in
866 * memory. (The current implementation in
871 COPYTYPE(curstack,dst);
875 COPYTYPE(curstack,dst);
876 COPYTYPE(curstack,dst-2);
877 COPYTYPE(curstack->prev,dst-1);
881 COPYTYPE(curstack,dst);
882 COPYTYPE(curstack,dst-3);
883 COPYTYPE(curstack->prev,dst-1);
884 COPYTYPE(curstack->prev->prev,dst-2);
888 COPYTYPE(curstack,dst);
889 COPYTYPE(curstack->prev,dst-1);
893 COPYTYPE(curstack,dst);
894 COPYTYPE(curstack->prev,dst-1);
895 COPYTYPE(curstack,dst-3);
896 COPYTYPE(curstack->prev,dst-4);
897 COPYTYPE(curstack->prev->prev,dst-2);
901 COPYTYPE(curstack,dst);
902 COPYTYPE(curstack->prev,dst-1);
903 COPYTYPE(curstack,dst-4);
904 COPYTYPE(curstack->prev,dst-5);
905 COPYTYPE(curstack->prev->prev,dst-2);
906 COPYTYPE(curstack->prev->prev->prev,dst-3);
910 COPYTYPE(curstack,dst-1);
911 COPYTYPE(curstack->prev,dst);
914 /****************************************/
915 /* LOADING ADDRESS FROM VARIABLE */
918 CHECK_ONEWORD(iptr->op1,TYPE_ADR);
920 /* loading a returnAddress is not allowed */
921 if (TYPEINFO_IS_PRIMITIVE(vinfo[iptr->op1]))
922 panic("illegal instruction: ALOAD loading returnAddress");
924 TYPEINFO_COPY(vinfo[iptr->op1],dst->typeinfo);
927 /****************************************/
928 /* STORING ADDRESS TO VARIABLE */
932 TYPEINFO_IS_NEWOBJECT(curstack->typeinfo))
933 panic("Storing uninitialized object in local variable inside try block");
935 STORE_ONEWORD(iptr->op1,TYPE_ADDRESS);
936 TYPEINFO_COPY(curstack->typeinfo,vinfo[iptr->op1]);
939 /****************************************/
940 /* LOADING ADDRESS FROM ARRAY */
943 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(curstack->prev->typeinfo))
944 panic("illegal instruction: AALOAD on non-reference array");
946 typeinfo_init_component(&curstack->prev->typeinfo,&dst->typeinfo);
950 /****************************************/
954 if (!TYPEINFO_IS_REFERENCE(curstack->prev->typeinfo))
955 panic("illegal instruction: PUTFIELD on non-reference");
956 if (TYPEINFO_IS_ARRAY(curstack->prev->typeinfo)) /* XXX arraystub */
957 panic("illegal instruction: PUTFIELD on array");
959 /* check if the value is assignable to the field */
961 fieldinfo *fi = (fieldinfo*) iptr[0].val.a;
963 if (!TYPEINFO_IS_NULLTYPE(curstack->prev->typeinfo)) {
965 /* XXX treat uinitialized objects specially? */
966 if (!class_issubclass(curstack->prev->typeinfo.typeclass,
968 panic("PUTFIELD reference type does not support field");
971 /* XXX check flags */
973 /* XXX ---> unify with ICMD_PUTSTATIC? */
975 /* XXX check access rights */
977 if (curstack->type != fi->type)
978 panic("PUTFIELD type mismatch");
979 if (fi->type == TYPE_ADR) {
980 TYPEINFO_INIT_FROM_FIELDINFO(rinfo,fi);
981 if (!typeinfo_is_assignable(&(curstack->typeinfo),
983 panic("PUTFIELD reference type not assignable");
990 /* check if the value is assignable to the field */
992 fieldinfo *fi = (fieldinfo*) iptr[0].val.a;
995 /* XXX check access rights */
997 if (curstack->type != fi->type)
998 panic("PUTSTATIC type mismatch");
999 if (fi->type == TYPE_ADR) {
1000 TYPEINFO_INIT_FROM_FIELDINFO(rinfo,fi);
1001 if (!typeinfo_is_assignable(&(curstack->typeinfo),
1003 panic("PUTSTATIC reference type not assignable");
1010 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1011 panic("illegal instruction: GETFIELD on non-reference");
1012 if (TYPEINFO_IS_ARRAY(curstack->typeinfo))
1013 panic("illegal instruction: GETFIELD on array");
1016 fieldinfo *fi = (fieldinfo *)(iptr->val.a);
1018 if (!TYPEINFO_IS_NULLTYPE(curstack->typeinfo)) {
1020 if (!class_issubclass(curstack->typeinfo.typeclass,
1022 panic("GETFIELD reference type does not support field");
1025 /* XXX check flags */
1026 /* XXX check access rights */
1027 if (dst->type == TYPE_ADR) {
1028 TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi);
1031 /* XXX check field type? */
1032 TYPEINFO_INIT_PRIMITIVE(dst->typeinfo);
1038 case ICMD_GETSTATIC:
1040 fieldinfo *fi = (fieldinfo *)(iptr->val.a);
1041 /* XXX check flags */
1042 /* XXX check access rights */
1043 if (dst->type == TYPE_ADR) {
1044 TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi);
1047 /* XXX check field type? */
1048 TYPEINFO_INIT_PRIMITIVE(dst->typeinfo);
1054 /****************************************/
1055 /* PRIMITIVE ARRAY ACCESS */
1057 case ICMD_ARRAYLENGTH:
1058 /* XXX should this also work on arraystubs? */
1059 if (!TYPEINFO_MAYBE_ARRAY(curstack->typeinfo))
1060 panic("illegal instruction: ARRAYLENGTH on non-array");
1065 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_BOOLEAN)
1066 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_BYTE))
1067 panic("Array type mismatch");
1071 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_CHAR))
1072 panic("Array type mismatch");
1076 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_DOUBLE))
1077 panic("Array type mismatch");
1081 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_FLOAT))
1082 panic("Array type mismatch");
1086 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_INT))
1087 panic("Array type mismatch");
1091 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_SHORT))
1092 panic("Array type mismatch");
1096 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_LONG))
1097 panic("Array type mismatch");
1102 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_BOOLEAN)
1103 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_BYTE))
1104 panic("Array type mismatch");
1108 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_CHAR))
1109 panic("Array type mismatch");
1113 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_DOUBLE))
1114 panic("Array type mismatch");
1118 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_FLOAT))
1119 panic("Array type mismatch");
1123 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_INT))
1124 panic("Array type mismatch");
1128 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_SHORT))
1129 panic("Array type mismatch");
1133 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_LONG))
1134 panic("Array type mismatch");
1138 /****************************************/
1139 /* OPERATIONS WITH UNCHECKED INPUT */
1141 case ICMD_CHECKCAST:
1142 TYPECHECK_ADR(curstack);
1143 /* returnAddress is not allowed */
1144 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1145 panic("Illegal instruction: CHECKCAST on non-reference");
1147 /* XXX check if the cast can be done statically */
1148 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,(classinfo *)iptr[0].val.a);
1153 case ICMD_INSTANCEOF:
1154 TYPECHECK_ADR(curstack);
1155 /* returnAddress is not allowed */
1156 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1157 panic("Illegal instruction: INSTANCEOF on non-reference");
1159 /* XXX optimize statically? */
1163 if (iptr->val.a == NULL)
1164 TYPEINFO_INIT_NULLTYPE(dst->typeinfo);
1166 /* XXX constants for builtin functions */
1167 /* string constants */
1168 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,class_java_lang_String);
1171 /****************************************/
1172 /* BRANCH INSTRUCTIONS */
1175 superblockend = true;
1178 case ICMD_IFNONNULL:
1185 case ICMD_IF_ICMPEQ:
1186 case ICMD_IF_ICMPNE:
1187 case ICMD_IF_ICMPLT:
1188 case ICMD_IF_ICMPGE:
1189 case ICMD_IF_ICMPGT:
1190 case ICMD_IF_ICMPLE:
1191 case ICMD_IF_ACMPEQ:
1192 case ICMD_IF_ACMPNE:
1199 case ICMD_IF_LCMPEQ:
1200 case ICMD_IF_LCMPNE:
1201 case ICMD_IF_LCMPLT:
1202 case ICMD_IF_LCMPGE:
1203 case ICMD_IF_LCMPGT:
1204 case ICMD_IF_LCMPLE:
1205 tbptr = (basicblock *) iptr->target;
1207 /* propagate stack and variables to the target block */
1208 TYPECHECK_REACH(REACH_STD);
1212 /****************************************/
1215 case ICMD_TABLESWITCH:
1217 s4 *s4ptr = iptr->val.a;
1218 s4ptr++; /* skip default */
1219 i = *s4ptr++; /* low */
1220 i = *s4ptr++ - i + 2; /* +1 for default target */
1222 goto switch_instruction_tail;
1224 case ICMD_LOOKUPSWITCH:
1226 s4 *s4ptr = iptr->val.a;
1227 s4ptr++; /* skip default */
1228 i = *s4ptr++ + 1; /* count +1 for default target */
1230 switch_instruction_tail:
1231 tptr = (basicblock **)iptr->target;
1235 LOG2("target %d is block %04d",(tptr-(basicblock **)iptr->target)-1,tbptr-block);
1236 TYPECHECK_REACH(REACH_STD);
1239 superblockend = true;
1242 /****************************************/
1243 /* RETURNS AND THROW */
1246 TYPEINFO_INIT_CLASSINFO(tempinfo,class_java_lang_Throwable);
1247 if (!typeinfo_is_assignable(&curstack->typeinfo,&tempinfo))
1248 panic("illegal instruction: ATHROW on non-Throwable");
1249 superblockend = true;
1254 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1255 panic("illegal instruction: ARETURN on non-reference");
1257 if (returntype != TYPE_ADDRESS
1258 || !typeinfo_is_assignable(&curstack->typeinfo,&returntypeinfo))
1259 panic("Return type mismatch");
1263 if (returntype != TYPE_INT) panic("Return type mismatch");
1267 if (returntype != TYPE_LONG) panic("Return type mismatch");
1271 if (returntype != TYPE_FLOAT) panic("Return type mismatch");
1275 if (returntype != TYPE_DOUBLE) panic("Return type mismatch");
1279 if (returntype != TYPE_VOID) panic("Return type mismatch");
1282 superblockend = true;
1286 /****************************************/
1287 /* SUBROUTINE INSTRUCTIONS */
1292 /* XXX This is a dirty hack. It is needed
1293 * because of the special handling of ICMD_JSR in stack.c
1295 dst = (stackptr) iptr->val.a;
1297 /* push return address */
1298 TYPEINFO_INIT_PRIMITIVE(dst->typeinfo);
1300 LOG("reaching block...");
1302 /* add the target to the JSR target chain and */
1303 /* propagate stack and variables to the target block */
1304 tbptr = (basicblock *) iptr->target;
1305 TYPECHECK_REACH(REACH_JSR);
1307 /* set dst to the stack after the subroutine execution */
1308 /* XXX We assume (as in stack.c) that the
1309 * subroutine returns the stack as it was
1310 * before the JSR instruction. Is this
1315 /* Find the jsr_record of the called subroutine */
1316 jsrtemp = jsrbuffer[tbptr - block];
1318 /* Check if we already calculated (at least
1319 * for one RET) which variables the
1320 * subroutine touches.
1322 if (jsrtemp->sbr_touched) {
1323 /* Calculate the local variables after the subroutine call */
1324 for (i=0; i<numlocals; ++i)
1325 if (jsrtemp->sbr_touched[i] != TOUCHED_NO) {
1327 if ((vtype[i] = jsrtemp->sbr_vtype[i]) == TYPE_ADR)
1328 TYPEINFO_CLONE(jsrtemp->sbr_vinfo[i],vinfo[i]);
1331 /* continue after the JSR call */
1332 superblockend = false;
1335 /* We cannot proceed until the subroutine has been typechecked. */
1336 /* XXX actually we would not have to check this block again */
1337 bptr->flags = BBTYPECHECK_REACHED;
1339 superblockend = true;
1341 /* XXX may throw? I don't think. */
1345 /* check returnAddress variable */
1346 CHECK_ONEWORD(iptr->op1,TYPE_ADR);
1348 if (!TYPEINFO_IS_PRIMITIVE(vinfo[iptr->op1]))
1349 panic("illegal instruction: RET using non-returnAddress variable");
1351 /* check if we are inside a subroutine */
1353 panic("RET outside of subroutine");
1355 /* determine which variables are touched by this subroutine */
1356 /* and their types */
1357 if (subroutine->sbr_touched) {
1358 for (i=0; i<numlocals; ++i)
1359 subroutine->sbr_touched[i] |= touched[i];
1360 ttype = subroutine->sbr_vtype;
1361 tinfo = subroutine->sbr_vinfo;
1362 TYPECHECK_MERGEVARS;
1365 subroutine->sbr_touched = DMNEW(u1,numlocals);
1366 memcpy(subroutine->sbr_touched,touched,sizeof(u1)*numlocals);
1367 subroutine->sbr_vtype = DMNEW(u1,numlocals);
1368 memcpy(subroutine->sbr_vtype,vtype,sizeof(u1)*numlocals);
1369 subroutine->sbr_vinfo = DMNEW(typeinfo,numlocals);
1370 for (i=0; i<numlocals; ++i)
1371 if (vtype[i] == TYPE_ADR)
1372 TYPEINFO_CLONE(vinfo[i],subroutine->sbr_vinfo[i]);
1374 /* XXX check if subroutine changed types? */
1376 LOGSTR("subroutine touches:");
1377 DOLOG(typeinfo_print_locals(get_logfile(),subroutine->sbr_vtype,subroutine->sbr_vinfo,
1378 subroutine->sbr_touched,numlocals));
1381 /* reach blocks after JSR statements */
1382 for (i=0; i<block_count; ++i) {
1384 LOG1("block L%03d",tbptr->debug_nr);
1385 if (tbptr->iinstr[tbptr->icount - 1].opc != ICMD_JSR)
1387 LOG("ends with JSR");
1388 if ((basicblock*) tbptr->iinstr[tbptr->icount - 1].target != subroutine->target)
1392 LOG1("RET reaches block %04d",tbptr-block);
1394 /*TYPECHECK_REACH(REACH_RET);*/
1397 superblockend = true;
1400 /****************************************/
1403 case ICMD_INVOKEVIRTUAL:
1404 case ICMD_INVOKESPECIAL:
1405 case ICMD_INVOKESTATIC:
1406 case ICMD_INVOKEINTERFACE:
1408 /* XXX check if this opcode may invoke this method */
1409 /* XXX check access rights */
1411 methodinfo *mi = (methodinfo*) iptr->val.a;
1412 bool callinginit = (opcode == ICMD_INVOKESPECIAL && mi->name == name_init);
1414 classinfo *initclass;
1416 /* XXX for INVOKESPECIAL: check if the invokation is done at all */
1418 /* fetch parameter types and return type */
1419 /* XXX might use dst->typeinfo directly if non void */
1421 if (opcode != ICMD_INVOKESTATIC) {
1422 ptype[0] = TYPE_ADR;
1423 TYPEINFO_INIT_CLASSINFO(pinfo[0],mi->class);
1426 typeinfo_init_from_method_args(mi->descriptor,ptype+i,pinfo+i,
1430 /* check parameter types */
1431 srcstack = curstack;
1432 i = mi->paramcount; /* number of parameters including 'this'*/
1435 if (srcstack->type != ptype[i])
1436 panic("Parameter type mismatch in method invocation");
1437 if (srcstack->type == TYPE_ADR) {
1438 LOGINFO(&(srcstack->typeinfo));
1440 if (i==0 && callinginit)
1442 /* first argument to <init> method */
1443 if (!TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo))
1444 panic("Calling <init> on initialized object");
1446 /* get the address of the NEW instruction */
1447 LOGINFO(&(srcstack->typeinfo));
1448 ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(srcstack->typeinfo);
1449 initclass = (ins) ? (classinfo*)ins[-1].val.a : method->class;
1450 LOGSTR("class: "); LOGSTRu(initclass->name); LOGNL;
1452 /* XXX check type */
1455 if (!typeinfo_is_assignable(&(srcstack->typeinfo),pinfo+i))
1456 panic("Parameter reference type mismatch in method invocation");
1461 srcstack = srcstack->prev;
1464 LOG("checking return type");
1465 if (rtype != TYPE_VOID) {
1466 if (rtype != dst->type)
1467 panic("Return type mismatch in method invocation");
1468 TYPEINFO_COPY(rinfo,dst->typeinfo);
1472 LOG("replacing uninitialized object");
1473 /* replace uninitialized object type on stack */
1476 if (srcstack->type == TYPE_ADR
1477 && TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo)
1478 && TYPEINFO_NEWOBJECT_INSTRUCTION(srcstack->typeinfo) == ins)
1480 LOG("replacing uninitialized type on stack");
1481 TYPEINFO_INIT_CLASSINFO(srcstack->typeinfo,initclass);
1483 srcstack = srcstack->prev;
1485 /* replace uninitialized object type in locals */
1486 for (i=0; i<numlocals; ++i) {
1487 if (vtype[i] == TYPE_ADR
1488 && TYPEINFO_IS_NEWOBJECT(vinfo[i])
1489 && TYPEINFO_NEWOBJECT_INSTRUCTION(vinfo[i]) == ins)
1491 LOG1("replacing uninitialized type in local %d",i);
1492 TYPEINFO_INIT_CLASSINFO(vinfo[i],initclass);
1496 /* initializing the 'this' reference? */
1497 if (initmethod && !ins) {
1498 /* set our marker variable to type int */
1499 LOG("setting <init> marker");
1500 vtype[numlocals-1] = TYPE_INT;
1507 case ICMD_MULTIANEWARRAY:
1510 arraydescriptor *desc;
1512 /* check the array lengths on the stack */
1514 if (i<1) panic("MULTIANEWARRAY with dimensions < 1");
1515 srcstack = curstack;
1518 panic("MULTIANEWARRAY missing array length");
1519 if (srcstack->type != TYPE_INT)
1520 panic("MULTIANEWARRAY using non-int as array length");
1521 srcstack = srcstack->prev;
1524 /* check array descriptor */
1525 arrayvftbl = (vftbl*) iptr[0].val.a;
1527 panic("MULTIANEWARRAY with unlinked class");
1528 if ((desc = arrayvftbl->arraydesc) == NULL)
1529 panic("MULTIANEWARRAY with non-array class");
1530 if (desc->dimension < iptr[0].op1)
1531 panic("MULTIANEWARRAY dimension to high");
1533 /* set the array type of the result */
1534 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,arrayvftbl->class);
1540 if (ISBUILTIN(BUILTIN_aastore)) {
1541 TYPECHECK_ADR(curstack);
1542 TYPECHECK_INT(curstack->prev);
1543 TYPECHECK_ADR(curstack->prev->prev);
1544 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(curstack->prev->prev->typeinfo))
1545 panic("illegal instruction: AASTORE to non-reference array");
1549 typeinfo_init_component(&curstack->prev->prev->typeinfo,&tempinfo);
1550 if (!typeinfo_is_assignable(&curstack->typeinfo,&tempinfo))
1551 panic("illegal instruction: AASTORE to incompatible type");
1555 builtindesc = builtin_desc;
1556 while (builtindesc->opcode && builtindesc->builtin
1557 != (functionptr) iptr->val.a) builtindesc++;
1558 if (!builtindesc->opcode) {
1559 dolog("Builtin not in table: %s",icmd_builtin_name((functionptr) iptr->val.a));
1560 panic("Internal error: builtin not found in table");
1562 TYPECHECK_ARGS3(builtindesc->type_s3,builtindesc->type_s2,builtindesc->type_s1);
1564 maythrow = true; /* XXX better safe than sorry */
1568 /* XXX use BUILTIN_ macros */
1569 if (ISBUILTIN(BUILTIN_newarray))
1572 TYPECHECK_INT(curstack->prev);
1573 if (iptr[-1].opc != ICMD_ACONST)
1574 panic("illegal instruction: builtin_newarray without classinfo");
1575 vft = (vftbl *)iptr[-1].val.a;
1577 panic("ANEWARRAY with unlinked class");
1578 if (!vft->arraydesc)
1579 panic("ANEWARRAY with non-array class");
1580 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,vft->class);
1582 else if (ISBUILTIN(BUILTIN_arrayinstanceof))
1585 TYPECHECK_ADR(curstack->prev);
1586 if (iptr[-1].opc != ICMD_ACONST)
1587 panic("illegal instruction: builtin_arrayinstanceof without classinfo");
1588 vft = (vftbl *)iptr[-1].val.a;
1590 panic("INSTANCEOF with unlinked class");
1591 if (!vft->arraydesc)
1592 panic("internal error: builtin_arrayinstanceof with non-array class");
1594 else if (ISBUILTIN(BUILTIN_checkarraycast)) {
1596 TYPECHECK_ADR(curstack->prev);
1597 if (iptr[-1].opc != ICMD_ACONST)
1598 panic("illegal instruction: BUILTIN_checkarraycast without classinfo");
1599 vft = (vftbl *)iptr[-1].val.a;
1601 panic("CHECKCAST with unlinked class");
1602 if (!vft->arraydesc)
1603 panic("internal error: builtin_checkarraycast with non-array class");
1604 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,vft->class);
1607 builtindesc = builtin_desc;
1608 while (builtindesc->opcode && builtindesc->builtin
1609 != (functionptr) iptr->val.a) builtindesc++;
1610 if (!builtindesc->opcode) {
1611 dolog("Builtin not in table: %s",icmd_builtin_name((functionptr) iptr->val.a));
1612 panic("Internal error: builtin not found in table");
1614 TYPECHECK_ARGS2(builtindesc->type_s2,builtindesc->type_s1);
1616 maythrow = true; /* XXX better safe than sorry */
1620 if (ISBUILTIN(BUILTIN_new)) {
1621 if (iptr[-1].opc != ICMD_ACONST)
1622 panic("illegal instruction: builtin_new without classinfo");
1623 TYPEINFO_INIT_NEWOBJECT(dst->typeinfo,iptr);
1625 /* XXX unify the following cases */
1626 else if (ISBUILTIN(BUILTIN_newarray_boolean)) {
1627 TYPECHECK_INT(curstack);
1628 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BOOLEAN);
1630 else if (ISBUILTIN(BUILTIN_newarray_char)) {
1631 TYPECHECK_INT(curstack);
1632 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_CHAR);
1634 else if (ISBUILTIN(BUILTIN_newarray_float)) {
1635 TYPECHECK_INT(curstack);
1636 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_FLOAT);
1638 else if (ISBUILTIN(BUILTIN_newarray_double)) {
1639 TYPECHECK_INT(curstack);
1640 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_DOUBLE);
1642 else if (ISBUILTIN(BUILTIN_newarray_byte)) {
1643 TYPECHECK_INT(curstack);
1644 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BYTE);
1646 else if (ISBUILTIN(BUILTIN_newarray_short)) {
1647 TYPECHECK_INT(curstack);
1648 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_SHORT);
1650 else if (ISBUILTIN(BUILTIN_newarray_int)) {
1651 TYPECHECK_INT(curstack);
1652 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_INT);
1654 else if (ISBUILTIN(BUILTIN_newarray_long)) {
1655 TYPECHECK_INT(curstack);
1656 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_LONG);
1659 builtindesc = builtin_desc;
1660 while (builtindesc->opcode && builtindesc->builtin
1661 != (functionptr) iptr->val.a) builtindesc++;
1662 if (!builtindesc->opcode) {
1663 dolog("Builtin not in table: %s",icmd_builtin_name((functionptr) iptr->val.a));
1664 panic("Internal error: builtin not found in table");
1666 TYPECHECK_ARGS1(builtindesc->type_s1);
1668 maythrow = true; /* XXX better safe than sorry */
1671 /****************************************/
1672 /* PRIMITIVE VARIABLE ACCESS */
1674 case ICMD_ILOAD: CHECK_ONEWORD(iptr->op1,TYPE_INT); break;
1675 case ICMD_FLOAD: CHECK_ONEWORD(iptr->op1,TYPE_FLOAT); break;
1676 case ICMD_IINC: CHECK_ONEWORD(iptr->op1,TYPE_INT); break;
1677 case ICMD_LLOAD: CHECK_TWOWORD(iptr->op1,TYPE_LONG); break;
1678 case ICMD_DLOAD: CHECK_TWOWORD(iptr->op1,TYPE_DOUBLE); break;
1680 case ICMD_FSTORE: STORE_ONEWORD(iptr->op1,TYPE_FLOAT); break;
1681 case ICMD_ISTORE: STORE_ONEWORD(iptr->op1,TYPE_INT); break;
1682 case ICMD_LSTORE: STORE_TWOWORD(iptr->op1,TYPE_LONG); break;
1683 case ICMD_DSTORE: STORE_TWOWORD(iptr->op1,TYPE_DOUBLE); break;
1685 /****************************************/
1686 /* INSTRUCTIONS WHICH SHOULD HAVE BEEN */
1687 /* REPLACED BY BUILTIN CALLS */
1691 case ICMD_ANEWARRAY:
1692 case ICMD_MONITORENTER:
1693 case ICMD_MONITOREXIT:
1695 /* XXX only check this in debug mode? */
1696 LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
1697 LOG("Should have been converted to builtin function call.");
1698 panic("Internal error: unexpected instruction encountered");
1701 /****************************************/
1702 /* UNCHECKED OPERATIONS */
1704 /* These ops have no input or output to be checked */
1705 /* (apart from the checks done in analyse_stack). */
1706 /* XXX only add cases for them in debug mode? */
1711 case ICMD_READONLY_ARG: /* XXX ? */
1712 case ICMD_CLEAR_ARGREN: /* XXX ? */
1715 case ICMD_CHECKASIZE:
1716 case ICMD_NULLCHECKPOP:
1720 /****************************************/
1721 /* ARITHMETIC AND CONVERSION */
1722 /* (These instructions are typechecked in analyse_stack.) */
1724 /* The following instructions may throw a runtime exception: */
1734 /* The following instructions never throw a runtime exception: */
1735 /* XXX only add cases for them in debug mode? */
1742 case ICMD_IFEQ_ICONST:
1743 case ICMD_IFNE_ICONST:
1744 case ICMD_IFLT_ICONST:
1745 case ICMD_IFGE_ICONST:
1746 case ICMD_IFGT_ICONST:
1747 case ICMD_IFLE_ICONST:
1748 case ICMD_ELSE_ICONST:
1770 case ICMD_IREM0X10001:
1771 case ICMD_LREM0X10001:
1774 case ICMD_IADDCONST:
1775 case ICMD_ISUBCONST:
1776 case ICMD_IMULCONST:
1777 case ICMD_IANDCONST:
1779 case ICMD_IXORCONST:
1780 case ICMD_ISHLCONST:
1781 case ICMD_ISHRCONST:
1782 case ICMD_IUSHRCONST:
1784 case ICMD_LADDCONST:
1785 case ICMD_LSUBCONST:
1786 case ICMD_LMULCONST:
1787 case ICMD_LANDCONST:
1789 case ICMD_LXORCONST:
1790 case ICMD_LSHLCONST:
1791 case ICMD_LSHRCONST:
1792 case ICMD_LUSHRCONST:
1809 case ICMD_INT2SHORT:
1812 case ICMD_LCMPCONST:
1833 /****************************************/
1836 LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
1837 panic("Missing ICMD code during typecheck");
1840 /* the output of this instruction becomes the current stack */
1843 /* reach exception handlers for this instruction */
1845 LOG("reaching exception handlers");
1847 while (handlers[i]) {
1848 tbptr = handlers[i]->handler;
1849 TYPECHECK_REACH(REACH_THROW); /* XXX jsr chain? */
1855 DOLOG(typeinfo_print_block(get_logfile(),curstack,numlocals,vtype,vinfo,(jsrchain) ? touched : NULL));
1860 } /* while instructions */
1862 LOG("instructions done");
1863 LOGSTR("RESULT=> ");
1864 DOLOG(typeinfo_print_block(get_logfile(),curstack,numlocals,vtype,vinfo,(jsrchain) ? touched : NULL));
1867 /* propagate stack and variables to the following block */
1868 if (!superblockend) {
1869 LOG("reaching following block");
1871 while (tbptr->flags == BBDELETED) {
1873 #ifdef TYPECHECK_DEBUG
1874 if ((tbptr-block) >= block_count)
1875 panic("Control flow falls off the last block");
1878 TYPECHECK_REACH(REACH_STD);
1881 } /* if block has to be checked */
1883 } /* while blocks */
1885 LOGIF(repeat,"repeat=true");
1888 #ifdef TYPECHECK_STATISTICS
1889 dolog("Typechecker did %4d iterations",count_iterations);
1892 #ifdef TYPECHECK_DEBUG
1893 for (i=0; i<block_count; ++i) {
1894 if (block[i].flags != BBDELETED
1895 && block[i].flags != BBUNDEF
1896 && block[i].flags != BBFINISHED
1897 && block[i].flags != BBTYPECHECK_UNDEF) /* typecheck may never reach
1898 * some exception handlers,
1901 LOG2("block L%03d has invalid flags after typecheck: %d",
1902 block[i].debug_nr,block[i].flags);
1903 panic("Invalid block flags after typecheck");
1908 /* Reset blocks we never reached */
1909 for (i=0; i<block_count; ++i) {
1910 if (block[i].flags == BBTYPECHECK_UNDEF)
1911 block[i].flags = BBFINISHED;
1914 LOGimp("exiting typecheck");
1919 #endif /* CACAO_TYPECHECK */
1922 * These are local overrides for various environment variables in Emacs.
1923 * Please do not remove this and leave it at the end of the file, where
1924 * Emacs will automagically detect them.
1925 * ---------------------------------------------------------------------
1928 * indent-tabs-mode: t