* Removed all Id tags.
[cacao.git] / src / vm / jit / verify / icmds.c
index 24a3cd85ad6eb92a04252cc9bc6d785200217cd9..67cd6203d70acb9829b2d6b4208a0ee15b00c4fd 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/verify/icmds.c - ICMD-specific type checking code
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Edwin Steiner
-
-   Changes:
+*/
 
-   $Id$
+#if 0 /* (needed for code examples in the following comment) */
+/******************************************************************************/
+/* This file contains ICMD-specific code for type checking and type
+ * inference. It is an input file for the verifier generator
+ * (src/vm/jit/verify/generate.pl). The verifier generator creates
+ * code for three compiler passes:
+ *     - stack-based type-infering verification
+ *     - vasiables-based type-infering verification
+ *     - type inference pass (no verification - used for optimizing compiler)
+ *
+ * The rest of this file must consist of "case" clauses starting in
+ * the first column. Each clause can be marked with tags like this:
+ *
+ */          case ICMD_CONSTANT: /* {TAG, TAG, ...} */
+/*
+ * This must be on one line. The following tags are defined:
+ *     STACKBASED..........use this clause for the stack-based verifier
+ *     VARIABLESBASED......use this clause for the variables-based verifier
+ *     TYPEINFERER.........use this clause for the type inference pass
+ *     ALL.................use for all passes
+ *
+ * If no tag is specified, {STACKBASED,VARIABLESBASED} is assumed.
+ *
+ * There are also tags that can be used inside a clause like this:
+ *
+ */          /* {TAG} */
+/*
+ * The following tags are defined within clauses:
+ *     RESULTNOW...........generate code for modelling the stack action
+ *                         _before_ the user-defined code in the clause
+ *                         (Default is to model the stack action afterwards.)
+ *
+ * The following macros are pre-defined:
+ *
+ *     TYPECHECK_STACKBASED.......iff compiling the stack-based verifier
+ *     TYPECHECK_VARIABLESBASED...iff compiling the variables-based verifier
+ *     TYPECHECK_TYPEINFERER......iff compiling the type inference pass
+ *
+/******************************************************************************/
+#endif /* (end #if 0) */
 
-*/
 
 /* this marker is needed by generate.pl: */
 /* {START_OF_CODE} */
@@ -43,8 +77,8 @@
 
        /* (These are only used by the variables based verifier.) */
 
-case ICMD_MOVE: /* {VARIABLESBASED} */
-case ICMD_COPY: /* {VARIABLESBASED} */
+case ICMD_MOVE: /* {VARIABLESBASED,TYPEINFERER} */
+case ICMD_COPY: /* {VARIABLESBASED,TYPEINFERER} */
        TYPECHECK_COUNT(stat_ins_stack);
        COPYTYPE(IPTR->s1, IPTR->dst);
        DST->type = OP1->type;
@@ -53,29 +87,33 @@ case ICMD_COPY: /* {VARIABLESBASED} */
        /****************************************/
        /* LOADING ADDRESS FROM VARIABLE        */
 
-case ICMD_ALOAD:
+case ICMD_ALOAD: /* {ALL} */
        TYPECHECK_COUNT(stat_ins_aload);
 
+#if !defined(TYPECHECK_TYPEINFERER)
        /* loading a returnAddress is not allowed */
        if (!TYPEDESC_IS_REFERENCE(*OP1)) {
                VERIFY_ERROR("illegal instruction: ALOAD loading non-reference");
        }
+#endif
        TYPEINFO_COPY(OP1->typeinfo,DST->typeinfo);
        break;
 
        /****************************************/
        /* STORING ADDRESS TO VARIABLE          */
 
-case ICMD_ASTORE:
+case ICMD_ASTORE: /* {ALL} */
        TYPEINFO_COPY(OP1->typeinfo, DST->typeinfo);
        break;
 
        /****************************************/
        /* LOADING ADDRESS FROM ARRAY           */
 
-case ICMD_AALOAD:
+case ICMD_AALOAD: /* {ALL} */
+#if !defined(TYPECHECK_TYPEINFERER)
        if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(OP1->typeinfo))
                VERIFY_ERROR("illegal instruction: AALOAD on non-reference array");
+#endif
 
        if (!typeinfo_init_component(&OP1->typeinfo,&DST->typeinfo))
                EXCEPTION;
@@ -121,13 +159,13 @@ case ICMD_GETSTATIC:      /* {STACKBASED} */
        break;
 
 case ICMD_PUTFIELD:       /* {VARIABLESBASED} */
-       if (!verify_fieldaccess(state, VAROP(iptr->s1), VAROP(iptr->sx.s23.s2)))
+       if (!handle_fieldaccess(state, VAROP(iptr->s1), VAROP(iptr->sx.s23.s2)))
                return false;
        maythrow = true;
        break;
 
 case ICMD_PUTSTATIC:      /* {VARIABLESBASED} */
-       if (!verify_fieldaccess(state, NULL, VAROP(iptr->s1)))
+       if (!handle_fieldaccess(state, NULL, VAROP(iptr->s1)))
                return false;
        maythrow = true;
        break;
@@ -138,16 +176,17 @@ case ICMD_PUTFIELDCONST:  /* {VARIABLESBASED} */
        constvalue.type = fieldref->parseddesc.fd->type;
        if (IS_ADR_TYPE(constvalue.type)) {
                if (state->iptr->sx.val.anyptr) {
-                       assert(class_java_lang_String);
-                       assert(class_java_lang_String->state & CLASS_LINKED);
-                       typeinfo_init_classinfo(&(constvalue.typeinfo),
-                                                                       class_java_lang_String);
+                       classinfo *cc = (state->iptr->flags.bits & INS_FLAG_CLASS)
+                               ? class_java_lang_Class : class_java_lang_String;
+                       assert(cc);
+                       assert(cc->state & CLASS_LINKED);
+                       typeinfo_init_classinfo(&(constvalue.typeinfo), cc);
                }
                else {
                        TYPEINFO_INIT_NULLTYPE(constvalue.typeinfo);
                }
        }
-       if (!verify_fieldaccess(state, VAROP(iptr->s1), &constvalue))
+       if (!handle_fieldaccess(state, VAROP(iptr->s1), &constvalue))
                return false;
        maythrow = true;
        break;
@@ -158,28 +197,29 @@ case ICMD_PUTSTATICCONST: /* {VARIABLESBASED} */
        constvalue.type = fieldref->parseddesc.fd->type;
        if (IS_ADR_TYPE(constvalue.type)) {
                if (state->iptr->sx.val.anyptr) {
-                       assert(class_java_lang_String);
-                       assert(class_java_lang_String->state & CLASS_LINKED);
-                       typeinfo_init_classinfo(&(constvalue.typeinfo),
-                                                                       class_java_lang_String);
+                       classinfo *cc = (state->iptr->flags.bits & INS_FLAG_CLASS)
+                               ? class_java_lang_Class : class_java_lang_String;
+                       assert(cc);
+                       assert(cc->state & CLASS_LINKED);
+                       typeinfo_init_classinfo(&(constvalue.typeinfo), cc);
                }
                else {
                        TYPEINFO_INIT_NULLTYPE(constvalue.typeinfo);
                }
        }
-       if (!verify_fieldaccess(state, NULL, &constvalue))
+       if (!handle_fieldaccess(state, NULL, &constvalue))
                return false;
        maythrow = true;
        break;
 
-case ICMD_GETFIELD:       /* {VARIABLESBASED} */
-       if (!verify_fieldaccess(state, VAROP(iptr->s1), NULL))
+case ICMD_GETFIELD:       /* {VARIABLESBASED,TYPEINFERER} */
+       if (!handle_fieldaccess(state, VAROP(iptr->s1), NULL))
                return false;
        maythrow = true;
        break;
 
-case ICMD_GETSTATIC:      /* {VARIABLESBASED} */
-       if (!verify_fieldaccess(state, NULL, NULL))
+case ICMD_GETSTATIC:      /* {VARIABLESBASED,TYPEINFERER} */
+       if (!handle_fieldaccess(state, NULL, NULL))
                return false;
        maythrow = true;
        break;
@@ -303,7 +343,7 @@ case ICMD_SASTORECONST:
        /****************************************/
        /* ADDRESS CONSTANTS                    */
 
-case ICMD_ACONST:
+case ICMD_ACONST: /* {ALL} */
        if (IPTR->flags.bits & INS_FLAG_CLASS) {
                /* a java.lang.Class reference */
                TYPEINFO_INIT_JAVA_LANG_CLASS(DST->typeinfo,IPTR->sx.val.c);
@@ -321,11 +361,14 @@ case ICMD_ACONST:
        /****************************************/
        /* CHECKCAST AND INSTANCEOF             */
 
-case ICMD_CHECKCAST:
+case ICMD_CHECKCAST: /* {ALL} */
+#if !defined(TYPECHECK_TYPEINFERER)
        /* returnAddress is not allowed */
        if (!TYPEINFO_IS_REFERENCE(OP1->typeinfo))
                VERIFY_ERROR("Illegal instruction: CHECKCAST on non-reference");
+#endif
 
+    /* XXX only if narrower */
        if (!typeinfo_init_class(&(DST->typeinfo),IPTR->sx.s23.s3.c))
                EXCEPTION;
        break;
@@ -334,68 +377,70 @@ case ICMD_INSTANCEOF:
        /* returnAddress is not allowed */
        if (!TYPEINFO_IS_REFERENCE(OP1->typeinfo))
                VERIFY_ERROR("Illegal instruction: INSTANCEOF on non-reference");
+
+       /* XXX should propagate type information to the following if-branches */
        break;
 
        /****************************************/
        /* BRANCH INSTRUCTIONS                  */
 
-case ICMD_GOTO:
-case ICMD_IFNULL:
-case ICMD_IFNONNULL:
-case ICMD_IFEQ:
-case ICMD_IFNE:
-case ICMD_IFLT:
-case ICMD_IFGE:
-case ICMD_IFGT:
-case ICMD_IFLE:
-case ICMD_IF_ICMPEQ:
-case ICMD_IF_ICMPNE:
-case ICMD_IF_ICMPLT:
-case ICMD_IF_ICMPGE:
-case ICMD_IF_ICMPGT:
-case ICMD_IF_ICMPLE:
-case ICMD_IF_ACMPEQ:
-case ICMD_IF_ACMPNE:
-
-case ICMD_IF_LEQ:
-case ICMD_IF_LNE:
-case ICMD_IF_LLT:
-case ICMD_IF_LGE:
-case ICMD_IF_LGT:
-case ICMD_IF_LLE:
-
-case ICMD_IF_LCMPEQ:
-case ICMD_IF_LCMPNE:
-case ICMD_IF_LCMPLT:
-case ICMD_IF_LCMPGE:
-case ICMD_IF_LCMPGT:
-case ICMD_IF_LCMPLE:
-
-case ICMD_IF_FCMPEQ:
-case ICMD_IF_FCMPNE:
-
-case ICMD_IF_FCMPL_LT:
-case ICMD_IF_FCMPL_GE:
-case ICMD_IF_FCMPL_GT:
-case ICMD_IF_FCMPL_LE:
-
-case ICMD_IF_FCMPG_LT:
-case ICMD_IF_FCMPG_GE:
-case ICMD_IF_FCMPG_GT:
-case ICMD_IF_FCMPG_LE:
-
-case ICMD_IF_DCMPEQ:
-case ICMD_IF_DCMPNE:
-
-case ICMD_IF_DCMPL_LT:
-case ICMD_IF_DCMPL_GE:
-case ICMD_IF_DCMPL_GT:
-case ICMD_IF_DCMPL_LE:
-
-case ICMD_IF_DCMPG_LT:
-case ICMD_IF_DCMPG_GE:
-case ICMD_IF_DCMPG_GT:
-case ICMD_IF_DCMPG_LE:
+case ICMD_GOTO:            /* {ALL} */
+case ICMD_IFNULL:          /* {ALL} */
+case ICMD_IFNONNULL:       /* {ALL} */
+case ICMD_IFEQ:            /* {ALL} */
+case ICMD_IFNE:            /* {ALL} */
+case ICMD_IFLT:            /* {ALL} */
+case ICMD_IFGE:            /* {ALL} */
+case ICMD_IFGT:            /* {ALL} */
+case ICMD_IFLE:            /* {ALL} */
+case ICMD_IF_ICMPEQ:       /* {ALL} */
+case ICMD_IF_ICMPNE:       /* {ALL} */
+case ICMD_IF_ICMPLT:       /* {ALL} */
+case ICMD_IF_ICMPGE:       /* {ALL} */
+case ICMD_IF_ICMPGT:       /* {ALL} */
+case ICMD_IF_ICMPLE:       /* {ALL} */
+case ICMD_IF_ACMPEQ:       /* {ALL} */
+case ICMD_IF_ACMPNE:       /* {ALL} */
+
+case ICMD_IF_LEQ:          /* {ALL} */
+case ICMD_IF_LNE:          /* {ALL} */
+case ICMD_IF_LLT:          /* {ALL} */
+case ICMD_IF_LGE:          /* {ALL} */
+case ICMD_IF_LGT:          /* {ALL} */
+case ICMD_IF_LLE:          /* {ALL} */
+
+case ICMD_IF_LCMPEQ:       /* {ALL} */
+case ICMD_IF_LCMPNE:       /* {ALL} */
+case ICMD_IF_LCMPLT:       /* {ALL} */
+case ICMD_IF_LCMPGE:       /* {ALL} */
+case ICMD_IF_LCMPGT:       /* {ALL} */
+case ICMD_IF_LCMPLE:       /* {ALL} */
+
+case ICMD_IF_FCMPEQ:       /* {ALL} */
+case ICMD_IF_FCMPNE:       /* {ALL} */
+
+case ICMD_IF_FCMPL_LT:     /* {ALL} */
+case ICMD_IF_FCMPL_GE:     /* {ALL} */
+case ICMD_IF_FCMPL_GT:     /* {ALL} */
+case ICMD_IF_FCMPL_LE:     /* {ALL} */
+
+case ICMD_IF_FCMPG_LT:     /* {ALL} */
+case ICMD_IF_FCMPG_GE:     /* {ALL} */
+case ICMD_IF_FCMPG_GT:     /* {ALL} */
+case ICMD_IF_FCMPG_LE:     /* {ALL} */
+
+case ICMD_IF_DCMPEQ:       /* {ALL} */
+case ICMD_IF_DCMPNE:       /* {ALL} */
+
+case ICMD_IF_DCMPL_LT:     /* {ALL} */
+case ICMD_IF_DCMPL_GE:     /* {ALL} */
+case ICMD_IF_DCMPL_GT:     /* {ALL} */
+case ICMD_IF_DCMPL_LE:     /* {ALL} */
+
+case ICMD_IF_DCMPG_LT:     /* {ALL} */
+case ICMD_IF_DCMPG_GE:     /* {ALL} */
+case ICMD_IF_DCMPG_GT:     /* {ALL} */
+case ICMD_IF_DCMPG_LE:     /* {ALL} */
        /* {RESULTNOW} */
        TYPECHECK_COUNT(stat_ins_branch);
 
@@ -406,7 +451,7 @@ case ICMD_IF_DCMPG_LE:
        /****************************************/
        /* SWITCHES                             */
 
-case ICMD_TABLESWITCH:
+case ICMD_TABLESWITCH:     /* {ALL} */
        /* {RESULTNOW} */
        TYPECHECK_COUNT(stat_ins_switch);
 
@@ -422,7 +467,7 @@ case ICMD_TABLESWITCH:
        LOG("switch done");
        break;
 
-case ICMD_LOOKUPSWITCH:
+case ICMD_LOOKUPSWITCH:    /* {ALL} */
        /* {RESULTNOW} */
        TYPECHECK_COUNT(stat_ins_switch);
 
@@ -530,14 +575,14 @@ return_tail:
        /****************************************/
        /* SUBROUTINE INSTRUCTIONS              */
 
-case ICMD_JSR: /* {VARIABLESBASED} */
+case ICMD_JSR: /* {VARIABLESBASED,TYPEINFERER} */
        TYPEINFO_INIT_RETURNADDRESS(DST->typeinfo, BPTR->next);
        REACH(IPTR->sx.s23.s3.jsrtarget);
        break;
 
 case ICMD_JSR: /* {STACKBASED} */
        /* {RESULTNOW} */
-       tbptr = BLOCK_OF(IPTR->sx.s23.s3.jsrtarget.insindex);
+       tbptr = IPTR->sx.s23.s3.jsrtarget.block;
 
        TYPEINFO_INIT_RETURNADDRESS(stack[0].typeinfo, tbptr);
        REACH_BLOCK(tbptr);
@@ -547,16 +592,18 @@ case ICMD_JSR: /* {STACKBASED} */
                EXCEPTION;
        break;
 
-case ICMD_RET: /* {VARIABLESBASED} */
+case ICMD_RET: /* {VARIABLESBASED,TYPEINFERER} */
+#if !defined(TYPECHECK_TYPEINFERER)
        /* check returnAddress variable */
        if (!typevector_checkretaddr(jd->var,IPTR->s1.varindex))
                VERIFY_ERROR("illegal instruction: RET using non-returnAddress variable");
+#endif
        REACH(IPTR->dst);
        break;
 
 case ICMD_RET: /* {STACKBASED} */
        /* {RESULTNOW} */
-       CHECK_LOCAL_TYPE(IPTR->s1.varindex, TYPE_ADR);
+       CHECK_LOCAL_TYPE(IPTR->s1.varindex, TYPE_RET);
        if (!TYPEINFO_IS_PRIMITIVE(STATE->locals[IPTR->s1.varindex].typeinfo))
                VERIFY_ERROR("illegal instruction: RET using non-returnAddress variable");
 
@@ -567,12 +614,12 @@ case ICMD_RET: /* {STACKBASED} */
        /****************************************/
        /* INVOKATIONS                          */
 
-case ICMD_INVOKEVIRTUAL:   /* {VARIABLESBASED} */
-case ICMD_INVOKESPECIAL:   /* {VARIABLESBASED} */
-case ICMD_INVOKESTATIC:    /* {VARIABLESBASED} */
-case ICMD_INVOKEINTERFACE: /* {VARIABLESBASED} */
+case ICMD_INVOKEVIRTUAL:   /* {VARIABLESBASED,TYPEINFERER} */
+case ICMD_INVOKESPECIAL:   /* {VARIABLESBASED,TYPEINFERER} */
+case ICMD_INVOKESTATIC:    /* {VARIABLESBASED,TYPEINFERER} */
+case ICMD_INVOKEINTERFACE: /* {VARIABLESBASED,TYPEINFERER} */
        TYPECHECK_COUNT(stat_ins_invoke);
-       if (!verify_invocation(state))
+       if (!handle_invocation(state))
                EXCEPTION;
        TYPECHECK_COUNTIF(INSTRUCTION_IS_UNRESOLVED(IPTR), stat_ins_invoke_unresolved);
        break;
@@ -610,8 +657,8 @@ case ICMD_INVOKEINTERFACE: /* {STACKBASED} */
        /****************************************/
        /* MULTIANEWARRAY                       */
 
-case ICMD_MULTIANEWARRAY: /* {VARIABLESBASED} */
-       if (!verify_multianewarray(STATE))
+case ICMD_MULTIANEWARRAY: /* {VARIABLESBASED,TYPEINFERER} */
+       if (!handle_multianewarray(STATE))
                EXCEPTION;
        break;
 
@@ -625,9 +672,9 @@ case ICMD_MULTIANEWARRAY: /* {STACKBASED} */
        /****************************************/
        /* BUILTINS                             */
 
-case ICMD_BUILTIN: /* {VARIABLESBASED} */
+case ICMD_BUILTIN: /* {VARIABLESBASED,TYPEINFERER} */
        TYPECHECK_COUNT(stat_ins_builtin);
-       if (!verify_builtin(state))
+       if (!handle_builtin(state))
                EXCEPTION;
        break;
 
@@ -662,7 +709,7 @@ case ICMD_POP2: /* {STACKBASED} */
                CHECK_CAT1(stack[-1]);
        break;
 
-case ICMD_SWAP:
+case ICMD_SWAP: /* {STACKBASED} */
        CHECK_CAT1(stack[0]);
        CHECK_CAT1(stack[-1]);
 
@@ -671,14 +718,14 @@ case ICMD_SWAP:
        COPY_SLOT(temp     , stack[-1]);
        break;
 
-case ICMD_DUP:
+case ICMD_DUP: /* {STACKBASED} */
        /* we dup 1 */
        CHECK_CAT1(stack[0]);
 
        COPY_SLOT(stack[ 0], stack[ 1]);
        break;
 
-case ICMD_DUP_X1:
+case ICMD_DUP_X1: /* {STACKBASED} */
        /* we dup 1 */
        CHECK_CAT1(stack[0]);
        /* we skip 1 */
@@ -689,7 +736,7 @@ case ICMD_DUP_X1:
        COPY_SLOT(stack[ 1], stack[-1]);
        break;
 
-case ICMD_DUP_X2:
+case ICMD_DUP_X2: /* {STACKBASED} */
        /* we dup 1 */
        CHECK_CAT1(stack[0]);
        /* we skip either 11 or 2 */
@@ -702,7 +749,7 @@ case ICMD_DUP_X2:
        COPY_SLOT(stack[ 1], stack[-2]);
        break;
 
-case ICMD_DUP2:
+case ICMD_DUP2: /* {STACKBASED} */
        /* we dup either 11 or 2 */
        if (IS_CAT1(stack[0]))
                CHECK_CAT1(stack[-1]);
@@ -711,7 +758,7 @@ case ICMD_DUP2:
        COPY_SLOT(stack[-1], stack[ 1]);
        break;
 
-case ICMD_DUP2_X1:
+case ICMD_DUP2_X1: /* {STACKBASED} */
        /* we dup either 11 or 2 */
        if (IS_CAT1(stack[0]))
                CHECK_CAT1(stack[-1]);
@@ -725,7 +772,7 @@ case ICMD_DUP2_X1:
        COPY_SLOT(stack[ 1], stack[-2]);
        break;
 
-case ICMD_DUP2_X2:
+case ICMD_DUP2_X2: /* {STACKBASED} */
        /* we dup either 11 or 2 */
        if (IS_CAT1(stack[0]))
                CHECK_CAT1(stack[-1]);