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 726 2003-12-10 15:41:07Z 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 /* TYPECHECK_COPYVARS: copy the types and typeinfos of the current local
275 * variables to the local variables of the target block.
277 * vtype......current local variable types
278 * vinfo......current local variable typeinfos
279 * ttype......local variable types of target block
280 * tinfo......local variable typeinfos of target block
281 * numlocals..number of local variables
285 #define TYPECHECK_COPYVARS \
287 LOG("TYPECHECK_COPYVARS"); \
288 for (macro_i=0; macro_i<numlocals; ++macro_i) { \
289 if ((ttype[macro_i] = vtype[macro_i]) == TYPE_ADR) \
290 TYPEINFO_CLONE(vinfo[macro_i],tinfo[macro_i]); \
293 /* TYPECHECK_MERGEVARS: merge the local variables of the target block
294 * with the current local variables.
296 * vtype......current local variable types
297 * vinfo......current local variable typeinfos
298 * ttype......local variable types of target block
299 * tinfo......local variable typeinfos of target block
300 * numlocals..number of local variables
302 * changed....set to true if any typeinfo has changed
306 #define TYPECHECK_MERGEVARS \
308 LOG("TYPECHECK_MERGEVARS"); \
309 for (macro_i=0; macro_i<numlocals; ++macro_i) { \
310 if ((ttype[macro_i] != TYPE_VOID) && (vtype[macro_i] != ttype[macro_i])) { \
311 LOG3("var %d: type %d + type %d = void",macro_i,ttype[macro_i],vtype[macro_i]); \
312 ttype[macro_i] = TYPE_VOID; \
314 } else if (ttype[macro_i] == TYPE_ADR) { \
315 if ( ((TYPEINFO_IS_PRIMITIVE(tinfo[macro_i])) ? 1 : 0) \
317 ((TYPEINFO_IS_PRIMITIVE(vinfo[macro_i])) ? 1 : 0)) { \
318 LOG1("var %d: primitive + reference merge",macro_i); \
319 ttype[macro_i] = TYPE_VOID; \
323 LOG1("var %d:",macro_i); \
324 LOGINFO(tinfo+macro_i); \
325 LOGINFO(vinfo+macro_i); \
326 changed |= typeinfo_merge(tinfo+macro_i,vinfo+macro_i); \
327 LOGINFO(tinfo+macro_i); \
328 LOGIF(changed,"vars have changed"); \
333 /* TYPECHECK_MERGEJSR:
337 * tbptr......target block
338 * changed....set to true if any typeinfo has changed
339 * numlocals..number of local variables
340 * touched....current touched flags of local variables
342 * macro_i, jsrtemp, jsrtemp2
344 #define TYPECHECK_MERGEJSR \
346 LOG("TYPECHECK_MERGEJSR"); \
347 jsrtemp = jsrbuffer[tbptr-block]; \
348 jsrtemp2 = jsrchain; \
349 while (jsrtemp || jsrtemp2) { \
350 if (!jsrtemp || !jsrtemp2) \
351 panic("Merging JSR subroutines of different depth"); \
352 if (jsrtemp->target != jsrtemp2->target) \
353 panic("Merging different JSR subroutines"); \
354 jsrtemp = jsrtemp->next; \
355 jsrtemp2 = jsrtemp2->next; \
357 jsrtemp = jsrbuffer[tbptr-block]; \
359 for (macro_i=0; macro_i<numlocals; ++macro_i) { \
360 jsrtemp->touched[i] |= touched[i]; \
363 /* TYPECHECK_COPYSTACK: copy the typeinfos of the current stack to
364 * the input stack of the target block.
366 * srcstack...current stack
367 * dststack...input stack of target block
369 #define TYPECHECK_COPYSTACK \
371 LOG("TYPECHECK_COPYSTACK"); \
373 LOG1("copy %d",srcstack->type); \
374 if (!dststack) panic("Stack depth mismatch"); \
375 if (srcstack->type != dststack->type) \
376 panic("Type mismatch on stack"); \
377 if (srcstack->type == TYPE_ADR) { \
378 TYPEINFO_CLONE(srcstack->typeinfo,dststack->typeinfo); \
380 dststack = dststack->prev; \
381 srcstack = srcstack->prev; \
383 if (dststack) panic("Stack depth mismatch"); \
386 /* TYPECHECK_MERGESTACK: merge the input stack of the target block
387 * with the current stack.
389 * srcstack...current stack
390 * dststack...input stack of target block
392 * changed....set to true if any typeinfo has changed
394 #define TYPECHECK_MERGESTACK \
396 LOG("TYPECHECK_MERGESTACK"); \
398 if (!dststack) panic("Stack depth mismatch"); \
399 if (srcstack->type != dststack->type) \
400 panic("Type mismatch on stack"); \
401 if (srcstack->type == TYPE_ADR) { \
402 LOGINFO(&dststack->typeinfo); \
403 LOGINFO(&srcstack->typeinfo); LOGFLUSH; \
404 changed |= typeinfo_merge(&dststack->typeinfo, \
405 &srcstack->typeinfo); \
406 LOGINFO(&dststack->typeinfo); \
407 LOG((changed)?"CHANGED!\n":"not changed.\n"); \
409 dststack = dststack->prev; \
410 srcstack = srcstack->prev; \
412 if (dststack) panic("Stack depth mismatch"); \
416 /* TYPECHECK_CHECK_JSR_CHAIN: checks if the target block is reached by
417 * the same JSR targets on all control paths.
420 * tbptr......target block
421 * jsrchain...current JSR target chain
422 * jsrbuffer..JSR target chain for each basic block
424 * panic if the JSR target chains don't match
428 #define TYPECHECK_CHECK_JSR_CHAIN \
430 jsrtemp = jsrbuffer[tbptr-block]; \
431 if (!jsrtemp) panic("non-subroutine called by JSR"); \
432 if (jsrtemp->target != tbptr) \
433 panic("Merging different JSR subroutines"); \
434 jsrtemp = jsrtemp->next; \
435 jsrtemp2 = jsrchain; \
436 while (jsrtemp || jsrtemp2) { \
437 if (!jsrtemp || !jsrtemp2) \
438 panic("Merging JSR subroutines of different depth"); \
439 if (jsrtemp->target != jsrtemp2->target) \
440 panic("Merging different JSR subroutines"); \
441 jsrtemp = jsrtemp->next; \
442 jsrtemp2 = jsrtemp2->next; \
445 /* TYPECHECK_ADD_JSR: add a JSR target to the current JSR target chain
446 * and store the resulting chain in the target block.
449 * jsrchain...current JSR target chain
450 * tbptr.....the basic block targeted by the JSR
451 * numlocals..number of local variables
452 * jsrbuffer..JSR target chain for each basic block
456 #define TYPECHECK_ADD_JSR \
458 LOG1("adding JSR to block %04d",(tbptr)-block); \
459 jsrtemp = (jsr_record *) dump_alloc(sizeof(jsr_record)+(numlocals-1)*sizeof(u1)); \
460 jsrtemp->target = (tbptr); \
461 jsrtemp->next = jsrchain; \
462 jsrtemp->sbr_touched = NULL; \
463 memset(&jsrtemp->touched,TOUCHED_NO,sizeof(u1)*numlocals); \
464 jsrbuffer[tbptr-block] = jsrtemp; \
467 /* TYPECHECK_COPYJSR: copy the current JSR chain to the target block.
470 * chain......current JSR target chain
471 * tbptr.....the basic block targeted by the JSR
472 * numlocals..number of local variables
473 * jsrbuffer..JSR target chain for each basic block
474 * touched....current touched flags of local variables
478 #define TYPECHECK_COPYJSR(chain) \
480 LOG("TYPECHECK_COPYJSR"); \
482 jsrtemp = (jsr_record *) dump_alloc(sizeof(jsr_record)+(numlocals-1)*sizeof(u1)); \
483 jsrtemp->target = (chain)->target; \
484 jsrtemp->next = (chain)->next; \
485 jsrtemp->sbr_touched = NULL; \
486 memcpy(&jsrtemp->touched,touched,sizeof(u1)*numlocals); \
487 jsrbuffer[tbptr-block] = jsrtemp; \
490 jsrbuffer[tbptr-block] = NULL; \
493 /* TYPECHECK_BRANCH_BACKWARDS: executed when control flow moves
494 * backwards. Checks if there are uninitialized objects on the
495 * stack or in local variables.
497 * dst........current output stack pointer (not needed for REACH_THROW)
498 * vtype......current local variable types
499 * vinfo......current local variable typeinfos
503 #define TYPECHECK_BRANCH_BACKWARDS \
508 if (srcstack->type == TYPE_ADR && \
509 TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo)) \
510 panic("Branching backwards with uninitialized object on stack"); \
511 srcstack = srcstack->prev; \
513 for (macro_i=0; macro_i<numlocals; ++macro_i) \
514 if (vtype[macro_i] == TYPE_ADR && \
515 TYPEINFO_IS_NEWOBJECT(vinfo[macro_i])) \
516 panic("Branching backwards with uninitialized object in local variable"); \
519 /* TYPECHECK_REACH: executed, when the target block (tbptr) can be reached
520 * from the current block (bptr). The types of local variables and
521 * stack slots are propagated to the target block.
523 * bptr.......current block
524 * tbptr......target block
525 * dst........current output stack pointer (not needed for REACH_THROW)
526 * numlocals..number of local variables
527 * vtype......current local variable types
528 * vinfo......current local variable typeinfos
529 * jsrchain...current JSR target chain
530 * jsrbuffer..JSR target chain for each basic block
531 * way........in which way the block is reached (REACH_ constant)
532 * touched....current touched flags of local variables
534 * repeat.....changed to true if a block before the current
537 * ttype, tinfo, srcstack, dststack, changed, macro_i
539 #define TYPECHECK_REACH(way) \
541 LOG2("reaching block %04d (%d)",tbptr-block,way); \
542 if (tbptr <= bptr && way != REACH_THROW) \
543 TYPECHECK_BRANCH_BACKWARDS; \
545 dststack = tbptr->instack; \
546 ttype = vartype + numlocals*(tbptr-block); \
547 tinfo = vartypeinfo + numlocals*(tbptr-block); \
548 if (tbptr->flags == BBTYPECHECK_UNDEF) { \
549 /* This block is reached for the first time */ \
550 if (way == REACH_JSR) { \
552 TYPECHECK_COPYVARS; \
555 TYPECHECK_COPYJSR(jsrchain); \
556 TYPECHECK_COPYVARS; \
558 if (way != REACH_THROW) TYPECHECK_COPYSTACK; \
561 /* This block has been reached before */ \
563 if (way == REACH_JSR) \
564 TYPECHECK_CHECK_JSR_CHAIN; \
566 TYPECHECK_MERGEJSR; \
567 TYPECHECK_MERGEVARS; \
568 if (way != REACH_THROW) TYPECHECK_MERGESTACK; \
572 tbptr->flags = BBTYPECHECK_REACHED; \
573 if (tbptr <= bptr) {repeat = true; LOG("REPEAT!");} \
578 /* TYPECHECK_LEAVE: executed when the method is exited non-abruptly
580 * class........class of the current method
581 * numlocals....number of local variables
582 * vtype........current local variable types
583 * vinfo........current local variable typeinfos
584 * initmethod...true if this is an <init> method
586 #define TYPECHECK_LEAVE \
588 if (initmethod && class != class_java_lang_Object) { \
589 /* check the marker variable */ \
590 LOG("Checking <init> marker"); \
591 if (vtype[numlocals-1] == TYPE_VOID) \
592 panic("<init> method does not initialize 'this'"); \
596 /****************************************************************************/
598 /****************************************************************************/
600 #define MAXPARAMS 255
602 /* typecheck is called directly after analyse_stack */
606 int b_count, b_index;
607 stackptr curstack; /* input stack top for current instruction */
608 stackptr srcstack; /* source stack for copying and merging */
609 stackptr dststack; /* target stack for copying and merging */
610 int opcode; /* current opcode */
611 int macro_i, i; /* temporary counters */
612 int len; /* for counting instructions, etc. */
613 bool superblockend; /* true if no fallthrough to next block */
614 bool repeat; /* if true, blocks are iterated over again */
615 bool changed; /* used in macros */
616 instruction *iptr; /* pointer to current instruction */
617 basicblock *bptr; /* pointer to current basic block */
618 basicblock *tbptr; /* temporary for target block */
619 int numlocals; /* number of local variables */
620 int validlocals; /* number of valid local variable indices */
621 u1 *vartype; /* type of each local for each basic block */
622 typeinfo *vartypeinfo; /* type of each local for each basic block */
623 u1 *vtype; /* type of each local for current instruction */
624 typeinfo *vinfo; /* type of each local for current instruction */
625 u1 *ttype; /* temporary pointer */
626 typeinfo *tinfo; /* temporary pointer */
627 typeinfo tempinfo; /* temporary */
628 int returntype; /* return type of current method */
629 typeinfo returntypeinfo; /* typeinfo for return type */
630 u1 *ptype; /* parameter types of called method */
631 typeinfo *pinfo; /* parameter typeinfos of called method */
632 int rtype; /* return type of called method */
633 typeinfo rinfo; /* typeinfo for return type of called method */
634 stackptr dst; /* output stack of current instruction */
635 basicblock **tptr; /* pointer into target list of switch instructions */
636 jsr_record **jsrbuffer; /* JSR target chain for each basic block */
637 jsr_record *jsrchain; /* JSR chain for current block */
638 jsr_record *jsrtemp,*jsrtemp2; /* temporary variables */
639 jsr_record *subroutine; /* jsr_record of the current subroutine */
640 u1 *touched; /* touched flags for local variables */
641 xtable **handlers; /* active exception handlers */
642 classinfo *cls; /* temporary */
643 bool maythrow; /* true if this instruction may throw */
644 utf *name_init; /* "<init>" */
645 bool initmethod; /* true if this is an "<init>" method */
647 #ifdef TYPECHECK_STATISTICS
648 int count_iterations = 0;
651 LOGSTR("\n==============================================================================\n");
652 DOLOG(show_icmd_method());
653 LOGSTR("\n==============================================================================\n");
654 LOGimpSTR("Entering typecheck: ");
655 LOGimpSTRu(method->name);
657 LOGimpSTRu(method->descriptor);
658 LOGimpSTR(" (class ");
659 LOGimpSTRu(method->class->name);
662 name_init = utf_new_char("<init>");
663 initmethod = (method->name == name_init);
665 ptype = DMNEW(u1,MAXPARAMS);
666 pinfo = DMNEW(typeinfo,MAXPARAMS);
668 LOG("Buffer allocated.\n");
670 /* reset all BBFINISHED blocks to BBTYPECHECK_UNDEF. */
671 b_count = block_count;
673 while (--b_count >= 0) {
674 #ifdef TYPECHECK_DEBUG
675 if (bptr->flags != BBFINISHED && bptr->flags != BBDELETED
676 && bptr->flags != BBUNDEF)
679 LOGSTR1("block flags: %d\n",bptr->flags); LOGFLUSH;
680 panic("Internal error: Unexpected block flags in typecheck()");
683 if (bptr->flags >= BBFINISHED) {
684 bptr->flags = BBTYPECHECK_UNDEF;
689 /* The first block is always reached */
690 if (block_count && block[0].flags == BBTYPECHECK_UNDEF)
691 block[0].flags = BBTYPECHECK_REACHED;
693 LOG("Blocks reset.\n");
695 /* number of local variables */
697 /* In <init> methods we use an extra local variable to signal if
698 * the 'this' reference has been initialized. */
699 numlocals = maxlocals;
700 validlocals = numlocals;
701 if (initmethod) numlocals++;
703 /* allocate the buffers for local variables */
704 vartype = DMNEW(u1,numlocals * (block_count+1));
705 vartypeinfo = DMNEW(typeinfo,numlocals * (block_count+1));
706 touched = DMNEW(u1,numlocals);
707 vtype = vartype + numlocals * block_count;
708 vinfo = vartypeinfo + numlocals * block_count;
709 memset(vartype,TYPE_VOID,numlocals * (block_count+1) * sizeof(typeinfo));
710 memset(vartypeinfo,0,numlocals * (block_count+1) * sizeof(typeinfo));
712 LOG("Variable buffer initialized.\n");
714 /* allocate the buffer for storing JSR target chains */
715 jsrbuffer = DMNEW(jsr_record*,block_count);
716 memset(jsrbuffer,0,block_count * sizeof(jsr_record*));
719 LOG("jsrbuffer initialized.\n");
721 /* allocate the buffer of active exception handlers */
722 handlers = DMNEW(xtable*,method->exceptiontablelength + 1);
724 /* initialize the variable types of the first block */
725 /* to the types of the arguments */
729 /* if this is an instance method initialize the "this" ref type */
730 if (!(method->flags & ACC_STATIC)) {
731 *ttype++ = TYPE_ADDRESS;
733 TYPEINFO_INIT_NEWOBJECT(*tinfo,NULL);
735 TYPEINFO_INIT_CLASSINFO(*tinfo,class);
739 LOG("'this' argument set.\n");
741 /* the rest of the arguments and the return type */
742 typeinfo_init_from_method_args(method->descriptor,ttype,tinfo,
743 numlocals - (tinfo-vartypeinfo),
744 true, /* two word types use two slots */
745 &returntype,&returntypeinfo);
747 LOG("Arguments set.\n");
749 /* initialize the input stack of exception handlers */
750 for (i=0; i<method->exceptiontablelength; ++i) {
751 cls = extable[i].catchtype;
752 if (!cls) cls = class_java_lang_Throwable;
753 LOGSTR1("handler %i: ",i); LOGSTRu(cls->name); LOGNL;
754 TYPEINFO_INIT_CLASSINFO(extable[i].handler->instack->typeinfo,cls);
757 LOG("Exception handler stacks set.\n");
759 /* loop while there are still blocks to be checked */
761 TYPECHECK_COUNT(count_iterations);
765 b_count = block_count;
768 while (--b_count >= 0) {
769 LOGSTR1("---- BLOCK %04d, ",bptr-block);
770 LOGSTR1("blockflags: %d\n",bptr->flags);
773 if (bptr->flags == BBTYPECHECK_REACHED) {
774 LOGSTR1("\n---- BLOCK %04d ------------------------------------------------\n",bptr-block);
777 superblockend = false;
778 bptr->flags = BBFINISHED;
779 b_index = bptr - block;
781 /* init stack at the start of this block */
782 curstack = bptr->instack;
784 /* determine the active exception handlers for this block */
785 /* XXX could use a faster algorithm with sorted lists or
788 for (i=0; i<method->exceptiontablelength; ++i) {
789 if ((extable[i].start <= bptr) && (extable[i].end > bptr)) {
790 LOG1("active handler L%03d",extable[i].handler->debug_nr);
791 handlers[len++] = extable + i;
794 handlers[len] = NULL;
796 /* init variable types at the start of this block */
797 for (i=0; i<numlocals; ++i) {
798 vtype[i] = vartype[numlocals*b_index + i];
799 TYPEINFO_COPY(vartypeinfo[numlocals*b_index + i],vinfo[i]);
802 vtype[i] == TYPE_ADR && TYPEINFO_IS_NEWOBJECT(vinfo[i]))
803 panic("Uninitialized object in local variable inside try block");
806 /* init JSR target chain */
807 if ((jsrchain = jsrbuffer[b_index]) != NULL) {
808 #ifdef TYPECHECK_VERBOSE
809 if (typecheckverbose) {
810 LOGSTR("jsr chain:");
813 LOGSTR1(" L%03d",jsrtemp->target->debug_nr);
814 jsrtemp = jsrtemp->next;
821 subroutine = jsrbuffer[jsrchain->target - block];
822 memcpy(touched,jsrchain->touched,sizeof(u1)*numlocals);
826 #ifdef TYPECHECK_VERBOSE
827 if (typecheckverbose) {
828 if (subroutine) {LOGSTR1("subroutine L%03d\n",subroutine->target->debug_nr);LOGFLUSH;}
829 typeinfo_print_block(get_logfile(),curstack,numlocals,vtype,vinfo,(jsrchain) ? touched : NULL);
834 /* loop over the instructions */
838 DOLOG(show_icmd(iptr,false));
848 /****************************************/
849 /* STACK MANIPULATIONS */
851 /* We just need to copy the typeinfo */
852 /* for slots containing addresses. */
854 /* XXX We assume that the destination stack
855 * slots were continuously allocated in
856 * memory. (The current implementation in
861 COPYTYPE(curstack,dst);
865 COPYTYPE(curstack,dst);
866 COPYTYPE(curstack,dst-2);
867 COPYTYPE(curstack->prev,dst-1);
871 COPYTYPE(curstack,dst);
872 COPYTYPE(curstack,dst-3);
873 COPYTYPE(curstack->prev,dst-1);
874 COPYTYPE(curstack->prev->prev,dst-2);
878 COPYTYPE(curstack,dst);
879 COPYTYPE(curstack->prev,dst-1);
883 COPYTYPE(curstack,dst);
884 COPYTYPE(curstack->prev,dst-1);
885 COPYTYPE(curstack,dst-3);
886 COPYTYPE(curstack->prev,dst-4);
887 COPYTYPE(curstack->prev->prev,dst-2);
891 COPYTYPE(curstack,dst);
892 COPYTYPE(curstack->prev,dst-1);
893 COPYTYPE(curstack,dst-4);
894 COPYTYPE(curstack->prev,dst-5);
895 COPYTYPE(curstack->prev->prev,dst-2);
896 COPYTYPE(curstack->prev->prev->prev,dst-3);
900 COPYTYPE(curstack,dst-1);
901 COPYTYPE(curstack->prev,dst);
904 /****************************************/
905 /* LOADING ADDRESS FROM VARIABLE */
908 CHECK_ONEWORD(iptr->op1,TYPE_ADR);
910 /* loading a returnAddress is not allowed */
911 if (TYPEINFO_IS_PRIMITIVE(vinfo[iptr->op1]))
912 panic("illegal instruction: ALOAD loading returnAddress");
914 TYPEINFO_COPY(vinfo[iptr->op1],dst->typeinfo);
917 /****************************************/
918 /* STORING ADDRESS TO VARIABLE */
922 TYPEINFO_IS_NEWOBJECT(curstack->typeinfo))
923 panic("Storing uninitialized object in local variable inside try block");
925 STORE_ONEWORD(iptr->op1,TYPE_ADDRESS);
926 TYPEINFO_COPY(curstack->typeinfo,vinfo[iptr->op1]);
929 /****************************************/
930 /* LOADING ADDRESS FROM ARRAY */
933 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(curstack->prev->typeinfo))
934 panic("illegal instruction: AALOAD on non-reference array");
936 typeinfo_init_component(&curstack->prev->typeinfo,&dst->typeinfo);
940 /****************************************/
944 if (!TYPEINFO_IS_REFERENCE(curstack->prev->typeinfo))
945 panic("illegal instruction: PUTFIELD on non-reference");
946 if (TYPEINFO_IS_ARRAY(curstack->prev->typeinfo)) /* XXX arraystub */
947 panic("illegal instruction: PUTFIELD on array");
960 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
961 panic("illegal instruction: GETFIELD on non-reference");
962 if (TYPEINFO_IS_ARRAY(curstack->typeinfo))
963 panic("illegal instruction: GETFIELD on array");
966 fieldinfo *fi = (fieldinfo *)(iptr->val.a);
967 /* XXX check non-static? */
968 if (dst->type == TYPE_ADR) {
969 TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi);
972 /* XXX check field type? */
973 TYPEINFO_INIT_PRIMITIVE(dst->typeinfo);
981 fieldinfo *fi = (fieldinfo *)(iptr->val.a);
982 /* XXX check static? */
983 if (dst->type == TYPE_ADR) {
984 TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi);
987 /* XXX check field type? */
988 TYPEINFO_INIT_PRIMITIVE(dst->typeinfo);
994 /****************************************/
995 /* PRIMITIVE ARRAY ACCESS */
997 case ICMD_ARRAYLENGTH:
998 /* XXX should this also work on arraystubs? */
999 if (!TYPEINFO_MAYBE_ARRAY(curstack->typeinfo))
1000 panic("illegal instruction: ARRAYLENGTH on non-array");
1005 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_BOOLEAN)
1006 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_BYTE))
1007 panic("Array type mismatch");
1011 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_CHAR))
1012 panic("Array type mismatch");
1016 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_DOUBLE))
1017 panic("Array type mismatch");
1021 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_FLOAT))
1022 panic("Array type mismatch");
1026 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_INT))
1027 panic("Array type mismatch");
1031 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_SHORT))
1032 panic("Array type mismatch");
1036 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_LONG))
1037 panic("Array type mismatch");
1042 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_BOOLEAN)
1043 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_BYTE))
1044 panic("Array type mismatch");
1048 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_CHAR))
1049 panic("Array type mismatch");
1053 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_DOUBLE))
1054 panic("Array type mismatch");
1058 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_FLOAT))
1059 panic("Array type mismatch");
1063 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_INT))
1064 panic("Array type mismatch");
1068 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_SHORT))
1069 panic("Array type mismatch");
1073 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_LONG))
1074 panic("Array type mismatch");
1078 /****************************************/
1079 /* OPERATIONS WITH UNCHECKED INPUT */
1081 case ICMD_CHECKCAST:
1082 TYPECHECK_ADR(curstack);
1083 /* returnAddress is not allowed */
1084 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1085 panic("Illegal instruction: CHECKCAST on non-reference");
1087 /* XXX check if the cast can be done statically */
1088 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,(classinfo *)iptr[0].val.a);
1093 case ICMD_INSTANCEOF:
1094 TYPECHECK_ADR(curstack);
1095 /* returnAddress is not allowed */
1096 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1097 panic("Illegal instruction: INSTANCEOF on non-reference");
1099 /* XXX optimize statically? */
1103 if (iptr->val.a == NULL)
1104 TYPEINFO_INIT_NULLTYPE(dst->typeinfo);
1106 /* XXX constants for builtin functions */
1107 /* string constants */
1108 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,class_java_lang_String);
1111 /****************************************/
1112 /* BRANCH INSTRUCTIONS */
1115 superblockend = true;
1118 case ICMD_IFNONNULL:
1125 case ICMD_IF_ICMPEQ:
1126 case ICMD_IF_ICMPNE:
1127 case ICMD_IF_ICMPLT:
1128 case ICMD_IF_ICMPGE:
1129 case ICMD_IF_ICMPGT:
1130 case ICMD_IF_ICMPLE:
1131 case ICMD_IF_ACMPEQ:
1132 case ICMD_IF_ACMPNE:
1139 case ICMD_IF_LCMPEQ:
1140 case ICMD_IF_LCMPNE:
1141 case ICMD_IF_LCMPLT:
1142 case ICMD_IF_LCMPGE:
1143 case ICMD_IF_LCMPGT:
1144 case ICMD_IF_LCMPLE:
1145 tbptr = (basicblock *) iptr->target;
1147 /* propagate stack and variables to the target block */
1148 TYPECHECK_REACH(REACH_STD);
1152 /****************************************/
1155 case ICMD_TABLESWITCH:
1157 s4 *s4ptr = iptr->val.a;
1158 s4ptr++; /* skip default */
1159 i = *s4ptr++; /* low */
1160 i = *s4ptr++ - i + 2; /* +1 for default target */
1162 goto switch_instruction_tail;
1164 case ICMD_LOOKUPSWITCH:
1166 s4 *s4ptr = iptr->val.a;
1167 s4ptr++; /* skip default */
1168 i = *s4ptr++ + 1; /* count +1 for default target */
1170 switch_instruction_tail:
1171 tptr = (basicblock **)iptr->target;
1175 LOG2("target %d is block %04d",(tptr-(basicblock **)iptr->target)-1,tbptr-block);
1176 TYPECHECK_REACH(REACH_STD);
1179 superblockend = true;
1182 /****************************************/
1183 /* RETURNS AND THROW */
1186 TYPEINFO_INIT_CLASSINFO(tempinfo,class_java_lang_Throwable);
1187 if (!typeinfo_is_assignable(&curstack->typeinfo,&tempinfo))
1188 panic("illegal instruction: ATHROW on non-Throwable");
1189 superblockend = true;
1194 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1195 panic("illegal instruction: ARETURN on non-reference");
1197 if (returntype != TYPE_ADDRESS
1198 || !typeinfo_is_assignable(&curstack->typeinfo,&returntypeinfo))
1199 panic("Return type mismatch");
1203 if (returntype != TYPE_INT) panic("Return type mismatch");
1207 if (returntype != TYPE_LONG) panic("Return type mismatch");
1211 if (returntype != TYPE_FLOAT) panic("Return type mismatch");
1215 if (returntype != TYPE_DOUBLE) panic("Return type mismatch");
1219 if (returntype != TYPE_VOID) panic("Return type mismatch");
1222 superblockend = true;
1226 /****************************************/
1227 /* SUBROUTINE INSTRUCTIONS */
1232 /* XXX This is a dirty hack. It is needed
1233 * because of the special handling of ICMD_JSR in stack.c
1235 dst = (stackptr) iptr->val.a;
1237 /* push return address */
1238 TYPEINFO_INIT_PRIMITIVE(dst->typeinfo);
1240 LOG("reaching block...");
1242 /* add the target to the JSR target chain and */
1243 /* propagate stack and variables to the target block */
1244 tbptr = (basicblock *) iptr->target;
1245 TYPECHECK_REACH(REACH_JSR);
1247 /* set dst to the stack after the subroutine execution */
1248 /* XXX We assume (as in stack.c) that the
1249 * subroutine returns the stack as it was
1250 * before the JSR instruction. Is this
1255 /* Find the jsr_record of the called subroutine */
1256 jsrtemp = jsrbuffer[tbptr - block];
1258 /* Check if we already calculated (at least
1259 * for one RET) which variables the
1260 * subroutine touches.
1262 if (jsrtemp->sbr_touched) {
1263 /* Calculate the local variables after the subroutine call */
1264 for (i=0; i<numlocals; ++i)
1265 if (jsrtemp->sbr_touched[i] != TOUCHED_NO) {
1267 if ((vtype[i] = jsrtemp->sbr_vtype[i]) == TYPE_ADR)
1268 TYPEINFO_CLONE(jsrtemp->sbr_vinfo[i],vinfo[i]);
1271 /* continue after the JSR call */
1272 superblockend = false;
1275 /* We cannot proceed until the subroutine has been typechecked. */
1276 /* XXX actually we would not have to check this block again */
1277 bptr->flags = BBTYPECHECK_REACHED;
1279 superblockend = true;
1281 /* XXX may throw? I don't think. */
1285 /* check returnAddress variable */
1286 CHECK_ONEWORD(iptr->op1,TYPE_ADR);
1288 if (!TYPEINFO_IS_PRIMITIVE(vinfo[iptr->op1]))
1289 panic("illegal instruction: RET using non-returnAddress variable");
1291 /* check if we are inside a subroutine */
1293 panic("RET outside of subroutine");
1295 /* determine which variables are touched by this subroutine */
1296 /* and their types */
1297 if (subroutine->sbr_touched) {
1298 for (i=0; i<numlocals; ++i)
1299 subroutine->sbr_touched[i] |= touched[i];
1300 ttype = subroutine->sbr_vtype;
1301 tinfo = subroutine->sbr_vinfo;
1302 TYPECHECK_MERGEVARS;
1305 subroutine->sbr_touched = DMNEW(u1,numlocals);
1306 memcpy(subroutine->sbr_touched,touched,sizeof(u1)*numlocals);
1307 subroutine->sbr_vtype = DMNEW(u1,numlocals);
1308 memcpy(subroutine->sbr_vtype,vtype,sizeof(u1)*numlocals);
1309 subroutine->sbr_vinfo = DMNEW(typeinfo,numlocals);
1310 for (i=0; i<numlocals; ++i)
1311 if (vtype[i] == TYPE_ADR)
1312 TYPEINFO_CLONE(vinfo[i],subroutine->sbr_vinfo[i]);
1314 /* XXX check if subroutine changed types? */
1316 LOGSTR("subroutine touches:");
1317 DOLOG(typeinfo_print_locals(get_logfile(),subroutine->sbr_vtype,subroutine->sbr_vinfo,
1318 subroutine->sbr_touched,numlocals));
1321 /* reach blocks after JSR statements */
1322 for (i=0; i<block_count; ++i) {
1324 LOG1("block L%03d",tbptr->debug_nr);
1325 if (tbptr->iinstr[tbptr->icount - 1].opc != ICMD_JSR)
1327 LOG("ends with JSR");
1328 if ((basicblock*) tbptr->iinstr[tbptr->icount - 1].target != subroutine->target)
1332 LOG1("RET reaches block %04d",tbptr-block);
1334 /*TYPECHECK_REACH(REACH_RET);*/
1337 superblockend = true;
1340 /****************************************/
1343 case ICMD_INVOKEVIRTUAL:
1344 case ICMD_INVOKESPECIAL:
1345 case ICMD_INVOKESTATIC:
1346 case ICMD_INVOKEINTERFACE:
1348 /* XXX check if this opcode may invoke this method */
1349 /* XXX check access rights */
1351 methodinfo *mi = (methodinfo*) iptr->val.a;
1352 bool callinginit = (opcode == ICMD_INVOKESPECIAL && mi->name == name_init);
1354 classinfo *initclass;
1356 /* XXX for INVOKESPECIAL: check if the invokation is done at all */
1358 /* fetch parameter types and return type */
1359 /* XXX might use dst->typeinfo directly if non void */
1361 if (opcode != ICMD_INVOKESTATIC) {
1362 ptype[0] = TYPE_ADR;
1363 TYPEINFO_INIT_CLASSINFO(pinfo[0],mi->class);
1366 typeinfo_init_from_method_args(mi->descriptor,ptype+i,pinfo+i,
1370 /* check parameter types */
1371 srcstack = curstack;
1372 i = mi->paramcount; /* number of parameters including 'this'*/
1375 if (srcstack->type != ptype[i])
1376 panic("Parameter type mismatch in method invocation");
1377 if (srcstack->type == TYPE_ADR) {
1378 LOGINFO(&(srcstack->typeinfo));
1380 if (i==0 && callinginit)
1382 /* first argument to <init> method */
1383 if (!TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo))
1384 panic("Calling <init> on initialized object");
1386 /* get the address of the NEW instruction */
1387 LOGINFO(&(srcstack->typeinfo));
1388 ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(srcstack->typeinfo);
1389 initclass = (ins) ? (classinfo*)ins[-1].val.a : method->class;
1390 LOGSTR("class: "); LOGSTRu(initclass->name); LOGNL;
1392 /* XXX check type */
1395 if (!typeinfo_is_assignable(&(srcstack->typeinfo),pinfo+i))
1396 panic("Parameter reference type mismatch in method invocation");
1401 srcstack = srcstack->prev;
1404 LOG("checking return type");
1405 if (rtype != TYPE_VOID) {
1406 if (rtype != dst->type)
1407 panic("Return type mismatch in method invocation");
1408 TYPEINFO_COPY(rinfo,dst->typeinfo);
1412 LOG("replacing uninitialized object");
1413 /* replace uninitialized object type on stack */
1416 if (srcstack->type == TYPE_ADR
1417 && TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo)
1418 && TYPEINFO_NEWOBJECT_INSTRUCTION(srcstack->typeinfo) == ins)
1420 LOG("replacing uninitialized type on stack");
1421 TYPEINFO_INIT_CLASSINFO(srcstack->typeinfo,initclass);
1423 srcstack = srcstack->prev;
1425 /* replace uninitialized object type in locals */
1426 for (i=0; i<numlocals; ++i) {
1427 if (vtype[i] == TYPE_ADR
1428 && TYPEINFO_IS_NEWOBJECT(vinfo[i])
1429 && TYPEINFO_NEWOBJECT_INSTRUCTION(vinfo[i]) == ins)
1431 LOG1("replacing uninitialized type in local %d",i);
1432 TYPEINFO_INIT_CLASSINFO(vinfo[i],initclass);
1436 /* initializing the 'this' reference? */
1437 if (initmethod && !ins) {
1438 /* set our marker variable to type int */
1439 LOG("setting <init> marker");
1440 vtype[numlocals-1] = TYPE_INT;
1447 case ICMD_MULTIANEWARRAY:
1448 /* check the array lengths on the stack */
1450 if (i<1) panic("MULTIANEWARRAY with dimensions < 1");
1451 srcstack = curstack;
1454 panic("MULTIANEWARRAY missing array length");
1455 if (srcstack->type != TYPE_INT)
1456 panic("MULTIANEWARRAY using non-int as array length");
1457 srcstack = srcstack->prev;
1460 /* set the array type of the result */
1461 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,((vftbl *)iptr[0].val.a)->class);
1466 if (ISBUILTIN(asm_builtin_aastore)) {
1467 TYPECHECK_ADR(curstack);
1468 TYPECHECK_INT(curstack->prev);
1469 TYPECHECK_ADR(curstack->prev->prev);
1470 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(curstack->prev->prev->typeinfo))
1471 panic("illegal instruction: AASTORE to non-reference array");
1475 typeinfo_init_component(&curstack->prev->prev->typeinfo,&tempinfo);
1476 if (!typeinfo_is_assignable(&curstack->typeinfo,&tempinfo))
1477 panic("illegal instruction: AASTORE to incompatible type");
1480 /* XXX check for missed builtins in debug mode? */
1481 maythrow = true; /* XXX better safe than sorry */
1486 #if defined(__I386__)
1487 ISBUILTIN(asm_builtin_newarray)
1489 ISBUILTIN(builtin_newarray)
1493 TYPECHECK_INT(curstack->prev);
1494 if (iptr[-1].opc != ICMD_ACONST)
1495 panic("illegal instruction: builtin_newarray without classinfo");
1496 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,((vftbl *)iptr[-1].val.a)->class);
1498 else if (ISBUILTIN(asm_builtin_checkarraycast)) {
1499 TYPECHECK_ADR(curstack->prev);
1500 if (iptr[-1].opc != ICMD_ACONST)
1501 panic("illegal instruction: asm_builtin_checkarraycast without classinfo");
1502 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,((vftbl *)iptr[-1].val.a)->class);
1504 /* XXX check for missed builtins in debug mode? */
1505 maythrow = true; /* XXX better safe than sorry */
1509 if (ISBUILTIN(builtin_new)) {
1510 if (iptr[-1].opc != ICMD_ACONST)
1511 panic("illegal instruction: builtin_new without classinfo");
1512 TYPEINFO_INIT_NEWOBJECT(dst->typeinfo,iptr);
1514 /* XXX unify the following cases */
1515 else if (ISBUILTIN(builtin_newarray_boolean)) {
1516 TYPECHECK_INT(curstack);
1517 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BOOLEAN);
1519 else if (ISBUILTIN(builtin_newarray_char)) {
1520 TYPECHECK_INT(curstack);
1521 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_CHAR);
1523 else if (ISBUILTIN(builtin_newarray_float)) {
1524 TYPECHECK_INT(curstack);
1525 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_FLOAT);
1527 else if (ISBUILTIN(builtin_newarray_double)) {
1528 TYPECHECK_INT(curstack);
1529 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_DOUBLE);
1531 else if (ISBUILTIN(builtin_newarray_byte)) {
1532 TYPECHECK_INT(curstack);
1533 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BYTE);
1535 else if (ISBUILTIN(builtin_newarray_short)) {
1536 TYPECHECK_INT(curstack);
1537 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_SHORT);
1539 else if (ISBUILTIN(builtin_newarray_int)) {
1540 TYPECHECK_INT(curstack);
1541 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_INT);
1543 else if (ISBUILTIN(builtin_newarray_long)) {
1544 TYPECHECK_INT(curstack);
1545 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_LONG);
1547 /* XXX check for missed builtins in debug mode? */
1548 maythrow = true; /* XXX better safe than sorry */
1551 /****************************************/
1552 /* PRIMITIVE VARIABLE ACCESS */
1554 case ICMD_ILOAD: CHECK_ONEWORD(iptr->op1,TYPE_INT); break;
1555 case ICMD_FLOAD: CHECK_ONEWORD(iptr->op1,TYPE_FLOAT); break;
1556 case ICMD_IINC: CHECK_ONEWORD(iptr->op1,TYPE_INT); break;
1557 case ICMD_LLOAD: CHECK_TWOWORD(iptr->op1,TYPE_LONG); break;
1558 case ICMD_DLOAD: CHECK_TWOWORD(iptr->op1,TYPE_DOUBLE); break;
1560 case ICMD_FSTORE: STORE_ONEWORD(iptr->op1,TYPE_FLOAT); break;
1561 case ICMD_ISTORE: STORE_ONEWORD(iptr->op1,TYPE_INT); break;
1562 case ICMD_LSTORE: STORE_TWOWORD(iptr->op1,TYPE_LONG); break;
1563 case ICMD_DSTORE: STORE_TWOWORD(iptr->op1,TYPE_DOUBLE); break;
1565 /****************************************/
1566 /* INSTRUCTIONS WHICH SHOULD HAVE BEEN */
1567 /* REPLACED BY BUILTIN CALLS */
1571 case ICMD_ANEWARRAY:
1572 case ICMD_MONITORENTER:
1573 case ICMD_MONITOREXIT:
1575 /* XXX only check this in debug mode? */
1576 LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
1577 LOG("Should have been converted to builtin function call.");
1578 panic("Internal error: unexpected instruction encountered");
1581 /****************************************/
1582 /* UNCHECKED OPERATIONS */
1584 /* These ops have no input or output to be checked */
1585 /* (apart from the checks done in analyse_stack). */
1586 /* XXX only add cases for them in debug mode? */
1591 case ICMD_READONLY_ARG: /* XXX ? */
1592 case ICMD_CLEAR_ARGREN: /* XXX ? */
1595 case ICMD_CHECKASIZE:
1596 case ICMD_NULLCHECKPOP:
1600 /****************************************/
1601 /* ARITHMETIC AND CONVERSION */
1602 /* (These instructions are typechecked in analyse_stack.) */
1604 /* The following instructions may throw a runtime exception: */
1614 /* The following instructions never throw a runtime exception: */
1615 /* XXX only add cases for them in debug mode? */
1622 case ICMD_IFEQ_ICONST:
1623 case ICMD_IFNE_ICONST:
1624 case ICMD_IFLT_ICONST:
1625 case ICMD_IFGE_ICONST:
1626 case ICMD_IFGT_ICONST:
1627 case ICMD_IFLE_ICONST:
1628 case ICMD_ELSE_ICONST:
1650 case ICMD_IREM0X10001:
1651 case ICMD_LREM0X10001:
1654 case ICMD_IADDCONST:
1655 case ICMD_ISUBCONST:
1656 case ICMD_IMULCONST:
1657 case ICMD_IANDCONST:
1659 case ICMD_IXORCONST:
1660 case ICMD_ISHLCONST:
1661 case ICMD_ISHRCONST:
1662 case ICMD_IUSHRCONST:
1664 case ICMD_LADDCONST:
1665 case ICMD_LSUBCONST:
1666 case ICMD_LMULCONST:
1667 case ICMD_LANDCONST:
1669 case ICMD_LXORCONST:
1670 case ICMD_LSHLCONST:
1671 case ICMD_LSHRCONST:
1672 case ICMD_LUSHRCONST:
1689 case ICMD_INT2SHORT:
1692 case ICMD_LCMPCONST:
1713 /****************************************/
1716 LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
1717 panic("Missing ICMD code during typecheck");
1720 /* the output of this instruction becomes the current stack */
1723 /* reach exception handlers for this instruction */
1725 LOG("reaching exception handlers");
1727 while (handlers[i]) {
1728 tbptr = handlers[i]->handler;
1729 TYPECHECK_REACH(REACH_THROW); /* XXX jsr chain? */
1735 DOLOG(typeinfo_print_block(get_logfile(),curstack,numlocals,vtype,vinfo,(jsrchain) ? touched : NULL));
1740 } /* while instructions */
1742 LOG("instructions done");
1743 LOGSTR("RESULT=> ");
1744 DOLOG(typeinfo_print_block(get_logfile(),curstack,numlocals,vtype,vinfo,(jsrchain) ? touched : NULL));
1747 /* propagate stack and variables to the following block */
1748 if (!superblockend) {
1749 LOG("reaching following block");
1751 while (tbptr->flags == BBDELETED) {
1753 #ifdef TYPECHECK_DEBUG
1754 if ((tbptr-block) >= block_count)
1755 panic("Control flow falls off the last block");
1758 TYPECHECK_REACH(REACH_STD);
1761 } /* if block has to be checked */
1763 } /* while blocks */
1765 LOGIF(repeat,"repeat=true");
1768 #ifdef TYPECHECK_STATISTICS
1769 dolog("Typechecker did %4d iterations",count_iterations);
1772 #ifdef TYPECHECK_DEBUG
1773 for (i=0; i<block_count; ++i) {
1774 if (block[i].flags != BBDELETED
1775 && block[i].flags != BBUNDEF
1776 && block[i].flags != BBFINISHED)
1778 LOG2("block L%03d has invalid flags after typecheck: %d",
1779 block[i].debug_nr,block[i].flags);
1780 panic("Invalid block flags after typecheck");
1785 LOGimp("exiting typecheck");
1790 #endif /* CACAO_TYPECHECK */
1793 * These are local overrides for various environment variables in Emacs.
1794 * Please do not remove this and leave it at the end of the file, where
1795 * Emacs will automagically detect them.
1796 * ---------------------------------------------------------------------
1799 * indent-tabs-mode: t