1 /* src/vm/jit/verify/icmds.c - ICMD-specific type checking code
3 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
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., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contact: cacao@cacaojvm.org
27 Authors: Edwin Steiner
35 /* this marker is needed by generate.pl: */
38 /****************************************/
41 /* We just need to copy the typeinfo */
42 /* for slots containing addresses. */
44 /* (These are only used by the variables based verifier.) */
46 case ICMD_MOVE: /* {VARIABLESBASED} */
47 case ICMD_COPY: /* {VARIABLESBASED} */
48 TYPECHECK_COUNT(stat_ins_stack);
49 COPYTYPE(IPTR->s1, IPTR->dst);
50 DST->type = OP1->type;
53 /****************************************/
54 /* LOADING ADDRESS FROM VARIABLE */
57 TYPECHECK_COUNT(stat_ins_aload);
59 /* loading a returnAddress is not allowed */
60 if (!TYPEDESC_IS_REFERENCE(*OP1)) {
61 VERIFY_ERROR("illegal instruction: ALOAD loading non-reference");
63 TYPEINFO_COPY(OP1->typeinfo,DST->typeinfo);
66 /****************************************/
67 /* STORING ADDRESS TO VARIABLE */
70 TYPEINFO_COPY(OP1->typeinfo, DST->typeinfo);
73 /****************************************/
74 /* LOADING ADDRESS FROM ARRAY */
77 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(OP1->typeinfo))
78 VERIFY_ERROR("illegal instruction: AALOAD on non-reference array");
80 if (!typeinfo_init_component(&OP1->typeinfo,&DST->typeinfo))
84 /****************************************/
87 case ICMD_PUTFIELD: /* {STACKBASED} */
89 if (!IS_CAT1(stack[0])) {
93 CHECK_STACK_TYPE(stack[-1], TYPE_ADR);
94 stack = typecheck_stackbased_verify_fieldaccess(STATE, stack-1, stack, stack-2);
99 case ICMD_PUTSTATIC: /* {STACKBASED} */
100 CHECK_STACK_DEPTH(1);
101 if (!IS_CAT1(stack[0])) {
102 /* (stack depth >= 2 is guaranteed) */
105 stack = typecheck_stackbased_verify_fieldaccess(STATE, NULL, stack, stack-1);
110 case ICMD_GETFIELD: /* {STACKBASED} */
111 CHECK_STACK_TYPE(stack[0], TYPE_ADR);
112 stack = typecheck_stackbased_verify_fieldaccess(STATE, stack, NULL, stack-1);
117 case ICMD_GETSTATIC: /* {STACKBASED} */
118 stack = typecheck_stackbased_verify_fieldaccess(STATE, NULL, NULL, stack);
123 case ICMD_PUTFIELD: /* {VARIABLESBASED} */
124 if (!verify_fieldaccess(state, VAROP(iptr->s1), VAROP(iptr->sx.s23.s2)))
129 case ICMD_PUTSTATIC: /* {VARIABLESBASED} */
130 if (!verify_fieldaccess(state, NULL, VAROP(iptr->s1)))
135 case ICMD_PUTFIELDCONST: /* {VARIABLESBASED} */
136 /* XXX this mess will go away with const operands */
137 INSTRUCTION_GET_FIELDREF(state->iptr, fieldref);
138 constvalue.type = fieldref->parseddesc.fd->type;
139 if (IS_ADR_TYPE(constvalue.type)) {
140 if (state->iptr->sx.val.anyptr) {
141 classinfo *cc = (state->iptr->flags.bits & INS_FLAG_CLASS)
142 ? class_java_lang_Class : class_java_lang_String;
144 assert(cc->state & CLASS_LINKED);
145 typeinfo_init_classinfo(&(constvalue.typeinfo), cc);
148 TYPEINFO_INIT_NULLTYPE(constvalue.typeinfo);
151 if (!verify_fieldaccess(state, VAROP(iptr->s1), &constvalue))
156 case ICMD_PUTSTATICCONST: /* {VARIABLESBASED} */
157 /* XXX this mess will go away with const operands */
158 INSTRUCTION_GET_FIELDREF(state->iptr, fieldref);
159 constvalue.type = fieldref->parseddesc.fd->type;
160 if (IS_ADR_TYPE(constvalue.type)) {
161 if (state->iptr->sx.val.anyptr) {
162 classinfo *cc = (state->iptr->flags.bits & INS_FLAG_CLASS)
163 ? class_java_lang_Class : class_java_lang_String;
165 assert(cc->state & CLASS_LINKED);
166 typeinfo_init_classinfo(&(constvalue.typeinfo), cc);
169 TYPEINFO_INIT_NULLTYPE(constvalue.typeinfo);
172 if (!verify_fieldaccess(state, NULL, &constvalue))
177 case ICMD_GETFIELD: /* {VARIABLESBASED} */
178 if (!verify_fieldaccess(state, VAROP(iptr->s1), NULL))
183 case ICMD_GETSTATIC: /* {VARIABLESBASED} */
184 if (!verify_fieldaccess(state, NULL, NULL))
189 /****************************************/
190 /* PRIMITIVE ARRAY ACCESS */
192 case ICMD_ARRAYLENGTH:
193 if (!TYPEINFO_MAYBE_ARRAY(OP1->typeinfo)
194 && OP1->typeinfo.typeclass.cls != pseudo_class_Arraystub)
195 VERIFY_ERROR("illegal instruction: ARRAYLENGTH on non-array");
199 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_BOOLEAN)
200 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_BYTE))
201 VERIFY_ERROR("Array type mismatch");
205 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_CHAR))
206 VERIFY_ERROR("Array type mismatch");
210 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_DOUBLE))
211 VERIFY_ERROR("Array type mismatch");
215 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_FLOAT))
216 VERIFY_ERROR("Array type mismatch");
220 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_INT))
221 VERIFY_ERROR("Array type mismatch");
225 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_SHORT))
226 VERIFY_ERROR("Array type mismatch");
230 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_LONG))
231 VERIFY_ERROR("Array type mismatch");
235 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_BOOLEAN)
236 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_BYTE))
237 VERIFY_ERROR("Array type mismatch");
241 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_CHAR))
242 VERIFY_ERROR("Array type mismatch");
246 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_DOUBLE))
247 VERIFY_ERROR("Array type mismatch");
251 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_FLOAT))
252 VERIFY_ERROR("Array type mismatch");
256 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_INT))
257 VERIFY_ERROR("Array type mismatch");
261 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_SHORT))
262 VERIFY_ERROR("Array type mismatch");
266 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_LONG))
267 VERIFY_ERROR("Array type mismatch");
271 /* we just check the basic input types and that the */
272 /* destination is an array of references. Assignability to */
273 /* the actual array must be checked at runtime, each time the */
274 /* instruction is performed. (See builtin_canstore.) */
275 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(OP1->typeinfo))
276 VERIFY_ERROR("illegal instruction: AASTORE to non-reference array");
279 case ICMD_IASTORECONST:
280 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_INT))
281 VERIFY_ERROR("Array type mismatch");
284 case ICMD_LASTORECONST:
285 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_LONG))
286 VERIFY_ERROR("Array type mismatch");
289 case ICMD_BASTORECONST:
290 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_BOOLEAN)
291 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_BYTE))
292 VERIFY_ERROR("Array type mismatch");
295 case ICMD_CASTORECONST:
296 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_CHAR))
297 VERIFY_ERROR("Array type mismatch");
300 case ICMD_SASTORECONST:
301 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_SHORT))
302 VERIFY_ERROR("Array type mismatch");
305 /****************************************/
306 /* ADDRESS CONSTANTS */
309 if (IPTR->flags.bits & INS_FLAG_CLASS) {
310 /* a java.lang.Class reference */
311 TYPEINFO_INIT_JAVA_LANG_CLASS(DST->typeinfo,IPTR->sx.val.c);
314 if (IPTR->sx.val.anyptr == NULL)
315 TYPEINFO_INIT_NULLTYPE(DST->typeinfo);
317 /* string constant (or constant for builtin function) */
318 typeinfo_init_classinfo(&(DST->typeinfo),class_java_lang_String);
323 /****************************************/
324 /* CHECKCAST AND INSTANCEOF */
327 /* returnAddress is not allowed */
328 if (!TYPEINFO_IS_REFERENCE(OP1->typeinfo))
329 VERIFY_ERROR("Illegal instruction: CHECKCAST on non-reference");
331 if (!typeinfo_init_class(&(DST->typeinfo),IPTR->sx.s23.s3.c))
335 case ICMD_INSTANCEOF:
336 /* returnAddress is not allowed */
337 if (!TYPEINFO_IS_REFERENCE(OP1->typeinfo))
338 VERIFY_ERROR("Illegal instruction: INSTANCEOF on non-reference");
341 /****************************************/
342 /* BRANCH INSTRUCTIONS */
379 case ICMD_IF_FCMPL_LT:
380 case ICMD_IF_FCMPL_GE:
381 case ICMD_IF_FCMPL_GT:
382 case ICMD_IF_FCMPL_LE:
384 case ICMD_IF_FCMPG_LT:
385 case ICMD_IF_FCMPG_GE:
386 case ICMD_IF_FCMPG_GT:
387 case ICMD_IF_FCMPG_LE:
392 case ICMD_IF_DCMPL_LT:
393 case ICMD_IF_DCMPL_GE:
394 case ICMD_IF_DCMPL_GT:
395 case ICMD_IF_DCMPL_LE:
397 case ICMD_IF_DCMPG_LT:
398 case ICMD_IF_DCMPG_GE:
399 case ICMD_IF_DCMPG_GT:
400 case ICMD_IF_DCMPG_LE:
402 TYPECHECK_COUNT(stat_ins_branch);
404 /* propagate stack and variables to the target block */
408 /****************************************/
411 case ICMD_TABLESWITCH:
413 TYPECHECK_COUNT(stat_ins_switch);
415 table = IPTR->dst.table;
416 i = IPTR->sx.s23.s3.tablehigh
417 - IPTR->sx.s23.s2.tablelow + 1 + 1; /* plus default */
427 case ICMD_LOOKUPSWITCH:
429 TYPECHECK_COUNT(stat_ins_switch);
431 lookup = IPTR->dst.lookup;
432 i = IPTR->sx.s23.s2.lookupcount;
433 REACH(IPTR->sx.s23.s3.lookupdefault);
436 REACH(lookup->target);
444 /****************************************/
445 /* ADDRESS RETURNS AND THROW */
448 TYPECHECK_COUNT(stat_ins_athrow);
449 r = typeinfo_is_assignable_to_class(&OP1->typeinfo,
450 CLASSREF_OR_CLASSINFO(class_java_lang_Throwable));
451 if (r == typecheck_FALSE)
452 VERIFY_ERROR("illegal instruction: ATHROW on non-Throwable");
453 if (r == typecheck_FAIL)
455 if (r == typecheck_MAYBE) {
456 /* the check has to be postponed. we need a patcher */
457 TYPECHECK_COUNT(stat_ins_athrow_unresolved);
458 IPTR->sx.s23.s2.uc = create_unresolved_class(
460 /* XXX make this more efficient, use class_java_lang_Throwable
462 class_get_classref(METHOD->class,utf_java_lang_Throwable),
464 IPTR->flags.bits |= INS_FLAG_UNRESOLVED;
469 TYPECHECK_COUNT(stat_ins_areturn);
470 if (!TYPEINFO_IS_REFERENCE(OP1->typeinfo))
471 VERIFY_ERROR("illegal instruction: ARETURN on non-reference");
473 if (STATE->returntype.type != TYPE_ADR
474 || (r = typeinfo_is_assignable(&OP1->typeinfo,&(STATE->returntype.typeinfo)))
476 VERIFY_ERROR("Return type mismatch");
477 if (r == typecheck_FAIL)
479 if (r == typecheck_MAYBE) {
480 /* the check has to be postponed, we need a patcher */
481 TYPECHECK_COUNT(stat_ins_areturn_unresolved);
482 IPTR->sx.s23.s2.uc = create_unresolved_class(
484 METHOD->parseddesc->returntype.classref,
486 IPTR->flags.bits |= INS_FLAG_UNRESOLVED;
490 /****************************************/
491 /* PRIMITIVE RETURNS */
494 if (STATE->returntype.type != TYPE_INT)
495 VERIFY_ERROR("Return type mismatch");
499 if (STATE->returntype.type != TYPE_LNG)
500 VERIFY_ERROR("Return type mismatch");
504 if (STATE->returntype.type != TYPE_FLT)
505 VERIFY_ERROR("Return type mismatch");
509 if (STATE->returntype.type != TYPE_DBL)
510 VERIFY_ERROR("Return type mismatch");
514 if (STATE->returntype.type != TYPE_VOID)
515 VERIFY_ERROR("Return type mismatch");
518 TYPECHECK_COUNT(stat_ins_primitive_return);
520 if (STATE->initmethod && METHOD->class != class_java_lang_Object) {
521 /* Check if the 'this' instance has been initialized. */
522 LOG("Checking <init> marker");
523 #if defined(TYPECHECK_VARIABLESBASED)
524 if (!typevector_checktype(jd->var,STATE->numlocals-1,TYPE_INT))
526 if (STATE->locals[STATE->numlocals-1].type != TYPE_INT)
528 VERIFY_ERROR("<init> method does not initialize 'this'");
532 /****************************************/
533 /* SUBROUTINE INSTRUCTIONS */
535 case ICMD_JSR: /* {VARIABLESBASED} */
536 TYPEINFO_INIT_RETURNADDRESS(DST->typeinfo, BPTR->next);
537 REACH(IPTR->sx.s23.s3.jsrtarget);
540 case ICMD_JSR: /* {STACKBASED} */
542 tbptr = BLOCK_OF(IPTR->sx.s23.s3.jsrtarget.insindex);
544 TYPEINFO_INIT_RETURNADDRESS(stack[0].typeinfo, tbptr);
547 stack = typecheck_stackbased_jsr(STATE, stack, stackfloor);
552 case ICMD_RET: /* {VARIABLESBASED} */
553 /* check returnAddress variable */
554 if (!typevector_checkretaddr(jd->var,IPTR->s1.varindex))
555 VERIFY_ERROR("illegal instruction: RET using non-returnAddress variable");
559 case ICMD_RET: /* {STACKBASED} */
561 CHECK_LOCAL_TYPE(IPTR->s1.varindex, TYPE_ADR);
562 if (!TYPEINFO_IS_PRIMITIVE(STATE->locals[IPTR->s1.varindex].typeinfo))
563 VERIFY_ERROR("illegal instruction: RET using non-returnAddress variable");
565 if (!typecheck_stackbased_ret(STATE, stack, stackfloor))
569 /****************************************/
572 case ICMD_INVOKEVIRTUAL: /* {VARIABLESBASED} */
573 case ICMD_INVOKESPECIAL: /* {VARIABLESBASED} */
574 case ICMD_INVOKESTATIC: /* {VARIABLESBASED} */
575 case ICMD_INVOKEINTERFACE: /* {VARIABLESBASED} */
576 TYPECHECK_COUNT(stat_ins_invoke);
577 if (!verify_invocation(state))
579 TYPECHECK_COUNTIF(INSTRUCTION_IS_UNRESOLVED(IPTR), stat_ins_invoke_unresolved);
582 case ICMD_INVOKEVIRTUAL: /* {STACKBASED} */
583 case ICMD_INVOKESPECIAL: /* {STACKBASED} */
584 case ICMD_INVOKESTATIC: /* {STACKBASED} */
585 case ICMD_INVOKEINTERFACE: /* {STACKBASED} */
586 TYPECHECK_COUNT(stat_ins_invoke);
588 INSTRUCTION_GET_METHODDESC(IPTR, md);
589 CHECK_STACK_DEPTH(md->paramslots);
591 if (!typecheck_stackbased_verify_invocation(STATE, stack, stackfloor))
594 stack -= md->paramslots;
596 if (md->returntype.type != TYPE_VOID) {
597 if (IS_2_WORD_TYPE(md->returntype.type)) {
598 CHECK_STACK_SPACE(2);
600 stack[0].type = TYPE_VOID;
601 stack[-1].type = md->returntype.type;
604 CHECK_STACK_SPACE(1);
606 stack[0].type = md->returntype.type;
609 TYPECHECK_COUNTIF(INSTRUCTION_IS_UNRESOLVED(IPTR), stat_ins_invoke_unresolved);
612 /****************************************/
615 case ICMD_MULTIANEWARRAY: /* {VARIABLESBASED} */
616 if (!verify_multianewarray(STATE))
620 case ICMD_MULTIANEWARRAY: /* {STACKBASED} */
621 if (!typecheck_stackbased_multianewarray(STATE, stack, stackfloor))
623 stack -= (IPTR->s1.argcount - 1);
624 stack[0].type = TYPE_ADR;
627 /****************************************/
630 case ICMD_BUILTIN: /* {VARIABLESBASED} */
631 TYPECHECK_COUNT(stat_ins_builtin);
632 if (!verify_builtin(state))
636 case ICMD_BUILTIN: /* {STACKBASED} */
637 TYPECHECK_COUNT(stat_ins_builtin);
638 if (!typecheck_stackbased_verify_builtin(STATE, stack, stackfloor))
641 /* pop operands and push return value */
643 u1 rtype = IPTR->sx.s23.s3.bte->md->returntype.type;
644 stack -= IPTR->sx.s23.s3.bte->md->paramslots;
645 if (rtype != TYPE_VOID) {
646 if (IS_2_WORD_TYPE(rtype))
654 /* the following code is only used by the stackbased verifier */
656 case ICMD_POP: /* {STACKBASED} */
658 CHECK_CAT1(stack[0]);
661 case ICMD_POP2: /* {STACKBASED} */
662 /* we pop either 11 or 2 */
663 if (IS_CAT1(stack[0]))
664 CHECK_CAT1(stack[-1]);
668 CHECK_CAT1(stack[0]);
669 CHECK_CAT1(stack[-1]);
671 COPY_SLOT(stack[ 0], temp );
672 COPY_SLOT(stack[-1], stack[ 0]);
673 COPY_SLOT(temp , stack[-1]);
678 CHECK_CAT1(stack[0]);
680 COPY_SLOT(stack[ 0], stack[ 1]);
685 CHECK_CAT1(stack[0]);
687 CHECK_CAT1(stack[-1]);
689 COPY_SLOT(stack[ 0], stack[ 1]);
690 COPY_SLOT(stack[-1], stack[ 0]);
691 COPY_SLOT(stack[ 1], stack[-1]);
696 CHECK_CAT1(stack[0]);
697 /* we skip either 11 or 2 */
698 if (IS_CAT1(stack[-1]))
699 CHECK_CAT1(stack[-2]);
701 COPY_SLOT(stack[ 0], stack[ 1]);
702 COPY_SLOT(stack[-1], stack[ 0]);
703 COPY_SLOT(stack[-2], stack[-1]);
704 COPY_SLOT(stack[ 1], stack[-2]);
708 /* we dup either 11 or 2 */
709 if (IS_CAT1(stack[0]))
710 CHECK_CAT1(stack[-1]);
712 COPY_SLOT(stack[ 0], stack[ 2]);
713 COPY_SLOT(stack[-1], stack[ 1]);
717 /* we dup either 11 or 2 */
718 if (IS_CAT1(stack[0]))
719 CHECK_CAT1(stack[-1]);
721 CHECK_CAT1(stack[-2]);
723 COPY_SLOT(stack[ 0], stack[ 2]);
724 COPY_SLOT(stack[-1], stack[ 1]);
725 COPY_SLOT(stack[-2], stack[ 0]);
726 COPY_SLOT(stack[ 2], stack[-1]);
727 COPY_SLOT(stack[ 1], stack[-2]);
731 /* we dup either 11 or 2 */
732 if (IS_CAT1(stack[0]))
733 CHECK_CAT1(stack[-1]);
734 /* we skip either 11 or 2 */
735 if (IS_CAT1(stack[-2]))
736 CHECK_CAT1(stack[-3]);
738 COPY_SLOT(stack[ 0], stack[ 2]);
739 COPY_SLOT(stack[-1], stack[ 1]);
740 COPY_SLOT(stack[-2], stack[ 0]);
741 COPY_SLOT(stack[-3], stack[-1]);
742 COPY_SLOT(stack[ 2], stack[-2]);
743 COPY_SLOT(stack[ 1], stack[-3]);
747 /* this marker is needed by generate.pl: */
751 * These are local overrides for various environment variables in Emacs.
752 * Please do not remove this and leave it at the end of the file, where
753 * Emacs will automagically detect them.
754 * ---------------------------------------------------------------------
757 * indent-tabs-mode: t
761 * vim:noexpandtab:sw=4:ts=4: