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 696 2003-12-06 20:10:05Z edwin $
33 #include "global.h" /* must be here because of CACAO_TYPECHECK */
35 #ifdef CACAO_TYPECHECK
42 #include "toolbox/loging.h"
43 #include "toolbox/memory.h"
45 #define TOUCHED_YES 0x01
46 #define TOUCHED_NO 0x02
47 #define TOUCHED_MAYBE (TOUCHED_YES | TOUCHED_NO)
53 /****************************************************************************/
55 /****************************************************************************/
57 #ifdef TYPECHECK_VERBOSE_OPT
58 bool typecheckverbose = false;
59 #define DOLOG(action) do { if (typecheckverbose) {action;} } while(0)
64 #ifdef TYPECHECK_VERBOSE
65 #define TYPECHECK_VERBOSE_IMPORTANT
66 #define LOG(str) DOLOG(log_text(str))
67 #define LOG1(str,a) DOLOG(dolog(str,a))
68 #define LOG2(str,a,b) DOLOG(dolog(str,a,b))
69 #define LOG3(str,a,b,c) DOLOG(dolog(str,a,b,c))
70 #define LOGIF(cond,str) DOLOG(do {if (cond) log_text(str);} while(0))
71 #define LOGINFO(info) DOLOG(do {typeinfo_print_short(stdout,info);printf("\n");} while(0))
72 #define LOGFLUSH DOLOG(fflush(stdout))
73 #define LOGNL DOLOG(printf("\n"))
74 #define LOGSTR(str) DOLOG(printf(str))
75 #define LOGSTR1(str,a) DOLOG(printf(str,a))
76 #define LOGSTR2(str,a,b) DOLOG(printf(str,a,b))
77 #define LOGSTR3(str,a,b,c) DOLOG(printf(str,a,b,c))
78 #define LOGSTRu(utf) DOLOG(utf_display(utf))
83 #define LOG3(str,a,b,c)
84 #define LOGIF(cond,str)
89 #define LOGSTR1(str,a)
90 #define LOGSTR2(str,a,b)
91 #define LOGSTR3(str,a,b,c)
94 #ifdef TYPECHECK_VERBOSE_IMPORTANT
95 #define LOGimp(str) DOLOG(log_text(str))
96 #define LOGimpSTR(str) DOLOG(printf(str))
97 #define LOGimpSTRu(utf) DOLOG(utf_display(utf))
100 #define LOGimpSTR(str)
101 #define LOGimpSTRu(utf)
104 #if defined(TYPECHECK_VERBOSE) || defined(TYPECHECK_VERBOSE_IMPORTANT)
108 typeinfo_print_locals(FILE *file,u1 *vtype,typeinfo *vinfo,u1 *touched,int num)
112 for (i=0; i<num; ++i) {
114 fprintf(file," %d%s=",i,
115 (touched[i]==TOUCHED_YES) ? "*"
116 : ((touched[i]==TOUCHED_NO) ? "" : "~"));
118 fprintf(file," %d=",i);
119 typeinfo_print_type(file,vtype[i],vinfo+i);
125 typeinfo_print_stack(FILE *file,stackptr stack)
128 typeinfo_print_type(file,stack->type,&stack->typeinfo);
130 if (stack) fprintf(file," ");
136 typeinfo_print_block(FILE *file,stackptr instack,
137 u1 *vtype,typeinfo *vinfo,u1 *touched)
139 fprintf(file,"Stack: ");
140 typeinfo_print_stack(file,instack);
141 fprintf(file," Locals:");
142 typeinfo_print_locals(file,vtype,vinfo,touched,maxlocals);
148 typeinfo_print_blocks(FILE *file,u1 *vtype,typeinfo *vinfo)
153 for (bi=0; bi<block_count; ++bi) {
154 fprintf(file,"%04d: (%3d) ",bi,block[bi].flags);
155 typeinfo_print_block(file,block[bi].instack,
156 vtype+maxlocals*bi,vinfo+maxlocals*bi,NULL);
159 /* for (j=0; j<block[bi].icount; ++j) { */
160 /* fprintf(file,"\t%s\n",icmd_names[block[bi].iinstr[j].opc]); */
163 show_icmd_block(block+bi);
169 /****************************************************************************/
170 /* INTERNAL DATA STRUCTURES */
171 /****************************************************************************/
173 typedef struct jsr_record jsr_record;
176 * For each basic block we store the chain of JSR instructions which
177 * were used to reach the block (usually zero or one). For more
178 * details on verifying JSR and RET instructions see the Java VM
181 * CAUTION: The fields starting with sbr_ are only valid for the
182 * jsr_record of the first block of the subroutine.
185 basicblock *target; /* target of the JSR instruction (first block of subroutine) */
186 jsr_record *next; /* for chaining in nested try ... finally */ /* XXX make it sbr_next? */
187 u1 *sbr_touched; /* specifies which variables the subroutine touches */
188 u1 *sbr_vtype; /* Types of local variables after RET */
189 typeinfo *sbr_vinfo; /* Types of local variables after RET */
190 u1 touched[1]; /* touched flags for local variables */
193 /****************************************************************************/
194 /* MACROS USED INTERNALLY IN typecheck() */
195 /****************************************************************************/
197 #define TOUCH_VARIABLE(num) do {if (jsrchain) touched[num] = TOUCHED_YES;} while (0)
198 #define TOUCH_TWOWORD(num) do {TOUCH_VARIABLE(num);TOUCH_VARIABLE((num)+1);} while (0)
200 /* XXX should check num in range? */
201 /* XXX invalidate two word variables on store in second half! */
202 #define STORE_TYPE(num,type) do {vtype[(num)] = (type); TOUCH_VARIABLE(num);} while(0)
203 #define STORE_INVALID(num) STORE_TYPE((num),TYPE_VOID)
204 #define STORE_PRIMITIVE(num,type) STORE_TYPE((num),(type))
205 #define STORE_TWOWORD(num,type) {STORE_PRIMITIVE((num),(type));STORE_INVALID((num)+1);}
207 #define CHECKVARTYPE(num,type) \
208 {if (vtype[(num)] != (type)) panic("Variable type mismatch"); TOUCH_VARIABLE(num);}
210 /* XXX maybe it's faster to copy always */
211 #define COPYTYPE(source,dest) \
212 {if ((source)->type == TYPE_ADR) \
213 TYPEINFO_COPY((source)->typeinfo,(dest)->typeinfo);}
215 #define ISBUILTIN(v) (iptr->val.a == (functionptr)(v))
217 /* TYPECHECK_COPYVARS: copy the types and typeinfos of the current local
218 * variables to the local variables of the target block.
220 * vtype......current local variable types
221 * vinfo......current local variable typeinfos
222 * ttype......local variable types of target block
223 * tinfo......local variable typeinfos of target block
224 * maxlocals..number of local variables
228 #define TYPECHECK_COPYVARS \
229 LOG("TYPECHECK_COPYVARS"); \
230 for (macro_i=0; macro_i<maxlocals; ++macro_i) { \
231 if ((ttype[macro_i] = vtype[macro_i]) == TYPE_ADR) \
232 TYPEINFO_CLONE(vinfo[macro_i],tinfo[macro_i]); \
235 /* TYPECHECK_MERGEVARS: merge the local variables of the target block
236 * with the current local variables.
238 * vtype......current local variable types
239 * vinfo......current local variable typeinfos
240 * ttype......local variable types of target block
241 * tinfo......local variable typeinfos of target block
242 * maxlocals..number of local variables
244 * changed....set to true if any typeinfo has changed
248 #define TYPECHECK_MERGEVARS \
249 LOG("TYPECHECK_MERGEVARS"); \
250 for (macro_i=0; macro_i<maxlocals; ++macro_i) { \
251 if ((ttype[macro_i] != TYPE_VOID) && (vtype[macro_i] != ttype[macro_i])) { \
252 LOG3("var %d: type %d + type %d = void",macro_i,ttype[macro_i],vtype[macro_i]); \
253 ttype[macro_i] = TYPE_VOID; \
255 } else if (ttype[macro_i] == TYPE_ADR) { \
256 if ( ((TYPEINFO_IS_PRIMITIVE(tinfo[macro_i])) ? 1 : 0) \
258 ((TYPEINFO_IS_PRIMITIVE(vinfo[macro_i])) ? 1 : 0)) { \
259 LOG1("var %d: primitive + reference merge",macro_i); \
260 ttype[macro_i] = TYPE_VOID; \
264 LOG1("var %d:",macro_i); \
265 LOGINFO(tinfo+macro_i); \
266 LOGINFO(vinfo+macro_i); \
267 changed |= typeinfo_merge(tinfo+macro_i,vinfo+macro_i); \
268 LOGINFO(tinfo+macro_i); \
269 LOGIF(changed,"vars have changed"); \
274 /* TYPECHECK_MERGEJSR:
278 * tbptr......target block
279 * changed....set to true if any typeinfo has changed
280 * maxlocals..number of local variables
281 * touched....current touched flags of local variables
283 * macro_i, jsrtemp, jsrtemp2
285 #define TYPECHECK_MERGEJSR \
287 LOG("TYPECHECK_MERGEJSR"); \
288 jsrtemp = jsrbuffer[tbptr-block]; \
289 jsrtemp2 = jsrchain; \
290 while (jsrtemp || jsrtemp2) { \
291 if (!jsrtemp || !jsrtemp2) \
292 panic("Merging JSR subroutines of different depth"); \
293 if (jsrtemp->target != jsrtemp2->target) \
294 panic("Merging different JSR subroutines"); \
295 jsrtemp = jsrtemp->next; \
296 jsrtemp2 = jsrtemp2->next; \
298 jsrtemp = jsrbuffer[tbptr-block]; \
300 for (macro_i=0; macro_i<maxlocals; ++macro_i) { \
301 jsrtemp->touched[i] |= touched[i]; \
304 /* TYPECHECK_COPYSTACK: copy the typeinfos of the current stack to
305 * the input stack of the target block.
307 * srcstack...current stack
308 * dststack...input stack of target block
310 #define TYPECHECK_COPYSTACK \
311 LOG("TYPECHECK_COPYSTACK"); \
313 LOG1("copy %d",srcstack->type); \
314 if (!dststack) panic("Stack depth mismatch"); \
315 if (srcstack->type != dststack->type) \
316 panic("Type mismatch on stack"); \
317 if (srcstack->type == TYPE_ADR) { \
318 TYPEINFO_CLONE(srcstack->typeinfo,dststack->typeinfo); \
320 dststack = dststack->prev; \
321 srcstack = srcstack->prev; \
323 if (dststack) panic("Stack depth mismatch");
325 /* TYPECHECK_MERGESTACK: merge the input stack of the target block
326 * with the current stack.
328 * srcstack...current stack
329 * dststack...input stack of target block
331 * changed....set to true if any typeinfo has changed
333 #define TYPECHECK_MERGESTACK \
334 LOG("TYPECHECK_MERGESTACK"); \
336 if (!dststack) panic("Stack depth mismatch"); \
337 if (srcstack->type != dststack->type) \
338 panic("Type mismatch on stack"); \
339 if (srcstack->type == TYPE_ADR) { \
340 LOGINFO(&dststack->typeinfo); \
341 LOGINFO(&srcstack->typeinfo); LOGFLUSH; \
342 changed |= typeinfo_merge(&dststack->typeinfo, \
343 &srcstack->typeinfo); \
344 LOGINFO(&dststack->typeinfo); \
345 LOG((changed)?"CHANGED!\n":"not changed.\n"); \
347 dststack = dststack->prev; \
348 srcstack = srcstack->prev; \
350 if (dststack) panic("Stack depth mismatch");
353 /* TYPECHECK_CHECK_JSR_CHAIN: checks if the target block is reached by
354 * the same JSR targets on all control paths.
357 * tbptr......target block
358 * jsrchain...current JSR target chain
359 * jsrbuffer..JSR target chain for each basic block
361 * panic if the JSR target chains don't match
365 #define TYPECHECK_CHECK_JSR_CHAIN \
367 jsrtemp = jsrbuffer[tbptr-block]; \
368 if (!jsrtemp) panic("non-subroutine called by JSR"); \
369 if (jsrtemp->target != tbptr) \
370 panic("Merging different JSR subroutines"); \
371 jsrtemp = jsrtemp->next; \
372 jsrtemp2 = jsrchain; \
373 while (jsrtemp || jsrtemp2) { \
374 if (!jsrtemp || !jsrtemp2) \
375 panic("Merging JSR subroutines of different depth"); \
376 if (jsrtemp->target != jsrtemp2->target) \
377 panic("Merging different JSR subroutines"); \
378 jsrtemp = jsrtemp->next; \
379 jsrtemp2 = jsrtemp2->next; \
382 /* TYPECHECK_ADD_JSR: add a JSR target to the current JSR target chain
383 * and store the resulting chain in the target block.
386 * jsrchain...current JSR target chain
387 * tbptr.....the basic block targeted by the JSR
388 * maxlocals..number of local variables
389 * jsrbuffer..JSR target chain for each basic block
393 #define TYPECHECK_ADD_JSR \
395 LOG1("adding JSR to block %04d",(tbptr)-block); \
396 jsrtemp = (jsr_record *) dump_alloc(sizeof(jsr_record)+(maxlocals-1)*sizeof(u1)); \
397 jsrtemp->target = (tbptr); \
398 jsrtemp->next = jsrchain; \
399 jsrtemp->sbr_touched = NULL; \
400 memset(&jsrtemp->touched,TOUCHED_NO,sizeof(u1)*maxlocals); \
401 jsrbuffer[tbptr-block] = jsrtemp; \
404 /* TYPECHECK_COPYJSR: copy the current JSR chain to the target block.
407 * chain......current JSR target chain
408 * tbptr.....the basic block targeted by the JSR
409 * maxlocals..number of local variables
410 * jsrbuffer..JSR target chain for each basic block
411 * touched....current touched flags of local variables
415 #define TYPECHECK_COPYJSR(chain) \
417 LOG("TYPECHECK_COPYJSR"); \
419 jsrtemp = (jsr_record *) dump_alloc(sizeof(jsr_record)+(maxlocals-1)*sizeof(u1)); \
420 jsrtemp->target = (chain)->target; \
421 jsrtemp->next = (chain)->next; \
422 jsrtemp->sbr_touched = NULL; \
423 memcpy(&jsrtemp->touched,touched,sizeof(u1)*maxlocals); \
424 jsrbuffer[tbptr-block] = jsrtemp; \
427 jsrbuffer[tbptr-block] = NULL; \
430 /* TYPECHECK_REACH: executed, when the target block (tbptr) can be reached
431 * from the current block (bptr). The types of local variables and
432 * stack slots are propagated to the target block.
434 * bptr.......current block
435 * tbptr......target block
436 * dst........current output stack pointer
437 * vtype......current local variable types
438 * vinfo......current local variable typeinfos
439 * jsrchain...current JSR target chain
440 * jsrbuffer..JSR target chain for each basic block
441 * way........in which way the block is reached (REACH_ constant)
442 * touched....current touched flags of local variables
444 * repeat.....changed to true if a block before the current
447 * ttype, tinfo, srcstack, dststack, changed, macro_i
449 #define TYPECHECK_REACH(way) \
450 LOG1("reaching block %04d",tbptr-block); \
452 dststack = tbptr->instack; \
453 ttype = vartype + maxlocals*(tbptr-block); \
454 tinfo = vartypeinfo + maxlocals*(tbptr-block); \
455 if (tbptr->flags == BBTYPECHECK_UNDEF) { \
456 /* This block is reached for the first time */ \
457 if (way == REACH_JSR) { \
459 TYPECHECK_COPYVARS; \
462 TYPECHECK_COPYJSR(jsrchain); \
463 TYPECHECK_COPYVARS; \
465 TYPECHECK_COPYSTACK; \
468 /* This block has been reached before */ \
470 if (way == REACH_JSR) \
471 TYPECHECK_CHECK_JSR_CHAIN; \
473 TYPECHECK_MERGEJSR; \
474 LOGIF(changed,"changed jsr"); \
475 TYPECHECK_MERGEVARS; \
476 LOGIF(changed,"changed vars"); \
477 TYPECHECK_MERGESTACK; \
478 LOGIF(changed,"changed stack"); \
482 tbptr->flags = BBTYPECHECK_REACHED; \
483 if (tbptr <= bptr) {repeat = true; LOG("MUST REPEAT!");} \
486 /****************************************************************************/
488 /****************************************************************************/
490 #define MAXPARAMS 255
492 /* typecheck is called directly after analyse_stack */
496 int b_count, b_index;
497 stackptr curstack; /* input stack top for current instruction */
498 stackptr srcstack; /* source stack for copying and merging */
499 stackptr dststack; /* target stack for copying and merging */
500 int opcode, macro_i, len, i;
501 bool superblockend; /* true if no fallthrough to next block */
502 bool repeat; /* if true, blocks are iterated over again */
504 instruction *iptr = instr; /* pointer to current instruction */
505 basicblock *bptr; /* pointer to current basic block */
507 u1 *vartype; /* type of each local for each basic block */
508 typeinfo *vartypeinfo; /* type of each local for each basic block */
509 u1 *vtype; /* type of each local for current instruction */
510 typeinfo *vinfo; /* type of each local for current instruction */
511 u1 *ttype; /* temporary pointer */
512 typeinfo *tinfo; /* temporary pointer */
513 typeinfo tempinfo; /* temporary */
514 int returntype; /* return type of current method */
515 typeinfo returntypeinfo; /* typeinfo for return type */
516 u1 *ptype; /* parameter types of called method */
517 typeinfo *pinfo; /* parameter typeinfos of called method */
518 int rtype; /* return type of called method */
519 typeinfo rinfo; /* typeinfo for return type of called method */
520 stackptr dst; /* output stack of current instruction */
521 int changeddepth; /* depth to which the stack has changed */ /* XXX */
522 bool fulltypecheck; /* false == check only changed types */ /* XXX */
523 basicblock **tptr; /* pointer into target list of switch instructions */
524 jsr_record **jsrbuffer; /* JSR target chain for each basic block */
525 jsr_record *jsrchain; /* JSR chain for current block */
526 jsr_record *jsrtemp,*jsrtemp2,*jsrold; /* temporary variables */
527 jsr_record *subroutine; /* jsr_record of the current subroutine */
528 u1 *touched; /* touched flags for local variables */
530 LOGSTR("\n==============================================================================\n");
531 DOLOG(show_icmd_method());
532 LOGSTR("\n==============================================================================\n");
533 LOGimpSTR("Entering typecheck: ");
534 LOGimpSTRu(method->name);
536 LOGimpSTRu(method->descriptor);
537 LOGimpSTR(" (class ");
538 LOGimpSTRu(method->class->name);
541 /* XXX allocate buffers for method arguments */
542 ptype = DMNEW(u1,MAXPARAMS);
543 pinfo = DMNEW(typeinfo,MAXPARAMS);
545 LOG("Buffer allocated.\n");
547 /* reset all BBFINISHED blocks to BBTYPECHECK_UNDEF. */
548 b_count = block_count;
550 while (--b_count >= 0) {
551 #ifdef TYPECHECK_DEBUG
552 if (bptr->flags != BBFINISHED && bptr->flags != BBDELETED
553 && bptr->flags != BBUNDEF)
556 LOGSTR1("block flags: %d\n",bptr->flags); LOGFLUSH;
557 panic("Internal error: Unexpected block flags in typecheck()");
560 if (bptr->flags >= BBFINISHED) {
561 bptr->flags = BBTYPECHECK_UNDEF;
566 /* The first block is always reached */
567 if (block_count && block[0].flags == BBTYPECHECK_UNDEF)
568 block[0].flags = BBTYPECHECK_REACHED;
570 LOG("Blocks reset.\n");
572 /* allocate the buffers for local variables */
573 vartype = DMNEW(u1,maxlocals * (block_count+1));
574 vartypeinfo = DMNEW(typeinfo,maxlocals * (block_count+1));
575 touched = DMNEW(u1,maxlocals);
576 vtype = vartype + maxlocals * block_count;
577 vinfo = vartypeinfo + maxlocals * block_count;
578 memset(vartype,TYPE_VOID,maxlocals * (block_count+1) * sizeof(typeinfo));
579 memset(vartypeinfo,0,maxlocals * (block_count+1) * sizeof(typeinfo));
581 LOG("Variable buffer initialized.\n");
583 /* allocate the buffer for storing JSR target chains */
584 jsrbuffer = DMNEW(jsr_record*,block_count);
585 memset(jsrbuffer,0,block_count * sizeof(jsr_record*));
588 LOG("jsrbuffer initialized.\n");
590 /* initialize the variable types of the first block */
591 /* to the types of the arguments */
595 /* if this is an instance method initialize the "this" ref type */
596 if (!(method->flags & ACC_STATIC)) {
597 *ttype++ = TYPE_ADDRESS;
598 TYPEINFO_INIT_CLASSINFO(*tinfo,class);
602 LOG("'this' argument set.\n");
604 /* the rest of the arguments and the return type */
605 typeinfo_init_from_method_args(method->descriptor,ttype,tinfo,
606 maxlocals - (tinfo-vartypeinfo),
607 true, /* two word types use two slots */
608 &returntype,&returntypeinfo);
610 LOG("Arguments set.\n");
612 /* loop while there are still blocks to be checked */
613 fulltypecheck = true; /* XXX */
618 b_count = block_count;
621 while (--b_count >= 0) {
622 LOGSTR1("---- BLOCK %04d, ",bptr-block);
623 LOGSTR1("blockflags: %d\n",bptr->flags);
626 if (bptr->flags == BBTYPECHECK_REACHED) {
627 LOGSTR1("\n---- BLOCK %04d ------------------------------------------------\n",bptr-block);
630 superblockend = false;
631 bptr->flags = BBFINISHED;
632 b_index = bptr - block;
634 /* init stack at the start of this block */
635 curstack = bptr->instack;
637 /* init variable types at the start of this block */
638 for (i=0; i<maxlocals; ++i) {
639 vtype[i] = vartype[maxlocals*b_index + i];
640 TYPEINFO_COPY(vartypeinfo[maxlocals*b_index + i],vinfo[i]);
643 /* init JSR target chain */
644 if ((jsrchain = jsrbuffer[b_index]) != NULL) {
645 #ifdef TYPECHECK_VERBOSE
646 if (typecheckverbose) {
647 LOGSTR("jsr chain:");
650 LOGSTR1(" L%03d",jsrtemp->target->debug_nr);
651 jsrtemp = jsrtemp->next;
658 subroutine = jsrbuffer[jsrchain->target - block];
659 memcpy(touched,jsrchain->touched,sizeof(u1)*maxlocals);
663 #ifdef TYPECHECK_VERBOSE
664 if (typecheckverbose) {
665 if (subroutine) {LOGSTR1("subroutine L%03d\n",subroutine->target->debug_nr);LOGFLUSH;}
666 typeinfo_print_block(stdout,curstack,vtype,vinfo,(jsrchain) ? touched : NULL);
671 /* loop over the instructions */
675 DOLOG(show_icmd(iptr,false));
684 /****************************************/
685 /* STACK MANIPULATIONS */
687 /* We just need to copy the typeinfo */
688 /* for slots containing addresses. */
691 COPYTYPE(curstack,dst);
695 COPYTYPE(curstack,dst);
696 COPYTYPE(curstack,dst-2);
697 COPYTYPE(curstack->prev,dst-1);
701 COPYTYPE(curstack,dst);
702 COPYTYPE(curstack,dst-3);
703 COPYTYPE(curstack->prev,dst-1);
704 COPYTYPE(curstack->prev->prev,dst-2);
708 COPYTYPE(curstack,dst);
709 COPYTYPE(curstack->prev,dst-1);
713 COPYTYPE(curstack,dst);
714 COPYTYPE(curstack->prev,dst-1);
715 COPYTYPE(curstack,dst-3);
716 COPYTYPE(curstack->prev,dst-4);
717 COPYTYPE(curstack->prev->prev,dst-2);
721 COPYTYPE(curstack,dst);
722 COPYTYPE(curstack->prev,dst-1);
723 COPYTYPE(curstack,dst-4);
724 COPYTYPE(curstack->prev,dst-5);
725 COPYTYPE(curstack->prev->prev,dst-2);
726 COPYTYPE(curstack->prev->prev->prev,dst-3);
730 COPYTYPE(curstack,dst-1);
731 COPYTYPE(curstack->prev,dst);
734 /* XXX only add these cases in debug mode? */
741 /****************************************/
742 /* LOADING ADDRESS FROM VARIABLE */
745 CHECKVARTYPE(iptr->op1,TYPE_ADR);
747 /* loading a returnAddress is not allowed */
748 if (TYPEINFO_IS_PRIMITIVE(vinfo[iptr->op1]))
749 panic("illegal instruction: ALOAD loading returnAddress");
751 TYPEINFO_COPY(vinfo[iptr->op1],dst->typeinfo);
754 /****************************************/
755 /* STORING ADDRESS TO VARIABLE */
758 /* TYPE_ADR has already been checked. */
759 STORE_TYPE(iptr->op1,TYPE_ADDRESS);
760 TYPEINFO_COPY(curstack->typeinfo,vinfo[iptr->op1]);
763 /****************************************/
764 /* LOADING ADDRESS FROM ARRAY */
767 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(curstack->prev->typeinfo))
768 panic("illegal instruction: AALOAD on non-reference array");
770 typeinfo_init_component(&curstack->prev->typeinfo,&dst->typeinfo);
773 /****************************************/
774 /* STORING ADDRESS TO ARRAY */
777 /* XXX also handled by builtin3 */
778 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(curstack->prev->prev->typeinfo))
779 panic("illegal instruction: AASTORE to non-reference array");
783 typeinfo_init_component(&curstack->prev->prev->typeinfo,&tempinfo);
784 if (!typeinfo_is_assignable(&curstack->typeinfo,&tempinfo))
785 panic("illegal instruction: AASTORE to incompatible type");
789 /****************************************/
793 if (!TYPEINFO_IS_REFERENCE(curstack->prev->typeinfo))
794 panic("illegal instruction: PUTFIELD on non-reference");
795 if (TYPEINFO_IS_ARRAY(curstack->prev->typeinfo)) /* XXX arraystub */
796 panic("illegal instruction: PUTFIELD on array");
807 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
808 panic("illegal instruction: GETFIELD on non-reference");
809 if (TYPEINFO_IS_ARRAY(curstack->typeinfo))
810 panic("illegal instruction: GETFIELD on array");
813 fieldinfo *fi = (fieldinfo *)(iptr->val.a);
814 /* XXX check non-static? */
815 if (dst->type == TYPE_ADR) {
816 TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi);
819 TYPEINFO_INIT_PRIMITIVE(dst->typeinfo);
826 fieldinfo *fi = (fieldinfo *)(iptr->val.a);
827 /* XXX check static? */
828 if (dst->type == TYPE_ADR) {
829 TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi);
832 TYPEINFO_INIT_PRIMITIVE(dst->typeinfo);
837 /****************************************/
838 /* PRIMITIVE ARRAY ACCESS */
840 case ICMD_ARRAYLENGTH:
841 /* XXX should this also work on arraystubs? */
842 if (!TYPEINFO_MAYBE_ARRAY(curstack->typeinfo))
843 panic("illegal instruction: ARRAYLENGTH on non-array");
847 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_BOOLEAN)
848 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_BYTE))
849 panic("Array type mismatch");
852 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_CHAR))
853 panic("Array type mismatch");
856 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_DOUBLE))
857 panic("Array type mismatch");
860 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_FLOAT))
861 panic("Array type mismatch");
864 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_INT))
865 panic("Array type mismatch");
868 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_SHORT))
869 panic("Array type mismatch");
872 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_LONG))
873 panic("Array type mismatch");
877 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_BOOLEAN)
878 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_BYTE))
879 panic("Array type mismatch");
882 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_CHAR))
883 panic("Array type mismatch");
886 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_DOUBLE))
887 panic("Array type mismatch");
890 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_FLOAT))
891 panic("Array type mismatch");
894 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_INT))
895 panic("Array type mismatch");
898 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_SHORT))
899 panic("Array type mismatch");
902 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_LONG))
903 panic("Array type mismatch");
906 /****************************************/
907 /* OPERATIONS WITH UNCHECKED INPUT */
910 /* returnAddress is not allowed */
911 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
912 panic("Illegal instruction: INSTANCEOF on non-reference");
914 /* XXX check if the cast can be done statically */
915 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,(classinfo *)iptr[0].val.a);
919 case ICMD_INSTANCEOF:
920 /* returnAddress is not allowed */
921 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
922 panic("Illegal instruction: INSTANCEOF on non-reference");
928 if (iptr->val.a == NULL)
929 TYPEINFO_INIT_NULLTYPE(dst->typeinfo)
931 /* XXX constants for builtin functions */
932 /* string constants */
933 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,class_java_lang_String);
936 /****************************************/
937 /* BRANCH INSTRUCTIONS */
940 superblockend = true;
970 tbptr = (basicblock *) iptr->target;
972 /* propagate stack and variables to the target block */
973 TYPECHECK_REACH(REACH_STD);
977 /****************************************/
980 case ICMD_TABLESWITCH:
982 s4 *s4ptr = iptr->val.a;
983 s4ptr++; /* skip default */
984 i = *s4ptr++; /* low */
985 i = *s4ptr++ - i + 2; /* +1 for default target */
987 goto switch_instruction_tail;
989 case ICMD_LOOKUPSWITCH:
991 s4 *s4ptr = iptr->val.a;
992 s4ptr++; /* skip default */
993 i = *s4ptr++ + 1; /* count +1 for default target */
995 switch_instruction_tail:
996 tptr = (basicblock **)iptr->target;
1000 LOG2("target %d is block %04d",(tptr-(basicblock **)iptr->target)-1,tbptr-block);
1001 TYPECHECK_REACH(REACH_STD);
1004 superblockend = true;
1007 /****************************************/
1008 /* RETURNS AND THROW */
1011 TYPEINFO_INIT_CLASSINFO(tempinfo,class_java_lang_Throwable);
1012 if (!typeinfo_is_assignable(&curstack->typeinfo,&tempinfo))
1013 panic("illegal instruction: ATHROW on non-Throwable");
1014 superblockend = true;
1018 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1019 panic("illegal instruction: ARETURN on non-reference");
1021 if (returntype != TYPE_ADDRESS
1022 || !typeinfo_is_assignable(&curstack->typeinfo,&returntypeinfo))
1023 panic("Return type mismatch");
1025 superblockend = true;
1029 if (returntype != TYPE_INT)
1030 panic("Return type mismatch");
1031 superblockend = true;
1034 if (returntype != TYPE_LONG)
1035 panic("Return type mismatch");
1036 superblockend = true;
1039 if (returntype != TYPE_FLOAT)
1040 panic("Return type mismatch");
1041 superblockend = true;
1044 if (returntype != TYPE_DOUBLE)
1045 panic("Return type mismatch");
1046 superblockend = true;
1049 if (returntype != TYPE_VOID)
1050 panic("Return type mismatch");
1051 superblockend = true;
1054 /****************************************/
1055 /* SUBROUTINE INSTRUCTIONS */
1060 /* XXX This is a dirty hack. It is needed
1061 * because of the special handling of ICMD_JSR in stack.c
1063 dst = (stackptr) iptr->val.a;
1065 /* push return address */
1066 TYPEINFO_INIT_PRIMITIVE(dst->typeinfo);
1068 LOG("reaching block...");
1070 /* add the target to the JSR target chain and */
1071 /* propagate stack and variables to the target block */
1072 tbptr = (basicblock *) iptr->target;
1073 TYPECHECK_REACH(REACH_JSR);
1075 /* set dst to the stack after the subroutine execution */
1076 /* XXX We assume (as in stack.c) that the
1077 * subroutine returns the stack as it was
1078 * before the JSR instruction. Is this
1083 /* Find the jsr_record of the called subroutine */
1084 jsrtemp = jsrbuffer[tbptr - block];
1086 /* Check if we already calculated (at least
1087 * for one RET) which variables the
1088 * subroutine touches.
1090 if (jsrtemp->sbr_touched) {
1091 /* Calculate the local variables after the subroutine call */
1092 for (i=0; i<maxlocals; ++i)
1093 if (jsrtemp->sbr_touched[i] != TOUCHED_NO) {
1095 if ((vtype[i] = jsrtemp->sbr_vtype[i]) == TYPE_ADR)
1096 TYPEINFO_CLONE(jsrtemp->sbr_vinfo[i],vinfo[i]);
1099 /* continue after the JSR call */
1100 superblockend = false;
1103 /* We cannot proceed until the subroutine has been typechecked. */
1104 /* XXX actually we would not have to check this block again */
1105 bptr->flags = BBTYPECHECK_REACHED;
1107 superblockend = true;
1112 /* check returnAddress variable */
1113 CHECKVARTYPE(iptr->op1,TYPE_ADR);
1115 if (!TYPEINFO_IS_PRIMITIVE(vinfo[iptr->op1]))
1116 panic("illegal instruction: RET using non-returnAddress variable");
1118 /* check if we are inside a subroutine */
1120 panic("RET outside of subroutine");
1122 /* determine which variables are touched by this subroutine */
1123 /* and their types */
1124 if (subroutine->sbr_touched) {
1125 for (i=0; i<maxlocals; ++i)
1126 subroutine->sbr_touched[i] |= touched[i];
1127 ttype = subroutine->sbr_vtype;
1128 tinfo = subroutine->sbr_vinfo;
1129 TYPECHECK_MERGEVARS;
1132 subroutine->sbr_touched = DMNEW(u1,maxlocals);
1133 memcpy(subroutine->sbr_touched,touched,sizeof(u1)*maxlocals);
1134 subroutine->sbr_vtype = DMNEW(u1,maxlocals);
1135 memcpy(subroutine->sbr_vtype,vtype,sizeof(u1)*maxlocals);
1136 subroutine->sbr_vinfo = DMNEW(typeinfo,maxlocals);
1137 for (i=0; i<maxlocals; ++i)
1138 if (vtype[i] == TYPE_ADR)
1139 TYPEINFO_CLONE(vinfo[i],subroutine->sbr_vinfo[i]);
1142 LOGSTR("subroutine touches:");
1143 DOLOG(typeinfo_print_locals(stdout,subroutine->sbr_vtype,subroutine->sbr_vinfo,
1144 subroutine->sbr_touched,maxlocals));
1147 /* reach blocks after JSR statements */
1148 for (i=0; i<block_count; ++i) {
1150 if (tbptr->iinstr[tbptr->icount - 1].opc != ICMD_JSR)
1152 if ((basicblock*) tbptr->iinstr[tbptr->icount - 1].target != jsrold->target)
1156 LOG1("RET reaches block %04d",tbptr-block);
1158 /*TYPECHECK_REACH(REACH_RET);*/
1161 superblockend = true;
1164 /****************************************/
1167 case ICMD_INVOKEVIRTUAL:
1168 case ICMD_INVOKESPECIAL:
1169 case ICMD_INVOKESTATIC:
1170 case ICMD_INVOKEINTERFACE:
1172 /* XXX check access rights */
1174 methodinfo *mi = (methodinfo*) iptr->val.a;
1175 /* XXX might use dst->typeinfo directly if non void */
1176 typeinfo_init_from_method_args(mi->descriptor,ptype,pinfo,MAXPARAMS,false,
1179 /* XXX compare rtype and dst->type? */
1180 if (rtype != TYPE_VOID) {
1181 TYPEINFO_COPY(rinfo,dst->typeinfo);
1186 case ICMD_MULTIANEWARRAY:
1187 /* check the array lengths on the stack */
1189 if (i<1) panic("MULTIANEWARRAY with dimensions < 1");
1190 srcstack = curstack;
1193 panic("MULTIANEWARRAY missing array length");
1194 if (srcstack->type != TYPE_INT)
1195 panic("MULTIANEWARRAY using non-int as array length");
1196 srcstack = srcstack->prev;
1199 /* set the array type of the result */
1200 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,((vftbl *)iptr[0].val.a)->class);
1204 if (ISBUILTIN(asm_builtin_aastore)) {
1205 /* XXX also handled by ICMD_AASTORE */
1206 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(curstack->prev->prev->typeinfo))
1207 panic("illegal instruction: AASTORE to non-reference array");
1211 typeinfo_init_component(&curstack->prev->prev->typeinfo,&tempinfo);
1212 if (!typeinfo_is_assignable(&curstack->typeinfo,&tempinfo))
1213 panic("illegal instruction: AASTORE to incompatible type");
1216 /* XXX check for missed builtins in debug mode? */
1221 #if defined(__I386__)
1222 ISBUILTIN(asm_builtin_newarray)
1224 ISBUILTIN(builtin_newarray)
1228 if (iptr[-1].opc != ICMD_ACONST)
1229 panic("illegal instruction: builtin_newarray without classinfo");
1230 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,((vftbl *)iptr[-1].val.a)->class);
1232 else if (ISBUILTIN(asm_builtin_checkarraycast)) {
1233 if (iptr[-1].opc != ICMD_ACONST)
1234 panic("illegal instruction: asm_builtin_checkarraycast without classinfo");
1235 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,((vftbl *)iptr[-1].val.a)->class);
1237 /* XXX check for missed builtins in debug mode? */
1241 if (ISBUILTIN(builtin_new)) {
1242 if (iptr[-1].opc != ICMD_ACONST)
1243 panic("illegal instruction: builtin_new without classinfo");
1244 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,(classinfo *)iptr[-1].val.a);
1246 else if (ISBUILTIN(builtin_newarray_boolean)) {
1247 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BOOLEAN);
1249 else if (ISBUILTIN(builtin_newarray_char)) {
1250 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_CHAR);
1252 else if (ISBUILTIN(builtin_newarray_float)) {
1253 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_FLOAT);
1255 else if (ISBUILTIN(builtin_newarray_double)) {
1256 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_DOUBLE);
1258 else if (ISBUILTIN(builtin_newarray_byte)) {
1259 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BYTE);
1261 else if (ISBUILTIN(builtin_newarray_short)) {
1262 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_SHORT);
1264 else if (ISBUILTIN(builtin_newarray_int)) {
1265 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_INT);
1267 else if (ISBUILTIN(builtin_newarray_long)) {
1268 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_LONG);
1270 /* XXX check for missed builtins in debug mode? */
1273 /****************************************/
1274 /* PRIMITIVE VARIABLE ACCESS */
1276 case ICMD_ILOAD: CHECKVARTYPE(iptr->op1,TYPE_INT); break;
1277 case ICMD_LLOAD: CHECKVARTYPE(iptr->op1,TYPE_LONG); break;
1278 case ICMD_FLOAD: CHECKVARTYPE(iptr->op1,TYPE_FLOAT); break;
1279 case ICMD_DLOAD: CHECKVARTYPE(iptr->op1,TYPE_DOUBLE); break;
1280 case ICMD_IINC: CHECKVARTYPE(iptr->op1,TYPE_INT); /*TOUCH_VARIABLE(iptr->op1);*/ break;
1282 case ICMD_FSTORE: STORE_PRIMITIVE(iptr->op1,TYPE_FLOAT); break;
1283 case ICMD_ISTORE: STORE_PRIMITIVE(iptr->op1,TYPE_INT); break;
1284 case ICMD_LSTORE: STORE_TWOWORD(iptr->op1,TYPE_LONG); break;
1285 case ICMD_DSTORE: STORE_TWOWORD(iptr->op1,TYPE_DOUBLE); break;
1287 /****************************************/
1288 /* INSTRUCTIONS WHICH SHOULD HAVE BEEN */
1289 /* REPLACED BY BUILTIN CALLS */
1293 case ICMD_ANEWARRAY:
1294 case ICMD_MONITORENTER:
1295 case ICMD_MONITOREXIT:
1296 /* XXX only check this in debug mode? */
1297 LOGSTR2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
1298 panic("Internal error: unexpected instruction encountered");
1301 /****************************************/
1302 /* UNCHECKED OPERATIONS */
1304 /* These ops have no input or output to be checked */
1305 /* (apart from the checks done in analyse_stack). */
1306 /* XXX only add cases for them in debug mode? */
1309 case ICMD_CHECKASIZE: /* XXX ? */
1310 case ICMD_NULLCHECKPOP: /* XXX ? */
1311 case ICMD_READONLY_ARG: /* XXX ? */
1312 case ICMD_CLEAR_ARGREN: /* XXX ? */
1315 /****************************************/
1316 /* ARITHMETIC AND CONVERSION */
1318 /* These instructions are typechecked in analyse_stack. */
1319 /* XXX only add cases for them in debug mode? */
1345 case ICMD_IREM0X10001:
1346 case ICMD_LREM0X10001:
1349 case ICMD_IADDCONST:
1350 case ICMD_ISUBCONST:
1351 case ICMD_IMULCONST:
1352 case ICMD_IANDCONST:
1354 case ICMD_IXORCONST:
1355 case ICMD_ISHLCONST:
1356 case ICMD_ISHRCONST:
1357 case ICMD_IUSHRCONST:
1359 case ICMD_LADDCONST:
1360 case ICMD_LSUBCONST:
1361 case ICMD_LMULCONST:
1362 case ICMD_LANDCONST:
1364 case ICMD_LXORCONST:
1365 case ICMD_LSHLCONST:
1366 case ICMD_LSHRCONST:
1367 case ICMD_LUSHRCONST:
1371 case ICMD_LCMPCONST:
1404 case ICMD_INT2SHORT:
1411 case ICMD_IFEQ_ICONST:
1412 case ICMD_IFNE_ICONST:
1413 case ICMD_IFLT_ICONST:
1414 case ICMD_IFGE_ICONST:
1415 case ICMD_IFGT_ICONST:
1416 case ICMD_IFLE_ICONST:
1417 case ICMD_ELSE_ICONST:
1421 /****************************************/
1424 LOGSTR2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
1425 panic("Missing ICMD code during typecheck");
1428 /* the output of this instruction becomes the current stack */
1432 } /* while instructions */
1434 LOG("instructions done");
1435 LOGSTR("RESULT=> ");
1436 DOLOG(typeinfo_print_block(stdout,curstack,vtype,vinfo,(jsrchain) ? touched : NULL));
1439 /* propagate stack and variables to the following block */
1440 if (!superblockend) {
1441 LOG("reaching following block");
1443 while (tbptr->flags == BBDELETED) {
1445 #ifdef TYPECHECK_DEBUG
1446 if ((tbptr-block) >= block_count)
1447 panic("Control flow falls off the last block");
1450 TYPECHECK_REACH(REACH_STD);
1453 } /* if block has to be checked */
1455 } /* while blocks */
1457 /* the following iterations only check if any types changed */
1458 fulltypecheck = false; /* XXX */
1460 LOGIF(repeat,"repeat=true");
1463 /* XXX reset BB... to BBFINISHED */
1465 /* XXX free vartype */
1466 /* XXX free vartypeinfo */
1467 /* XXX free buffers for method arguments. */
1469 /* XXX add debug check if all non-dead blocks have been checked */
1471 LOGimp("exiting typecheck");
1476 #endif /* CACAO_TYPECHECK */