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 719 2003-12-08 14:26: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)
49 #define REACH_STD 0 /* reached by branch or fallthrough */
50 #define REACH_JSR 1 /* reached by JSR */
51 #define REACH_RET 2 /* reached by RET */ /* XXX ? */
52 #define REACH_THROW 3 /* reached by THROW (exception handler) */
54 /****************************************************************************/
56 /****************************************************************************/
58 #ifdef TYPECHECK_VERBOSE_OPT
59 bool typecheckverbose = false;
60 #define DOLOG(action) do { if (typecheckverbose) {action;} } while(0)
65 #ifdef TYPECHECK_VERBOSE
66 #define TYPECHECK_VERBOSE_IMPORTANT
67 #define LOG(str) DOLOG(log_text(str))
68 #define LOG1(str,a) DOLOG(dolog(str,a))
69 #define LOG2(str,a,b) DOLOG(dolog(str,a,b))
70 #define LOG3(str,a,b,c) DOLOG(dolog(str,a,b,c))
71 #define LOGIF(cond,str) DOLOG(do {if (cond) log_text(str);} while(0))
72 #define LOGINFO(info) DOLOG(do {typeinfo_print_short(get_logfile(),info);log_plain("\n");} while(0))
73 #define LOGFLUSH DOLOG(fflush(get_logfile()))
74 #define LOGNL DOLOG(log_plain("\n"))
75 #define LOGSTR(str) DOLOG(dolog_plain(str))
76 #define LOGSTR1(str,a) DOLOG(dolog_plain(str,a))
77 #define LOGSTR2(str,a,b) DOLOG(dolog_plain(str,a,b))
78 #define LOGSTR3(str,a,b,c) DOLOG(dolog_plain(str,a,b,c))
79 #define LOGSTRu(utf) DOLOG(log_plain_utf(utf))
84 #define LOG3(str,a,b,c)
85 #define LOGIF(cond,str)
90 #define LOGSTR1(str,a)
91 #define LOGSTR2(str,a,b)
92 #define LOGSTR3(str,a,b,c)
96 #ifdef TYPECHECK_VERBOSE_IMPORTANT
97 #define LOGimp(str) DOLOG(log_text(str))
98 #define LOGimpSTR(str) DOLOG(dolog_plain(str))
99 #define LOGimpSTRu(utf) DOLOG(log_plain_utf(utf))
102 #define LOGimpSTR(str)
103 #define LOGimpSTRu(utf)
106 #if defined(TYPECHECK_VERBOSE) || defined(TYPECHECK_VERBOSE_IMPORTANT)
110 typeinfo_print_locals(FILE *file,u1 *vtype,typeinfo *vinfo,u1 *touched,int num)
114 for (i=0; i<num; ++i) {
116 fprintf(file," %d%s=",i,
117 (touched[i]==TOUCHED_YES) ? "*"
118 : ((touched[i]==TOUCHED_NO) ? "" : "~"));
120 fprintf(file," %d=",i);
121 typeinfo_print_type(file,vtype[i],vinfo+i);
127 typeinfo_print_stack(FILE *file,stackptr stack)
130 typeinfo_print_type(file,stack->type,&stack->typeinfo);
132 if (stack) fprintf(file," ");
138 typeinfo_print_block(FILE *file,stackptr instack,
139 int vnum,u1 *vtype,typeinfo *vinfo,u1 *touched)
141 fprintf(file,"Stack: ");
142 typeinfo_print_stack(file,instack);
143 fprintf(file," Locals:");
144 typeinfo_print_locals(file,vtype,vinfo,touched,vnum);
150 typeinfo_print_blocks(FILE *file,int vnum,u1 *vtype,typeinfo *vinfo)
155 for (bi=0; bi<block_count; ++bi) {
156 fprintf(file,"%04d: (%3d) ",bi,block[bi].flags);
157 typeinfo_print_block(file,block[bi].instack,
158 vnum,vtype+vnum*bi,vinfo+vnum*bi,NULL);
161 /* for (j=0; j<block[bi].icount; ++j) { */
162 /* fprintf(file,"\t%s\n",icmd_names[block[bi].iinstr[j].opc]); */
165 show_icmd_block(block+bi);
171 /****************************************************************************/
172 /* INTERNAL DATA STRUCTURES */
173 /****************************************************************************/
175 typedef struct jsr_record jsr_record;
178 * For each basic block we store the chain of JSR instructions which
179 * were used to reach the block (usually zero or one). For more
180 * details on verifying JSR and RET instructions see the Java VM
183 * CAUTION: The fields starting with sbr_ are only valid for the
184 * jsr_record of the first block of the subroutine.
187 basicblock *target; /* target of the JSR instruction (first block of subroutine) */
188 jsr_record *next; /* for chaining in nested try ... finally */ /* XXX make it sbr_next? */
189 u1 *sbr_touched; /* specifies which variables the subroutine touches */
190 u1 *sbr_vtype; /* Types of local variables after RET */
191 typeinfo *sbr_vinfo; /* Types of local variables after RET */
192 u1 touched[1]; /* touched flags for local variables */
195 /****************************************************************************/
196 /* MACROS USED INTERNALLY IN typecheck() */
197 /****************************************************************************/
199 #define TOUCH_VARIABLE(num) do {if (jsrchain) touched[num] = TOUCHED_YES;} while (0)
200 #define TOUCH_TWOWORD(num) do {TOUCH_VARIABLE(num);TOUCH_VARIABLE((num)+1);} while (0)
202 /* XXX should check num in range? */
203 /* XXX invalidate two word variables on store in second half! */
204 #define STORE_TYPE(num,type) do {vtype[(num)] = (type); TOUCH_VARIABLE(num);} while(0)
205 #define STORE_INVALID(num) STORE_TYPE((num),TYPE_VOID)
206 #define STORE_PRIMITIVE(num,type) STORE_TYPE((num),(type))
207 #define STORE_TWOWORD(num,type) {STORE_PRIMITIVE((num),(type));STORE_INVALID((num)+1);}
209 #define CHECKVARTYPE(num,type) \
210 {if (vtype[(num)] != (type)) panic("Variable type mismatch"); TOUCH_VARIABLE(num);}
212 /* XXX maybe it's faster to copy always */
213 #define COPYTYPE(source,dest) \
214 {if ((source)->type == TYPE_ADR) \
215 TYPEINFO_COPY((source)->typeinfo,(dest)->typeinfo);}
217 #define ISBUILTIN(v) (iptr->val.a == (functionptr)(v))
219 /* TYPECHECK_COPYVARS: copy the types and typeinfos of the current local
220 * variables to the local variables of the target block.
222 * vtype......current local variable types
223 * vinfo......current local variable typeinfos
224 * ttype......local variable types of target block
225 * tinfo......local variable typeinfos of target block
226 * numlocals..number of local variables
230 #define TYPECHECK_COPYVARS \
232 LOG("TYPECHECK_COPYVARS"); \
233 for (macro_i=0; macro_i<numlocals; ++macro_i) { \
234 if ((ttype[macro_i] = vtype[macro_i]) == TYPE_ADR) \
235 TYPEINFO_CLONE(vinfo[macro_i],tinfo[macro_i]); \
238 /* TYPECHECK_MERGEVARS: merge the local variables of the target block
239 * with the current local variables.
241 * vtype......current local variable types
242 * vinfo......current local variable typeinfos
243 * ttype......local variable types of target block
244 * tinfo......local variable typeinfos of target block
245 * numlocals..number of local variables
247 * changed....set to true if any typeinfo has changed
251 #define TYPECHECK_MERGEVARS \
253 LOG("TYPECHECK_MERGEVARS"); \
254 for (macro_i=0; macro_i<numlocals; ++macro_i) { \
255 if ((ttype[macro_i] != TYPE_VOID) && (vtype[macro_i] != ttype[macro_i])) { \
256 LOG3("var %d: type %d + type %d = void",macro_i,ttype[macro_i],vtype[macro_i]); \
257 ttype[macro_i] = TYPE_VOID; \
259 } else if (ttype[macro_i] == TYPE_ADR) { \
260 if ( ((TYPEINFO_IS_PRIMITIVE(tinfo[macro_i])) ? 1 : 0) \
262 ((TYPEINFO_IS_PRIMITIVE(vinfo[macro_i])) ? 1 : 0)) { \
263 LOG1("var %d: primitive + reference merge",macro_i); \
264 ttype[macro_i] = TYPE_VOID; \
268 LOG1("var %d:",macro_i); \
269 LOGINFO(tinfo+macro_i); \
270 LOGINFO(vinfo+macro_i); \
271 changed |= typeinfo_merge(tinfo+macro_i,vinfo+macro_i); \
272 LOGINFO(tinfo+macro_i); \
273 LOGIF(changed,"vars have changed"); \
278 /* TYPECHECK_MERGEJSR:
282 * tbptr......target block
283 * changed....set to true if any typeinfo has changed
284 * numlocals..number of local variables
285 * touched....current touched flags of local variables
287 * macro_i, jsrtemp, jsrtemp2
289 #define TYPECHECK_MERGEJSR \
291 LOG("TYPECHECK_MERGEJSR"); \
292 jsrtemp = jsrbuffer[tbptr-block]; \
293 jsrtemp2 = jsrchain; \
294 while (jsrtemp || jsrtemp2) { \
295 if (!jsrtemp || !jsrtemp2) \
296 panic("Merging JSR subroutines of different depth"); \
297 if (jsrtemp->target != jsrtemp2->target) \
298 panic("Merging different JSR subroutines"); \
299 jsrtemp = jsrtemp->next; \
300 jsrtemp2 = jsrtemp2->next; \
302 jsrtemp = jsrbuffer[tbptr-block]; \
304 for (macro_i=0; macro_i<numlocals; ++macro_i) { \
305 jsrtemp->touched[i] |= touched[i]; \
308 /* TYPECHECK_COPYSTACK: copy the typeinfos of the current stack to
309 * the input stack of the target block.
311 * srcstack...current stack
312 * dststack...input stack of target block
314 #define TYPECHECK_COPYSTACK \
316 LOG("TYPECHECK_COPYSTACK"); \
318 LOG1("copy %d",srcstack->type); \
319 if (!dststack) panic("Stack depth mismatch"); \
320 if (srcstack->type != dststack->type) \
321 panic("Type mismatch on stack"); \
322 if (srcstack->type == TYPE_ADR) { \
323 TYPEINFO_CLONE(srcstack->typeinfo,dststack->typeinfo); \
325 dststack = dststack->prev; \
326 srcstack = srcstack->prev; \
328 if (dststack) panic("Stack depth mismatch"); \
331 /* TYPECHECK_MERGESTACK: merge the input stack of the target block
332 * with the current stack.
334 * srcstack...current stack
335 * dststack...input stack of target block
337 * changed....set to true if any typeinfo has changed
339 #define TYPECHECK_MERGESTACK \
341 LOG("TYPECHECK_MERGESTACK"); \
343 if (!dststack) panic("Stack depth mismatch"); \
344 if (srcstack->type != dststack->type) \
345 panic("Type mismatch on stack"); \
346 if (srcstack->type == TYPE_ADR) { \
347 LOGINFO(&dststack->typeinfo); \
348 LOGINFO(&srcstack->typeinfo); LOGFLUSH; \
349 changed |= typeinfo_merge(&dststack->typeinfo, \
350 &srcstack->typeinfo); \
351 LOGINFO(&dststack->typeinfo); \
352 LOG((changed)?"CHANGED!\n":"not changed.\n"); \
354 dststack = dststack->prev; \
355 srcstack = srcstack->prev; \
357 if (dststack) panic("Stack depth mismatch"); \
361 /* TYPECHECK_CHECK_JSR_CHAIN: checks if the target block is reached by
362 * the same JSR targets on all control paths.
365 * tbptr......target block
366 * jsrchain...current JSR target chain
367 * jsrbuffer..JSR target chain for each basic block
369 * panic if the JSR target chains don't match
373 #define TYPECHECK_CHECK_JSR_CHAIN \
375 jsrtemp = jsrbuffer[tbptr-block]; \
376 if (!jsrtemp) panic("non-subroutine called by JSR"); \
377 if (jsrtemp->target != tbptr) \
378 panic("Merging different JSR subroutines"); \
379 jsrtemp = jsrtemp->next; \
380 jsrtemp2 = jsrchain; \
381 while (jsrtemp || jsrtemp2) { \
382 if (!jsrtemp || !jsrtemp2) \
383 panic("Merging JSR subroutines of different depth"); \
384 if (jsrtemp->target != jsrtemp2->target) \
385 panic("Merging different JSR subroutines"); \
386 jsrtemp = jsrtemp->next; \
387 jsrtemp2 = jsrtemp2->next; \
390 /* TYPECHECK_ADD_JSR: add a JSR target to the current JSR target chain
391 * and store the resulting chain in the target block.
394 * jsrchain...current JSR target chain
395 * tbptr.....the basic block targeted by the JSR
396 * numlocals..number of local variables
397 * jsrbuffer..JSR target chain for each basic block
401 #define TYPECHECK_ADD_JSR \
403 LOG1("adding JSR to block %04d",(tbptr)-block); \
404 jsrtemp = (jsr_record *) dump_alloc(sizeof(jsr_record)+(numlocals-1)*sizeof(u1)); \
405 jsrtemp->target = (tbptr); \
406 jsrtemp->next = jsrchain; \
407 jsrtemp->sbr_touched = NULL; \
408 memset(&jsrtemp->touched,TOUCHED_NO,sizeof(u1)*numlocals); \
409 jsrbuffer[tbptr-block] = jsrtemp; \
412 /* TYPECHECK_COPYJSR: copy the current JSR chain to the target block.
415 * chain......current JSR target chain
416 * tbptr.....the basic block targeted by the JSR
417 * numlocals..number of local variables
418 * jsrbuffer..JSR target chain for each basic block
419 * touched....current touched flags of local variables
423 #define TYPECHECK_COPYJSR(chain) \
425 LOG("TYPECHECK_COPYJSR"); \
427 jsrtemp = (jsr_record *) dump_alloc(sizeof(jsr_record)+(numlocals-1)*sizeof(u1)); \
428 jsrtemp->target = (chain)->target; \
429 jsrtemp->next = (chain)->next; \
430 jsrtemp->sbr_touched = NULL; \
431 memcpy(&jsrtemp->touched,touched,sizeof(u1)*numlocals); \
432 jsrbuffer[tbptr-block] = jsrtemp; \
435 jsrbuffer[tbptr-block] = NULL; \
438 /* TYPECHECK_BRANCH_BACKWARDS: executed when control flow moves
439 * backwards. Checks if there are uninitialized objects on the
440 * stack or in local variables.
442 * dst........current output stack pointer (not needed for REACH_THROW)
443 * vtype......current local variable types
444 * vinfo......current local variable typeinfos
448 #define TYPECHECK_BRANCH_BACKWARDS \
453 if (srcstack->type == TYPE_ADR && \
454 TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo)) \
455 panic("Branching backwards with uninitialized object on stack"); \
456 srcstack = srcstack->prev; \
458 for (macro_i=0; macro_i<numlocals; ++macro_i) \
459 if (vtype[macro_i] == TYPE_ADR && \
460 TYPEINFO_IS_NEWOBJECT(vinfo[macro_i])) \
461 panic("Branching backwards with uninitialized object in local variable"); \
464 /* TYPECHECK_REACH: executed, when the target block (tbptr) can be reached
465 * from the current block (bptr). The types of local variables and
466 * stack slots are propagated to the target block.
468 * bptr.......current block
469 * tbptr......target block
470 * dst........current output stack pointer (not needed for REACH_THROW)
471 * numlocals..number of local variables
472 * vtype......current local variable types
473 * vinfo......current local variable typeinfos
474 * jsrchain...current JSR target chain
475 * jsrbuffer..JSR target chain for each basic block
476 * way........in which way the block is reached (REACH_ constant)
477 * touched....current touched flags of local variables
479 * repeat.....changed to true if a block before the current
482 * ttype, tinfo, srcstack, dststack, changed, macro_i
484 #define TYPECHECK_REACH(way) \
486 LOG2("reaching block %04d (%d)",tbptr-block,way); \
487 if (tbptr <= bptr && way != REACH_THROW) \
488 TYPECHECK_BRANCH_BACKWARDS; \
490 dststack = tbptr->instack; \
491 ttype = vartype + numlocals*(tbptr-block); \
492 tinfo = vartypeinfo + numlocals*(tbptr-block); \
493 if (tbptr->flags == BBTYPECHECK_UNDEF) { \
494 /* This block is reached for the first time */ \
495 if (way == REACH_JSR) { \
497 TYPECHECK_COPYVARS; \
500 TYPECHECK_COPYJSR(jsrchain); \
501 TYPECHECK_COPYVARS; \
503 if (way != REACH_THROW) TYPECHECK_COPYSTACK; \
506 /* This block has been reached before */ \
508 if (way == REACH_JSR) \
509 TYPECHECK_CHECK_JSR_CHAIN; \
511 TYPECHECK_MERGEJSR; \
512 TYPECHECK_MERGEVARS; \
513 if (way != REACH_THROW) TYPECHECK_MERGESTACK; \
517 tbptr->flags = BBTYPECHECK_REACHED; \
518 if (tbptr <= bptr) {repeat = true; LOG("REPEAT!");} \
523 /* TYPECHECK_LEAVE: executed when the method is exited non-abruptly
525 * class........class of the current method
526 * numlocals....number of local variables
527 * vtype........current local variable types
528 * vinfo........current local variable typeinfos
529 * initmethod...true if this is an <init> method
531 #define TYPECHECK_LEAVE \
533 if (initmethod && class != class_java_lang_Object) { \
534 /* check the marker variable */ \
535 LOG("Checking <init> marker"); \
536 if (vtype[numlocals-1] == TYPE_VOID) \
537 panic("<init> method does not initialize 'this'"); \
541 /****************************************************************************/
543 /****************************************************************************/
545 #define MAXPARAMS 255
547 /* typecheck is called directly after analyse_stack */
551 int b_count, b_index;
552 stackptr curstack; /* input stack top for current instruction */
553 stackptr srcstack; /* source stack for copying and merging */
554 stackptr dststack; /* target stack for copying and merging */
555 int opcode; /* current opcode */
556 int macro_i, i; /* temporary counters */
557 int len; /* for counting instructions, etc. */
558 bool superblockend; /* true if no fallthrough to next block */
559 bool repeat; /* if true, blocks are iterated over again */
560 bool changed; /* used in macros */
561 instruction *iptr; /* pointer to current instruction */
562 basicblock *bptr; /* pointer to current basic block */
563 basicblock *tbptr; /* temporary for target block */
564 int numlocals; /* number of local variables */
565 u1 *vartype; /* type of each local for each basic block */
566 typeinfo *vartypeinfo; /* type of each local for each basic block */
567 u1 *vtype; /* type of each local for current instruction */
568 typeinfo *vinfo; /* type of each local for current instruction */
569 u1 *ttype; /* temporary pointer */
570 typeinfo *tinfo; /* temporary pointer */
571 typeinfo tempinfo; /* temporary */
572 int returntype; /* return type of current method */
573 typeinfo returntypeinfo; /* typeinfo for return type */
574 u1 *ptype; /* parameter types of called method */
575 typeinfo *pinfo; /* parameter typeinfos of called method */
576 int rtype; /* return type of called method */
577 typeinfo rinfo; /* typeinfo for return type of called method */
578 stackptr dst; /* output stack of current instruction */
579 basicblock **tptr; /* pointer into target list of switch instructions */
580 jsr_record **jsrbuffer; /* JSR target chain for each basic block */
581 jsr_record *jsrchain; /* JSR chain for current block */
582 jsr_record *jsrtemp,*jsrtemp2; /* temporary variables */
583 jsr_record *subroutine; /* jsr_record of the current subroutine */
584 u1 *touched; /* touched flags for local variables */
585 xtable **handlers; /* active exception handlers */
586 classinfo *cls; /* temporary */
587 bool maythrow; /* true if this instruction may throw */
588 utf *name_init; /* "<init>" */
589 bool initmethod; /* true if this is an "<init>" method */
591 LOGSTR("\n==============================================================================\n");
592 DOLOG(show_icmd_method());
593 LOGSTR("\n==============================================================================\n");
594 LOGimpSTR("Entering typecheck: ");
595 LOGimpSTRu(method->name);
597 LOGimpSTRu(method->descriptor);
598 LOGimpSTR(" (class ");
599 LOGimpSTRu(method->class->name);
602 name_init = utf_new_char("<init>");
603 initmethod = (method->name == name_init);
605 /* XXX allocate buffers for method arguments */
606 ptype = DMNEW(u1,MAXPARAMS);
607 pinfo = DMNEW(typeinfo,MAXPARAMS);
609 LOG("Buffer allocated.\n");
611 /* reset all BBFINISHED blocks to BBTYPECHECK_UNDEF. */
612 b_count = block_count;
614 while (--b_count >= 0) {
615 #ifdef TYPECHECK_DEBUG
616 if (bptr->flags != BBFINISHED && bptr->flags != BBDELETED
617 && bptr->flags != BBUNDEF)
620 LOGSTR1("block flags: %d\n",bptr->flags); LOGFLUSH;
621 panic("Internal error: Unexpected block flags in typecheck()");
624 if (bptr->flags >= BBFINISHED) {
625 bptr->flags = BBTYPECHECK_UNDEF;
630 /* The first block is always reached */
631 if (block_count && block[0].flags == BBTYPECHECK_UNDEF)
632 block[0].flags = BBTYPECHECK_REACHED;
634 LOG("Blocks reset.\n");
636 /* number of local variables */
638 /* In <init> methods we use an extra local variable to signal if
639 * the 'this' reference has been initialized. */
640 numlocals = maxlocals;
641 if (initmethod) numlocals++;
643 /* allocate the buffers for local variables */
644 vartype = DMNEW(u1,numlocals * (block_count+1));
645 vartypeinfo = DMNEW(typeinfo,numlocals * (block_count+1));
646 touched = DMNEW(u1,numlocals);
647 vtype = vartype + numlocals * block_count;
648 vinfo = vartypeinfo + numlocals * block_count;
649 memset(vartype,TYPE_VOID,numlocals * (block_count+1) * sizeof(typeinfo));
650 memset(vartypeinfo,0,numlocals * (block_count+1) * sizeof(typeinfo));
652 LOG("Variable buffer initialized.\n");
654 /* allocate the buffer for storing JSR target chains */
655 jsrbuffer = DMNEW(jsr_record*,block_count);
656 memset(jsrbuffer,0,block_count * sizeof(jsr_record*));
659 LOG("jsrbuffer initialized.\n");
661 /* allocate the buffer of active exception handlers */
662 handlers = DMNEW(xtable*,method->exceptiontablelength + 1);
664 /* initialize the variable types of the first block */
665 /* to the types of the arguments */
669 /* if this is an instance method initialize the "this" ref type */
670 if (!(method->flags & ACC_STATIC)) {
671 *ttype++ = TYPE_ADDRESS;
673 TYPEINFO_INIT_NEWOBJECT(*tinfo,NULL);
675 TYPEINFO_INIT_CLASSINFO(*tinfo,class);
679 LOG("'this' argument set.\n");
681 /* the rest of the arguments and the return type */
682 typeinfo_init_from_method_args(method->descriptor,ttype,tinfo,
683 numlocals - (tinfo-vartypeinfo),
684 true, /* two word types use two slots */
685 &returntype,&returntypeinfo);
687 LOG("Arguments set.\n");
689 /* initialize the input stack of exception handlers */
690 for (i=0; i<method->exceptiontablelength; ++i) {
691 cls = extable[i].catchtype;
692 if (!cls) cls = class_java_lang_Throwable;
693 LOGSTR1("handler %i: ",i); LOGSTRu(cls->name); LOGNL;
694 TYPEINFO_INIT_CLASSINFO(extable[i].handler->instack->typeinfo,cls);
697 LOG("Exception handler stacks set.\n");
699 /* loop while there are still blocks to be checked */
704 b_count = block_count;
707 while (--b_count >= 0) {
708 LOGSTR1("---- BLOCK %04d, ",bptr-block);
709 LOGSTR1("blockflags: %d\n",bptr->flags);
712 if (bptr->flags == BBTYPECHECK_REACHED) {
713 LOGSTR1("\n---- BLOCK %04d ------------------------------------------------\n",bptr-block);
716 superblockend = false;
717 bptr->flags = BBFINISHED;
718 b_index = bptr - block;
720 /* init stack at the start of this block */
721 curstack = bptr->instack;
723 /* determine the active exception handlers for this block */
724 /* XXX could use a faster algorithm with sorted lists or
727 for (i=0; i<method->exceptiontablelength; ++i) {
728 if ((extable[i].start <= bptr) && (extable[i].end > bptr)) {
729 LOG1("active handler L%03d",extable[i].handler->debug_nr);
730 handlers[len++] = extable + i;
733 handlers[len] = NULL;
735 /* init variable types at the start of this block */
736 for (i=0; i<numlocals; ++i) {
737 vtype[i] = vartype[numlocals*b_index + i];
738 TYPEINFO_COPY(vartypeinfo[numlocals*b_index + i],vinfo[i]);
741 vtype[i] == TYPE_ADR && TYPEINFO_IS_NEWOBJECT(vinfo[i]))
742 panic("Uninitialized object in local variable inside try block");
745 /* init JSR target chain */
746 if ((jsrchain = jsrbuffer[b_index]) != NULL) {
747 #ifdef TYPECHECK_VERBOSE
748 if (typecheckverbose) {
749 LOGSTR("jsr chain:");
752 LOGSTR1(" L%03d",jsrtemp->target->debug_nr);
753 jsrtemp = jsrtemp->next;
760 subroutine = jsrbuffer[jsrchain->target - block];
761 memcpy(touched,jsrchain->touched,sizeof(u1)*numlocals);
765 #ifdef TYPECHECK_VERBOSE
766 if (typecheckverbose) {
767 if (subroutine) {LOGSTR1("subroutine L%03d\n",subroutine->target->debug_nr);LOGFLUSH;}
768 typeinfo_print_block(get_logfile(),curstack,numlocals,vtype,vinfo,(jsrchain) ? touched : NULL);
773 /* loop over the instructions */
777 DOLOG(show_icmd(iptr,false));
787 /****************************************/
788 /* STACK MANIPULATIONS */
790 /* We just need to copy the typeinfo */
791 /* for slots containing addresses. */
793 /* XXX We assume that the destination stack
794 * slots were continuously allocated in
795 * memory. (The current implementation in
800 COPYTYPE(curstack,dst);
804 COPYTYPE(curstack,dst);
805 COPYTYPE(curstack,dst-2);
806 COPYTYPE(curstack->prev,dst-1);
810 COPYTYPE(curstack,dst);
811 COPYTYPE(curstack,dst-3);
812 COPYTYPE(curstack->prev,dst-1);
813 COPYTYPE(curstack->prev->prev,dst-2);
817 COPYTYPE(curstack,dst);
818 COPYTYPE(curstack->prev,dst-1);
822 COPYTYPE(curstack,dst);
823 COPYTYPE(curstack->prev,dst-1);
824 COPYTYPE(curstack,dst-3);
825 COPYTYPE(curstack->prev,dst-4);
826 COPYTYPE(curstack->prev->prev,dst-2);
830 COPYTYPE(curstack,dst);
831 COPYTYPE(curstack->prev,dst-1);
832 COPYTYPE(curstack,dst-4);
833 COPYTYPE(curstack->prev,dst-5);
834 COPYTYPE(curstack->prev->prev,dst-2);
835 COPYTYPE(curstack->prev->prev->prev,dst-3);
839 COPYTYPE(curstack,dst-1);
840 COPYTYPE(curstack->prev,dst);
843 /* XXX only add these cases in debug mode? */
850 /****************************************/
851 /* LOADING ADDRESS FROM VARIABLE */
854 CHECKVARTYPE(iptr->op1,TYPE_ADR);
856 /* loading a returnAddress is not allowed */
857 if (TYPEINFO_IS_PRIMITIVE(vinfo[iptr->op1]))
858 panic("illegal instruction: ALOAD loading returnAddress");
860 TYPEINFO_COPY(vinfo[iptr->op1],dst->typeinfo);
863 /****************************************/
864 /* STORING ADDRESS TO VARIABLE */
867 /* TYPE_ADR has already been checked. */
870 TYPEINFO_IS_NEWOBJECT(curstack->typeinfo))
871 panic("Storing uninitialized object in local variable inside try block");
873 STORE_TYPE(iptr->op1,TYPE_ADDRESS);
874 TYPEINFO_COPY(curstack->typeinfo,vinfo[iptr->op1]);
877 /****************************************/
878 /* LOADING ADDRESS FROM ARRAY */
881 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(curstack->prev->typeinfo))
882 panic("illegal instruction: AALOAD on non-reference array");
884 typeinfo_init_component(&curstack->prev->typeinfo,&dst->typeinfo);
888 /****************************************/
889 /* STORING ADDRESS TO ARRAY */
892 /* XXX also handled by builtin3 */
893 /* XXX move this to unexpected instructions? */
894 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(curstack->prev->prev->typeinfo))
895 panic("illegal instruction: AASTORE to non-reference array");
899 typeinfo_init_component(&curstack->prev->prev->typeinfo,&tempinfo);
900 if (!typeinfo_is_assignable(&curstack->typeinfo,&tempinfo))
901 panic("illegal instruction: AASTORE to incompatible type");
906 /****************************************/
910 if (!TYPEINFO_IS_REFERENCE(curstack->prev->typeinfo))
911 panic("illegal instruction: PUTFIELD on non-reference");
912 if (TYPEINFO_IS_ARRAY(curstack->prev->typeinfo)) /* XXX arraystub */
913 panic("illegal instruction: PUTFIELD on array");
926 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
927 panic("illegal instruction: GETFIELD on non-reference");
928 if (TYPEINFO_IS_ARRAY(curstack->typeinfo))
929 panic("illegal instruction: GETFIELD on array");
932 fieldinfo *fi = (fieldinfo *)(iptr->val.a);
933 /* XXX check non-static? */
934 if (dst->type == TYPE_ADR) {
935 TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi);
938 /* XXX check field type? */
939 TYPEINFO_INIT_PRIMITIVE(dst->typeinfo);
947 fieldinfo *fi = (fieldinfo *)(iptr->val.a);
948 /* XXX check static? */
949 if (dst->type == TYPE_ADR) {
950 TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi);
953 /* XXX check field type? */
954 TYPEINFO_INIT_PRIMITIVE(dst->typeinfo);
960 /****************************************/
961 /* PRIMITIVE ARRAY ACCESS */
963 case ICMD_ARRAYLENGTH:
964 /* XXX should this also work on arraystubs? */
965 if (!TYPEINFO_MAYBE_ARRAY(curstack->typeinfo))
966 panic("illegal instruction: ARRAYLENGTH on non-array");
971 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_BOOLEAN)
972 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_BYTE))
973 panic("Array type mismatch");
977 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_CHAR))
978 panic("Array type mismatch");
982 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_DOUBLE))
983 panic("Array type mismatch");
987 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_FLOAT))
988 panic("Array type mismatch");
992 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_INT))
993 panic("Array type mismatch");
997 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_SHORT))
998 panic("Array type mismatch");
1002 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_LONG))
1003 panic("Array type mismatch");
1008 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_BOOLEAN)
1009 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_BYTE))
1010 panic("Array type mismatch");
1014 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_CHAR))
1015 panic("Array type mismatch");
1019 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_DOUBLE))
1020 panic("Array type mismatch");
1024 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_FLOAT))
1025 panic("Array type mismatch");
1029 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_INT))
1030 panic("Array type mismatch");
1034 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_SHORT))
1035 panic("Array type mismatch");
1039 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_LONG))
1040 panic("Array type mismatch");
1044 /****************************************/
1045 /* OPERATIONS WITH UNCHECKED INPUT */
1047 case ICMD_CHECKCAST:
1048 /* returnAddress is not allowed */
1049 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1050 panic("Illegal instruction: INSTANCEOF on non-reference");
1052 /* XXX check if the cast can be done statically */
1053 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,(classinfo *)iptr[0].val.a);
1058 case ICMD_INSTANCEOF:
1059 /* returnAddress is not allowed */
1060 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1061 panic("Illegal instruction: INSTANCEOF on non-reference");
1063 /* XXX may throw ? */
1067 if (iptr->val.a == NULL)
1068 TYPEINFO_INIT_NULLTYPE(dst->typeinfo);
1070 /* XXX constants for builtin functions */
1071 /* string constants */
1072 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,class_java_lang_String);
1075 /****************************************/
1076 /* BRANCH INSTRUCTIONS */
1079 superblockend = true;
1082 case ICMD_IFNONNULL:
1089 case ICMD_IF_ICMPEQ:
1090 case ICMD_IF_ICMPNE:
1091 case ICMD_IF_ICMPLT:
1092 case ICMD_IF_ICMPGE:
1093 case ICMD_IF_ICMPGT:
1094 case ICMD_IF_ICMPLE:
1095 case ICMD_IF_ACMPEQ:
1096 case ICMD_IF_ACMPNE:
1103 case ICMD_IF_LCMPEQ:
1104 case ICMD_IF_LCMPNE:
1105 case ICMD_IF_LCMPLT:
1106 case ICMD_IF_LCMPGE:
1107 case ICMD_IF_LCMPGT:
1108 case ICMD_IF_LCMPLE:
1109 tbptr = (basicblock *) iptr->target;
1111 /* propagate stack and variables to the target block */
1112 TYPECHECK_REACH(REACH_STD);
1116 /****************************************/
1119 case ICMD_TABLESWITCH:
1121 s4 *s4ptr = iptr->val.a;
1122 s4ptr++; /* skip default */
1123 i = *s4ptr++; /* low */
1124 i = *s4ptr++ - i + 2; /* +1 for default target */
1126 goto switch_instruction_tail;
1128 case ICMD_LOOKUPSWITCH:
1130 s4 *s4ptr = iptr->val.a;
1131 s4ptr++; /* skip default */
1132 i = *s4ptr++ + 1; /* count +1 for default target */
1134 switch_instruction_tail:
1135 tptr = (basicblock **)iptr->target;
1139 LOG2("target %d is block %04d",(tptr-(basicblock **)iptr->target)-1,tbptr-block);
1140 TYPECHECK_REACH(REACH_STD);
1143 superblockend = true;
1146 /****************************************/
1147 /* RETURNS AND THROW */
1149 /* XXX returns may throw */
1152 TYPEINFO_INIT_CLASSINFO(tempinfo,class_java_lang_Throwable);
1153 if (!typeinfo_is_assignable(&curstack->typeinfo,&tempinfo))
1154 panic("illegal instruction: ATHROW on non-Throwable");
1155 superblockend = true;
1160 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1161 panic("illegal instruction: ARETURN on non-reference");
1163 if (returntype != TYPE_ADDRESS
1164 || !typeinfo_is_assignable(&curstack->typeinfo,&returntypeinfo))
1165 panic("Return type mismatch");
1168 superblockend = true;
1172 if (returntype != TYPE_INT)
1173 panic("Return type mismatch");
1175 superblockend = true;
1178 if (returntype != TYPE_LONG)
1179 panic("Return type mismatch");
1181 superblockend = true;
1184 if (returntype != TYPE_FLOAT)
1185 panic("Return type mismatch");
1187 superblockend = true;
1190 if (returntype != TYPE_DOUBLE)
1191 panic("Return type mismatch");
1193 superblockend = true;
1196 if (returntype != TYPE_VOID)
1197 panic("Return type mismatch");
1199 superblockend = true;
1202 /****************************************/
1203 /* SUBROUTINE INSTRUCTIONS */
1208 /* XXX This is a dirty hack. It is needed
1209 * because of the special handling of ICMD_JSR in stack.c
1211 dst = (stackptr) iptr->val.a;
1213 /* push return address */
1214 TYPEINFO_INIT_PRIMITIVE(dst->typeinfo);
1216 LOG("reaching block...");
1218 /* add the target to the JSR target chain and */
1219 /* propagate stack and variables to the target block */
1220 tbptr = (basicblock *) iptr->target;
1221 TYPECHECK_REACH(REACH_JSR);
1223 /* set dst to the stack after the subroutine execution */
1224 /* XXX We assume (as in stack.c) that the
1225 * subroutine returns the stack as it was
1226 * before the JSR instruction. Is this
1231 /* Find the jsr_record of the called subroutine */
1232 jsrtemp = jsrbuffer[tbptr - block];
1234 /* Check if we already calculated (at least
1235 * for one RET) which variables the
1236 * subroutine touches.
1238 if (jsrtemp->sbr_touched) {
1239 /* Calculate the local variables after the subroutine call */
1240 for (i=0; i<numlocals; ++i)
1241 if (jsrtemp->sbr_touched[i] != TOUCHED_NO) {
1243 if ((vtype[i] = jsrtemp->sbr_vtype[i]) == TYPE_ADR)
1244 TYPEINFO_CLONE(jsrtemp->sbr_vinfo[i],vinfo[i]);
1247 /* continue after the JSR call */
1248 superblockend = false;
1251 /* We cannot proceed until the subroutine has been typechecked. */
1252 /* XXX actually we would not have to check this block again */
1253 bptr->flags = BBTYPECHECK_REACHED;
1255 superblockend = true;
1257 /* XXX may throw? */
1261 /* check returnAddress variable */
1262 CHECKVARTYPE(iptr->op1,TYPE_ADR);
1264 if (!TYPEINFO_IS_PRIMITIVE(vinfo[iptr->op1]))
1265 panic("illegal instruction: RET using non-returnAddress variable");
1267 /* check if we are inside a subroutine */
1269 panic("RET outside of subroutine");
1271 /* determine which variables are touched by this subroutine */
1272 /* and their types */
1273 if (subroutine->sbr_touched) {
1274 for (i=0; i<numlocals; ++i)
1275 subroutine->sbr_touched[i] |= touched[i];
1276 ttype = subroutine->sbr_vtype;
1277 tinfo = subroutine->sbr_vinfo;
1278 TYPECHECK_MERGEVARS;
1281 subroutine->sbr_touched = DMNEW(u1,numlocals);
1282 memcpy(subroutine->sbr_touched,touched,sizeof(u1)*numlocals);
1283 subroutine->sbr_vtype = DMNEW(u1,numlocals);
1284 memcpy(subroutine->sbr_vtype,vtype,sizeof(u1)*numlocals);
1285 subroutine->sbr_vinfo = DMNEW(typeinfo,numlocals);
1286 for (i=0; i<numlocals; ++i)
1287 if (vtype[i] == TYPE_ADR)
1288 TYPEINFO_CLONE(vinfo[i],subroutine->sbr_vinfo[i]);
1290 /* XXX check if subroutine changed types? */
1292 LOGSTR("subroutine touches:");
1293 DOLOG(typeinfo_print_locals(get_logfile(),subroutine->sbr_vtype,subroutine->sbr_vinfo,
1294 subroutine->sbr_touched,numlocals));
1297 /* reach blocks after JSR statements */
1298 for (i=0; i<block_count; ++i) {
1300 LOG1("block L%03d",tbptr->debug_nr);
1301 if (tbptr->iinstr[tbptr->icount - 1].opc != ICMD_JSR)
1303 LOG("ends with JSR");
1304 if ((basicblock*) tbptr->iinstr[tbptr->icount - 1].target != subroutine->target)
1308 LOG1("RET reaches block %04d",tbptr-block);
1310 /*TYPECHECK_REACH(REACH_RET);*/
1313 superblockend = true;
1316 /****************************************/
1319 case ICMD_INVOKEVIRTUAL:
1320 case ICMD_INVOKESPECIAL:
1321 case ICMD_INVOKESTATIC:
1322 case ICMD_INVOKEINTERFACE:
1324 /* XXX check access rights */
1326 methodinfo *mi = (methodinfo*) iptr->val.a;
1327 bool callinginit = (opcode == ICMD_INVOKESPECIAL && mi->name == name_init);
1329 classinfo *initclass;
1331 /* XXX for INVOKESPECIAL: check if the invokation is done at all */
1333 /* fetch parameter types and return type */
1334 /* XXX might use dst->typeinfo directly if non void */
1336 if (opcode != ICMD_INVOKESTATIC) {
1337 ptype[0] = TYPE_ADR;
1338 TYPEINFO_INIT_CLASSINFO(pinfo[0],mi->class);
1341 typeinfo_init_from_method_args(mi->descriptor,ptype+i,pinfo+i,
1345 /* check parameter types */
1346 srcstack = curstack;
1347 i = mi->paramcount; /* number of parameters including 'this'*/
1350 if (srcstack->type != ptype[i])
1351 panic("Parameter type mismatch in method invocation");
1352 if (srcstack->type == TYPE_ADR) {
1353 LOGINFO(&(srcstack->typeinfo));
1355 if (i==0 && callinginit)
1357 /* first argument to <init> method */
1358 if (!TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo))
1359 panic("Calling <init> on initialized object");
1361 /* get the address of the NEW instruction */
1362 LOGINFO(&(srcstack->typeinfo));
1363 ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(srcstack->typeinfo);
1364 initclass = (ins) ? (classinfo*)ins[-1].val.a : method->class;
1365 LOGSTR("class: "); LOGSTRu(initclass->name); LOGNL;
1367 /* XXX check type */
1370 if (!typeinfo_is_assignable(&(srcstack->typeinfo),pinfo+i))
1371 panic("Parameter reference type mismatch in method invocation");
1376 srcstack = srcstack->prev;
1379 if (rtype != TYPE_VOID) {
1380 if (rtype != dst->type)
1381 panic("Return type mismatch in method invocation");
1382 TYPEINFO_COPY(rinfo,dst->typeinfo);
1386 /* replace uninitialized object type on stack */
1389 if (srcstack->type == TYPE_ADR
1390 && TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo)
1391 && TYPEINFO_NEWOBJECT_INSTRUCTION(srcstack->typeinfo) == ins)
1393 LOG("replacing uninitialized type on stack");
1394 TYPEINFO_INIT_CLASSINFO(srcstack->typeinfo,initclass);
1396 srcstack = srcstack->prev;
1398 /* replace uninitialized object type in locals */
1399 for (i=0; i<numlocals; ++i) {
1400 if (vtype[i] == TYPE_ADR
1401 && TYPEINFO_IS_NEWOBJECT(vinfo[i])
1402 && TYPEINFO_NEWOBJECT_INSTRUCTION(vinfo[i]) == ins)
1404 LOG1("replacing uninitialized type in local %d",i);
1405 TYPEINFO_INIT_CLASSINFO(vinfo[i],initclass);
1409 /* initializing the 'this' reference? */
1410 if (initmethod && !ins) {
1411 /* set our marker variable to type int */
1412 LOG("setting <init> marker");
1413 STORE_PRIMITIVE(numlocals-1,TYPE_INT);
1420 case ICMD_MULTIANEWARRAY:
1421 /* check the array lengths on the stack */
1423 if (i<1) panic("MULTIANEWARRAY with dimensions < 1");
1424 srcstack = curstack;
1427 panic("MULTIANEWARRAY missing array length");
1428 if (srcstack->type != TYPE_INT)
1429 panic("MULTIANEWARRAY using non-int as array length");
1430 srcstack = srcstack->prev;
1433 /* set the array type of the result */
1434 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,((vftbl *)iptr[0].val.a)->class);
1439 if (ISBUILTIN(asm_builtin_aastore)) {
1440 /* XXX also handled by ICMD_AASTORE */
1441 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(curstack->prev->prev->typeinfo))
1442 panic("illegal instruction: AASTORE to non-reference array");
1446 typeinfo_init_component(&curstack->prev->prev->typeinfo,&tempinfo);
1447 if (!typeinfo_is_assignable(&curstack->typeinfo,&tempinfo))
1448 panic("illegal instruction: AASTORE to incompatible type");
1451 /* XXX check for missed builtins in debug mode? */
1452 maythrow = true; /* XXX better safe than sorry */
1457 #if defined(__I386__)
1458 ISBUILTIN(asm_builtin_newarray)
1460 ISBUILTIN(builtin_newarray)
1464 if (iptr[-1].opc != ICMD_ACONST)
1465 panic("illegal instruction: builtin_newarray without classinfo");
1466 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,((vftbl *)iptr[-1].val.a)->class);
1468 else if (ISBUILTIN(asm_builtin_checkarraycast)) {
1469 if (iptr[-1].opc != ICMD_ACONST)
1470 panic("illegal instruction: asm_builtin_checkarraycast without classinfo");
1471 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,((vftbl *)iptr[-1].val.a)->class);
1473 /* XXX check for missed builtins in debug mode? */
1474 maythrow = true; /* XXX better safe than sorry */
1478 if (ISBUILTIN(builtin_new)) {
1479 if (iptr[-1].opc != ICMD_ACONST)
1480 panic("illegal instruction: builtin_new without classinfo");
1481 TYPEINFO_INIT_NEWOBJECT(dst->typeinfo,iptr);
1483 else if (ISBUILTIN(builtin_newarray_boolean)) {
1484 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BOOLEAN);
1486 else if (ISBUILTIN(builtin_newarray_char)) {
1487 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_CHAR);
1489 else if (ISBUILTIN(builtin_newarray_float)) {
1490 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_FLOAT);
1492 else if (ISBUILTIN(builtin_newarray_double)) {
1493 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_DOUBLE);
1495 else if (ISBUILTIN(builtin_newarray_byte)) {
1496 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BYTE);
1498 else if (ISBUILTIN(builtin_newarray_short)) {
1499 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_SHORT);
1501 else if (ISBUILTIN(builtin_newarray_int)) {
1502 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_INT);
1504 else if (ISBUILTIN(builtin_newarray_long)) {
1505 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_LONG);
1507 /* XXX check for missed builtins in debug mode? */
1508 maythrow = true; /* XXX better safe than sorry */
1511 /****************************************/
1512 /* PRIMITIVE VARIABLE ACCESS */
1514 case ICMD_ILOAD: CHECKVARTYPE(iptr->op1,TYPE_INT); break;
1515 case ICMD_LLOAD: CHECKVARTYPE(iptr->op1,TYPE_LONG); break;
1516 case ICMD_FLOAD: CHECKVARTYPE(iptr->op1,TYPE_FLOAT); break;
1517 case ICMD_DLOAD: CHECKVARTYPE(iptr->op1,TYPE_DOUBLE); break;
1518 case ICMD_IINC: CHECKVARTYPE(iptr->op1,TYPE_INT); /*TOUCH_VARIABLE(iptr->op1);*/ break;
1520 case ICMD_FSTORE: STORE_PRIMITIVE(iptr->op1,TYPE_FLOAT); break;
1521 case ICMD_ISTORE: STORE_PRIMITIVE(iptr->op1,TYPE_INT); break;
1522 case ICMD_LSTORE: STORE_TWOWORD(iptr->op1,TYPE_LONG); break;
1523 case ICMD_DSTORE: STORE_TWOWORD(iptr->op1,TYPE_DOUBLE); break;
1525 /****************************************/
1526 /* INSTRUCTIONS WHICH SHOULD HAVE BEEN */
1527 /* REPLACED BY BUILTIN CALLS */
1531 case ICMD_ANEWARRAY:
1532 case ICMD_MONITORENTER:
1533 case ICMD_MONITOREXIT:
1534 /* XXX only check this in debug mode? */
1535 LOGSTR2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
1536 panic("Internal error: unexpected instruction encountered");
1539 /****************************************/
1540 /* UNCHECKED OPERATIONS */
1542 /* These ops have no input or output to be checked */
1543 /* (apart from the checks done in analyse_stack). */
1544 /* XXX only add cases for them in debug mode? */
1547 case ICMD_READONLY_ARG: /* XXX ? */
1548 case ICMD_CLEAR_ARGREN: /* XXX ? */
1551 case ICMD_CHECKASIZE:
1552 case ICMD_NULLCHECKPOP:
1556 /****************************************/
1557 /* ARITHMETIC AND CONVERSION */
1558 /* (These instructions are typechecked in analyse_stack.) */
1560 /* The following instructions may throw a runtime exception: */
1570 /* The following instructions never throw a runtime exception: */
1571 /* XXX only add cases for them in debug mode? */
1578 case ICMD_IFEQ_ICONST:
1579 case ICMD_IFNE_ICONST:
1580 case ICMD_IFLT_ICONST:
1581 case ICMD_IFGE_ICONST:
1582 case ICMD_IFGT_ICONST:
1583 case ICMD_IFLE_ICONST:
1584 case ICMD_ELSE_ICONST:
1606 case ICMD_IREM0X10001:
1607 case ICMD_LREM0X10001:
1610 case ICMD_IADDCONST:
1611 case ICMD_ISUBCONST:
1612 case ICMD_IMULCONST:
1613 case ICMD_IANDCONST:
1615 case ICMD_IXORCONST:
1616 case ICMD_ISHLCONST:
1617 case ICMD_ISHRCONST:
1618 case ICMD_IUSHRCONST:
1620 case ICMD_LADDCONST:
1621 case ICMD_LSUBCONST:
1622 case ICMD_LMULCONST:
1623 case ICMD_LANDCONST:
1625 case ICMD_LXORCONST:
1626 case ICMD_LSHLCONST:
1627 case ICMD_LSHRCONST:
1628 case ICMD_LUSHRCONST:
1645 case ICMD_INT2SHORT:
1648 case ICMD_LCMPCONST:
1669 /****************************************/
1672 LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
1673 panic("Missing ICMD code during typecheck");
1676 /* the output of this instruction becomes the current stack */
1679 /* reach exception handlers for this instruction */
1681 LOG("reaching exception handlers");
1683 while (handlers[i]) {
1684 tbptr = handlers[i]->handler;
1685 TYPECHECK_REACH(REACH_THROW); /* XXX jsr chain? */
1691 DOLOG(typeinfo_print_block(get_logfile(),curstack,numlocals,vtype,vinfo,(jsrchain) ? touched : NULL));
1696 } /* while instructions */
1698 LOG("instructions done");
1699 LOGSTR("RESULT=> ");
1700 DOLOG(typeinfo_print_block(get_logfile(),curstack,numlocals,vtype,vinfo,(jsrchain) ? touched : NULL));
1703 /* propagate stack and variables to the following block */
1704 if (!superblockend) {
1705 LOG("reaching following block");
1707 while (tbptr->flags == BBDELETED) {
1709 #ifdef TYPECHECK_DEBUG
1710 if ((tbptr-block) >= block_count)
1711 panic("Control flow falls off the last block");
1714 TYPECHECK_REACH(REACH_STD);
1717 } /* if block has to be checked */
1719 } /* while blocks */
1721 LOGIF(repeat,"repeat=true");
1724 /* XXX reset BB... to BBFINISHED */
1726 /* XXX free vartype */
1727 /* XXX free vartypeinfo */
1728 /* XXX free buffers for method arguments. */
1730 /* XXX add debug check if all non-dead blocks have been checked */
1732 LOGimp("exiting typecheck");
1737 #endif /* CACAO_TYPECHECK */