2007-09-25 Rodrigo Kumpera <rkumpera@novell.com>
[mono.git] / mono / metadata / verify.c
index 0f3e7adcca3b5edd025957902e5995e20a2ecaa3..89eb6f06bb3d21be43985c4ef7fe828636582a96 100644 (file)
@@ -1077,9 +1077,9 @@ in_same_block (MonoMethodHeader *header, guint offset, guint target)
 
        for (i = 0; i < header->num_clauses; ++i) {
                clause = &header->clauses [i];
-               if (MONO_OFFSET_IN_CLAUSE (clause, offset) && !MONO_OFFSET_IN_CLAUSE (clause, target))
+               if (MONO_OFFSET_IN_CLAUSE (clause, offset) MONO_OFFSET_IN_CLAUSE (clause, target))
                        return 0;
-               if (MONO_OFFSET_IN_HANDLER (clause, offset) && !MONO_OFFSET_IN_HANDLER (clause, target))
+               if (MONO_OFFSET_IN_HANDLER (clause, offset) MONO_OFFSET_IN_HANDLER (clause, target))
                        return 0;
                /* need to check filter ... */
        }
@@ -1122,7 +1122,7 @@ can_merge_stack (ILCodeDesc *a, ILCodeDesc *b)
 static gboolean
 is_valid_bool_arg (ILStackDesc *arg)
 {
-       if (arg->stype & POINTER_MASK)
+       if (IS_MANAGED_POINTER (arg->stype))
                return TRUE;
        switch (arg->stype) {
        case TYPE_I4:
@@ -1231,6 +1231,22 @@ stind_type (int op, int type) {
 }
 
 
+/*Type manipulation helper*/
+
+/*Returns the byref version of the supplied MonoType*/
+static MonoType*
+mono_type_get_type_byref (MonoType *type)
+{
+       return &mono_class_from_mono_type (type)->this_arg;
+}
+
+
+/*Returns the byval version of the supplied MonoType*/
+static MonoType*
+mono_type_get_type_byval (MonoType *type)
+{
+       return &mono_class_from_mono_type (type)->byval_arg;
+}
 
 
 /*Stack manipulation code*/
@@ -1262,7 +1278,7 @@ static int
 check_underflow (VerifyContext *ctx, int size)
 {
        if (ctx->eval.size < size) {
-               ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Stack underflow, required %d, but have %d", size, ctx->eval.size));
+               ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Stack underflow, required %d, but have %d at 0x%04x", size, ctx->eval.size, ctx->ip_offset));
                return 0;
        }
        return 1;
@@ -1272,7 +1288,7 @@ static int
 check_overflow (VerifyContext *ctx)
 {
        if (ctx->eval.size >= ctx->max_stack) {
-               ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Method doesn't have stack-depth %d", ctx->eval.size + 1));
+               ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Method doesn't have stack-depth %d at 0x%04x", ctx->eval.size + 1, ctx->ip_offset));
                return 0;
        }
        return 1;
@@ -1336,6 +1352,29 @@ stack_get (VerifyContext *ctx, int distance)
        return ctx->eval.stack + (ctx->eval.size - distance - 1);
 }
 
+/* Returns the MonoType associated with the token, or NULL if it is invalid.
+ * 
+ * A boxable type can be either a reference or value type, but cannot be a byref type or an unmanaged pointer   
+ * */
+static MonoType*
+get_boxable_mono_type (VerifyContext* ctx, int token)
+{
+       MonoType *type = mono_type_get_full (ctx->image, token, ctx->generic_context);
+
+       if (!type) {
+               ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Type (0x%08x) not found at 0x%04x", token, ctx->ip_offset));
+               return NULL;
+       }
+
+       if (type->byref && type->type != MONO_TYPE_TYPEDBYREF) {
+               ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid use of byref type at 0x%04x", ctx->ip_offset));
+               return NULL;
+       }
+
+       check_unverifiable_type (ctx, type);
+       return type;
+}
+
 
 /*operation result tables */
 
@@ -1411,10 +1450,10 @@ dump_stack_value (ILStackDesc *value)
        if (value->stype & CMMP_MASK)
                printf ("Controled Mutability MP: ");
 
-       if (value->stype & POINTER_MASK)
+       if (IS_MANAGED_POINTER (value->stype))
                printf ("Managed Pointer to: ");
 
-       switch (value->stype & TYPE_MASK) {
+       switch (UNMASK_TYPE (value->stype)) {
                case TYPE_INV:
                        printf ("invalid type]"); 
                        return;
@@ -1434,10 +1473,42 @@ dump_stack_value (ILStackDesc *value)
                        printf ("unmanaged pointer]"); 
                        return;
                case TYPE_COMPLEX:
-                       printf ("complex]"); 
-                       return;
+                       switch (value->type->type) {
+                       case MONO_TYPE_CLASS:
+                       case MONO_TYPE_VALUETYPE:
+                               printf ("complex] (%s)", value->type->data.klass->name);
+                               return;
+                       case MONO_TYPE_STRING:
+                               printf ("complex] (string)");
+                               return;
+                       case MONO_TYPE_OBJECT:
+                               printf ("complex] (object)");
+                               return;
+                       case MONO_TYPE_SZARRAY:
+                               printf ("complex] (%s [])", value->type->data.klass->name);
+                               return;
+                       case MONO_TYPE_ARRAY:
+                               printf ("complex] (%s [%d %d %d])",
+                                       value->type->data.array->eklass->name,
+                                       value->type->data.array->rank,
+                                       value->type->data.array->numsizes,
+                                       value->type->data.array->numlobounds);
+                               return;
+                       case MONO_TYPE_GENERICINST:
+                               printf ("complex] (inst of %s )", value->type->data.generic_class->container_class->name);
+                               return;
+                       case MONO_TYPE_VAR:
+                               printf ("complex] (type generic param !%d - %s) ", value->type->data.generic_param->num, value->type->data.generic_param->name);
+                               return;
+                       case MONO_TYPE_MVAR:
+                               printf ("complex] (method generic param !!%d - %s) ", value->type->data.generic_param->num, value->type->data.generic_param->name);
+                               return;
+                       default:
+                               printf ("unknown complex %d type]\n", value->type->type);
+                               g_assert_not_reached ();
+                       }
                default:
-                       printf ("unknown %d type]", value->stype);
+                       printf ("unknown stack %d type]\n", value->stype);
                        g_assert_not_reached ();
        }
 }
@@ -1524,6 +1595,7 @@ handle_enum:
        /* FIXME: the spec says that you cannot have a pointer to method pointer, do we need to check this here? */ 
        case MONO_TYPE_FNPTR:
        case MONO_TYPE_PTR:
+       case MONO_TYPE_TYPEDBYREF:
                return TYPE_PTR | mask;
 
        case MONO_TYPE_CLASS:
@@ -1531,7 +1603,6 @@ handle_enum:
        case MONO_TYPE_OBJECT:
        case MONO_TYPE_SZARRAY:
        case MONO_TYPE_ARRAY:
-       case MONO_TYPE_TYPEDBYREF:
        case MONO_TYPE_GENERICINST:
                return TYPE_COMPLEX | mask;
 
@@ -1560,12 +1631,12 @@ handle_enum:
 
 /* convert MonoType to ILStackDesc format (stype) */
 static void
-set_stack_value (ILStackDesc *stack, MonoType *type, int take_addr, int override_byref)
+set_stack_value (ILStackDesc *stack, MonoType *type, int take_addr)
 {
        int mask = 0;
        int type_kind = type->type;
 
-       if ((type->byref && !override_byref) || take_addr)
+       if (type->byref || take_addr)
                mask = POINTER_MASK;
        /* TODO handle CMMP_MASK */
 
@@ -1591,6 +1662,7 @@ handle_enum:
        /*FIXME: Do we need to check if it's a pointer to the method pointer? The spec says it' illegal to have that.*/
        case MONO_TYPE_FNPTR:
        case MONO_TYPE_PTR:
+       case MONO_TYPE_TYPEDBYREF:
                stack->stype = TYPE_PTR | mask;
                return;
 
@@ -1599,9 +1671,10 @@ handle_enum:
        case MONO_TYPE_OBJECT:
        case MONO_TYPE_SZARRAY:
        case MONO_TYPE_ARRAY:
-       case MONO_TYPE_TYPEDBYREF:
 
        case MONO_TYPE_GENERICINST:
+       case MONO_TYPE_VAR:
+       case MONO_TYPE_MVAR: 
                stack->stype = TYPE_COMPLEX | mask;
                return;
        case MONO_TYPE_I8:
@@ -1622,7 +1695,7 @@ handle_enum:
                        return;
                }
        default:
-               VERIFIER_DEBUG ( printf ("unknown type %02x in eval stack type\n", type->type); );
+               VERIFIER_DEBUG ( printf ("unknown type 0x%02x in eval stack type\n", type->type); );
                g_assert_not_reached ();
        }
        return;
@@ -1796,7 +1869,9 @@ mono_is_generic_instance_compatible (MonoGenericClass *target, MonoGenericClass
  */
 static gboolean
 verify_stack_type_compatibility (VerifyContext *ctx, MonoType *target, MonoType *candidate, gboolean strict) {
-       int stack_type;
+#define IS_ONE_OF3(T, A, B, C) (T == A || T == B || T == C)
+#define IS_ONE_OF2(T, A, B) (T == A || T == B)
+
        VERIFIER_DEBUG ( printf ("checking type compatibility %p %p[%d][%d] %p[%d][%d]\n", ctx, target, target->type, target->byref, candidate, candidate->type, candidate->byref); );
 
        /*only one is byref */
@@ -1814,33 +1889,40 @@ handle_enum:
        case MONO_TYPE_I1:
        case MONO_TYPE_U1:
        case MONO_TYPE_BOOLEAN:
+               if (strict)
+                       return IS_ONE_OF3 (candidate->type, MONO_TYPE_I1, MONO_TYPE_U1, MONO_TYPE_BOOLEAN);
        case MONO_TYPE_I2:
        case MONO_TYPE_U2:
        case MONO_TYPE_CHAR:
-       case MONO_TYPE_I4:
-       case MONO_TYPE_U4:
                if (strict)
-                       return candidate->type == target->type;
+                       return IS_ONE_OF3 (candidate->type, MONO_TYPE_I2, MONO_TYPE_U2, MONO_TYPE_CHAR);
                return get_stack_type (candidate) == TYPE_I4;
 
+       case MONO_TYPE_I4:
+       case MONO_TYPE_U4: {
+               gboolean is_native_int = IS_ONE_OF2 (candidate->type, MONO_TYPE_I, MONO_TYPE_U);
+               gboolean is_int4 = IS_ONE_OF2 (candidate->type, MONO_TYPE_I4, MONO_TYPE_U4);
+               if (strict)
+                       return is_native_int || is_int4;
+               return is_native_int || get_stack_type (candidate) == TYPE_I4;
+       }
+
        case MONO_TYPE_I8:
        case MONO_TYPE_U8:
-               if (strict)
-                       return candidate->type == target->type;
-               return get_stack_type (candidate)  == TYPE_I8;
+               return IS_ONE_OF2 (candidate->type, MONO_TYPE_I8, MONO_TYPE_U8);
 
        case MONO_TYPE_R4:
        case MONO_TYPE_R8:
                if (strict)
                        return candidate->type == target->type;
-               return get_stack_type (target)  == TYPE_R8;
+               return IS_ONE_OF2 (candidate->type, MONO_TYPE_R4, MONO_TYPE_R8);
 
        case MONO_TYPE_I:
-       case MONO_TYPE_U:
-               if (strict)
-                       return candidate->type == target->type;
-               stack_type = get_stack_type (target);
-               return stack_type == TYPE_NATIVE_INT || stack_type == TYPE_I4;;
+       case MONO_TYPE_U: {
+               gboolean is_native_int = IS_ONE_OF2 (candidate->type, MONO_TYPE_I, MONO_TYPE_U);
+               gboolean is_int4 = IS_ONE_OF2 (candidate->type, MONO_TYPE_I4, MONO_TYPE_U4);
+               return is_native_int || is_int4;
+       }
 
        case MONO_TYPE_PTR:
                if (candidate->type != MONO_TYPE_PTR)
@@ -1848,10 +1930,20 @@ handle_enum:
                /* check the underlying type */
                return verify_stack_type_compatibility (ctx, target->data.type, candidate->data.type, TRUE);
 
+       case MONO_TYPE_FNPTR: {
+               MonoMethodSignature *left, *right;
+               if (candidate->type != MONO_TYPE_FNPTR)
+                       return FALSE;
+
+               left = mono_type_get_signature (target);
+               right = mono_type_get_signature (candidate);
+               return mono_metadata_signature_equal (left, right) && left->call_convention == right->call_convention;
+       }
+
        case MONO_TYPE_GENERICINST: {
                MonoGenericClass *left;
                MonoGenericClass *right;
-               if (target->type != MONO_TYPE_GENERICINST)
+               if (candidate->type != MONO_TYPE_GENERICINST)
                        return FALSE;
                left = target->data.generic_class;
                right = candidate->data.generic_class;
@@ -1873,7 +1965,7 @@ handle_enum:
        case MONO_TYPE_SZARRAY: {
                MonoClass *left;
                MonoClass *right;
-               if (target->type != MONO_TYPE_SZARRAY)
+               if (candidate->type != MONO_TYPE_SZARRAY)
                        return FALSE;
 
                left = target->data.klass;
@@ -1888,7 +1980,7 @@ handle_enum:
 
        //TODO verify aditional checks that needs to be done
        case MONO_TYPE_TYPEDBYREF:
-               return candidate->type != MONO_TYPE_TYPEDBYREF;
+               return candidate->type == MONO_TYPE_TYPEDBYREF;
 
        case MONO_TYPE_VALUETYPE:
                if (target->data.klass->enumtype) {
@@ -1899,6 +1991,16 @@ handle_enum:
                                return FALSE;
                        return target->data.klass == candidate->data.klass;
                }
+               
+       case MONO_TYPE_VAR:
+               if (candidate->type != MONO_TYPE_VAR)
+                       return FALSE;
+               return candidate->data.generic_param->num == target->data.generic_param->num;
+
+       case MONO_TYPE_MVAR:
+               if (candidate->type != MONO_TYPE_MVAR)
+                       return FALSE;
+               return candidate->data.generic_param->num == target->data.generic_param->num;
 
        default:
                VERIFIER_DEBUG ( printf ("unknown store type %d\n", target->type); );
@@ -1906,6 +2008,8 @@ handle_enum:
                return FALSE;
        }
        return 1;
+#undef IS_ONE_OF3
+#undef IS_ONE_OF2
 }
 
 static int
@@ -1914,7 +2018,7 @@ verify_type_compat (VerifyContext *ctx, MonoType *type, ILStackDesc *stack) {
        VERIFIER_DEBUG ( printf ("checking compatibility %p %p[%d] %p[%d]\n", ctx, type, type->type, stack, stack_type ); );
 
        /*only one is byref */
-       if (type->byref ^ IS_MANAGED_POINTER(stack_type)) {
+       if (type->byref ^ IS_MANAGED_POINTER (stack_type)) {
                /* converting from native int to byref*/
                if (type->byref && stack_type == TYPE_NATIVE_INT) {
                        CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("using byref native int at 0x%04x", ctx->ip_offset));
@@ -1922,7 +2026,8 @@ verify_type_compat (VerifyContext *ctx, MonoType *type, ILStackDesc *stack) {
                }
                return FALSE;
        }
-       stack_type = UNMASK_TYPE (stack_type);
+       if (type->byref)
+               return verify_stack_type_compatibility (ctx, type, mono_type_get_type_byref (stack->type), TRUE);
 
 handle_enum:
        switch (type->type) {
@@ -2023,7 +2128,7 @@ handle_enum:
 
        /*TODO verify aditional checks that needs to be done */
        case MONO_TYPE_TYPEDBYREF:
-               if (stack_type != TYPE_COMPLEX)
+               if (stack_type != TYPE_PTR)
                        return FALSE;
                g_assert (stack->type);
                if (stack->type->type != MONO_TYPE_TYPEDBYREF)
@@ -2043,6 +2148,22 @@ handle_enum:
                        return stack->type->data.klass == type->data.klass;
                }
 
+       case MONO_TYPE_VAR:
+               if (stack_type != TYPE_COMPLEX)
+                       return FALSE;
+               g_assert (stack->type);
+               if (stack->type->type != MONO_TYPE_VAR)
+                       return FALSE;
+               return stack->type->data.generic_param->num == type->data.generic_param->num;
+
+       case MONO_TYPE_MVAR:
+               if (stack_type != TYPE_COMPLEX)
+                       return FALSE;
+               g_assert (stack->type);
+               if (stack->type->type != MONO_TYPE_MVAR)
+                       return FALSE;
+               return stack->type->data.generic_param->num == type->data.generic_param->num;
+
        default:
                printf("unknown store type %d\n", type->type);
                g_assert_not_reached ();
@@ -2061,19 +2182,14 @@ push_arg (VerifyContext *ctx, unsigned int arg, int take_addr)
                else {
                        CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Method doesn't have argument %d", arg + 1));
                        if (check_overflow (ctx)) //FIXME: what sane value could we ever push?
-                               stack_push_val (ctx, TYPE_I4, &mono_defaults.int_class->byval_arg);
+                               stack_push_val (ctx, TYPE_I4, &mono_defaults.int32_class->byval_arg);
                }
        } else if (check_overflow (ctx)) {
-               gboolean override_byref;
                /*We must let the value be pushed, otherwise we would get an underflow error*/
                check_unverifiable_type (ctx, ctx->params [arg]);
                if (ctx->params [arg]->byref && take_addr)
                        CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("ByRef of ByRef at 0x%04x", ctx->ip_offset));
-
-               /*the 'this' argument is byref, which is not right for reference types,
-                We override the byref only here, since it's the only point that push ctx->params values*/
-               override_byref = arg == 0 && ctx->method->klass && !(ctx->method->flags & METHOD_ATTRIBUTE_STATIC) && !ctx->method->klass->valuetype;   
-               set_stack_value (stack_push (ctx), ctx->params [arg], FALSE, override_byref);
+               set_stack_value (stack_push (ctx), ctx->params [arg], take_addr);
        } 
 }
 
@@ -2088,7 +2204,7 @@ push_local (VerifyContext *ctx, guint32 arg, int take_addr)
                if (ctx->locals [arg]->byref && take_addr)
                        CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("ByRef of ByRef at 0x%04x", ctx->ip_offset));
 
-               set_stack_value (stack_push (ctx), ctx->locals [arg], take_addr, FALSE);
+               set_stack_value (stack_push (ctx), ctx->locals [arg], take_addr);
        } 
 }
 
@@ -2098,14 +2214,16 @@ store_arg (VerifyContext *ctx, guint32 arg)
        ILStackDesc *value;
 
        if (arg >= ctx->max_args) {
-               ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Method doesn't have local var %d at 0x%04x", arg + 1, ctx->ip_offset));
+               CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Method doesn't have local var %d at 0x%04x", arg + 1, ctx->ip_offset));
+               check_underflow (ctx, 1);
+               stack_pop (ctx);
                return;
        }
 
        if (check_underflow (ctx, 1)) {
                value = stack_pop (ctx);
                if (!verify_type_compat (ctx, ctx->params [arg], value)) {
-                       CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Incompatible type %s in local store at 0x%04x", type_names [value->stype & TYPE_MASK], ctx->ip_offset));
+                       CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Incompatible type %s in local store at 0x%04x", type_names [UNMASK_TYPE (value->stype)], ctx->ip_offset));
                }
        }
 }
@@ -2123,7 +2241,7 @@ store_local (VerifyContext *ctx, guint32 arg)
        if (check_underflow (ctx, 1)) {
                value = stack_pop(ctx);
                if (!verify_type_compat (ctx, ctx->locals [arg], value)) {
-                       CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Incompatible type %s in local store at 0x%04x", type_names [value->stype & TYPE_MASK], ctx->ip_offset));    
+                       CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Incompatible type %s in local store at 0x%04x", type_names [UNMASK_TYPE (value->stype)], ctx->ip_offset));  
                }
        }
 }
@@ -2141,13 +2259,13 @@ do_binop (VerifyContext *ctx, unsigned int opcode, const unsigned char table [TY
        b = stack_top (ctx);
 
        idxa = a->stype;
-       if (idxa & POINTER_MASK) {
+       if (IS_MANAGED_POINTER (idxa)) {
                idxa = TYPE_PTR;
                complexMerge = 1;
        }
 
        idxb = b->stype;
-       if (idxb & POINTER_MASK) {
+       if (IS_MANAGED_POINTER (idxb)) {
                idxb = TYPE_PTR;
                complexMerge = 2;
        }
@@ -2161,15 +2279,13 @@ do_binop (VerifyContext *ctx, unsigned int opcode, const unsigned char table [TY
 
        ctx->eval.size--;
        if (res == TYPE_INV) {
-               CODE_NOT_VERIFIABLE (ctx, g_strdup_printf (
-                       "Binary instruction applyed to ill formed stack (%s x %s)", 
-                       type_names [idxa & TYPE_MASK], type_names [idxb & TYPE_MASK]));
+               CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Binary instruction applyed to ill formed stack (%s x %s)", type_names [UNMASK_TYPE (idxa)], type_names [UNMASK_TYPE (idxb)]));
                return;
        }
 
        if (res & NON_VERIFIABLE_RESULT) {
                CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Binary instruction is not verifiable (%s x %s)", 
-                       type_names [idxa & TYPE_MASK], type_names [idxb & TYPE_MASK]));
+                       type_names [UNMASK_TYPE (idxa)], type_names [UNMASK_TYPE (idxb)]));
 
                res = res & ~NON_VERIFIABLE_RESULT;
        }
@@ -2216,7 +2332,7 @@ do_boolean_branch_op (VerifyContext *ctx, int delta)
 
        top = stack_pop (ctx);
        if (!is_valid_bool_arg (top))
-               CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Argument type %s not valid for brtrue/brfalse at 0x%04x", type_names [stack_get (ctx, -1)->stype & TYPE_MASK], ctx->ip_offset));
+               CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Argument type %s not valid for brtrue/brfalse at 0x%04x", type_names [UNMASK_TYPE (stack_get (ctx, -1)->stype)], ctx->ip_offset));
 
        check_unmanaged_pointer (ctx, top);
 }
@@ -2251,11 +2367,11 @@ do_branch_op (VerifyContext *ctx, signed int delta, const unsigned char table [T
        a = stack_pop (ctx);
 
        idxa = a->stype;
-       if (idxa & POINTER_MASK)
+       if (IS_MANAGED_POINTER (idxa))
                idxa = TYPE_PTR;
 
        idxb = b->stype;
-       if (idxb & POINTER_MASK)
+       if (IS_MANAGED_POINTER (idxb))
                idxb = TYPE_PTR;
 
        --idxa;
@@ -2268,10 +2384,10 @@ do_branch_op (VerifyContext *ctx, signed int delta, const unsigned char table [T
        if (res == TYPE_INV) {
                ADD_VERIFY_ERROR (ctx,
                        g_strdup_printf ("Compare and Branch instruction applyed to ill formed stack (%s x %s) at 0x%04x",
-                               type_names [idxa & TYPE_MASK], type_names [idxb & TYPE_MASK], ctx->ip_offset));
+                               type_names [UNMASK_TYPE (idxa)], type_names [UNMASK_TYPE (idxb)], ctx->ip_offset));
        } else if (res & NON_VERIFIABLE_RESULT) {
                        CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Compare and Branch instruction is not verifiable (%s x %s) at 0x%04x",
-                               type_names [idxa & TYPE_MASK], type_names [idxb & TYPE_MASK], ctx->ip_offset)); 
+                               type_names [UNMASK_TYPE (idxa)], type_names [UNMASK_TYPE (idxb)], ctx->ip_offset)); 
                res = res & ~NON_VERIFIABLE_RESULT;
        }
 }
@@ -2289,28 +2405,25 @@ do_cmp_op (VerifyContext *ctx, const unsigned char table [TYPE_MAX][TYPE_MAX])
        a = stack_pop (ctx);
 
        idxa = a->stype;
-       if (idxa & POINTER_MASK)
+       if (IS_MANAGED_POINTER (idxa))
                idxa = TYPE_PTR;
 
        idxb = b->stype;
-       if (idxb & POINTER_MASK)
+       if (IS_MANAGED_POINTER (idxb)) 
                idxb = TYPE_PTR;
 
        --idxa;
        --idxb;
        res = table [idxa][idxb];
 
-       printf("binop res %d\n", res);
-       printf("idxa %d idxb %d\n", idxa, idxb);
-
        if(res == TYPE_INV) {
-               CODE_NOT_VERIFIABLE (ctx, g_strdup_printf("Compare instruction applyed to ill formed stack (%s x %s) at 0x%04x", type_names [idxa & TYPE_MASK], type_names [idxb & TYPE_MASK], ctx->ip_offset));
+               CODE_NOT_VERIFIABLE (ctx, g_strdup_printf("Compare instruction applyed to ill formed stack (%s x %s) at 0x%04x", type_names [UNMASK_TYPE (idxa)], type_names [UNMASK_TYPE (idxb)], ctx->ip_offset));
        } else if (res & NON_VERIFIABLE_RESULT) {
                CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Compare instruction is not verifiable (%s x %s) at 0x%04x",
-                       type_names [idxa & TYPE_MASK], type_names [idxb & TYPE_MASK], ctx->ip_offset)); 
+                       type_names [UNMASK_TYPE (idxa)], type_names [UNMASK_TYPE (idxb)], ctx->ip_offset)); 
                res = res & ~NON_VERIFIABLE_RESULT;
        }
-       stack_push_val (ctx, TYPE_I4, &mono_defaults.int_class->byval_arg);
+       stack_push_val (ctx, TYPE_I4, &mono_defaults.int32_class->byval_arg);
 }
 
 static void
@@ -2331,8 +2444,9 @@ do_ret (VerifyContext *ctx)
        }
 
        if (ctx->eval.size > 0) {
-               ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Stack not empty (%d) after ret at 0x%04x", ctx->eval.size, ctx->ip_offset));
-       } else if (in_any_block (ctx->header, ctx->ip_offset))
+               CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Stack not empty (%d) after ret at 0x%04x", ctx->eval.size, ctx->ip_offset));
+       } 
+       if (in_any_block (ctx->header, ctx->ip_offset))
                ADD_VERIFY_ERROR (ctx, g_strdup_printf ("ret cannot escape exception blocks at 0x%04x", ctx->ip_offset));
 }
 
@@ -2381,17 +2495,16 @@ do_invoke_method (VerifyContext *ctx, int method_token)
                VERIFIER_DEBUG ( printf ("verifying this argument\n"); );
                value = stack_pop (ctx);
                if (!verify_type_compat (ctx, type, value)) {
-                       ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Incompatible return value on stack with method signature ret at 0x%04x", ctx->ip_offset));
+                       ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Incompatible this argument on stack with method signature ret at 0x%04x", ctx->ip_offset));
                        return;
                }
        }
-
        if (!mono_method_can_access_method (ctx->method, method))
                CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Method is not accessible at 0x%04x", ctx->ip_offset));
-       
+
        if (sig->ret->type != MONO_TYPE_VOID) {
                if (check_overflow (ctx))
-                       set_stack_value (stack_push (ctx), sig->ret, FALSE, FALSE);
+                       set_stack_value (stack_push (ctx), sig->ret, FALSE);
        }
 }
 
@@ -2418,8 +2531,8 @@ do_push_static_field (VerifyContext *ctx, int token, gboolean take_addr)
 
        if (!mono_method_can_access_field (ctx->method, field))
                CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Type at stack is not accessible at 0x%04x", ctx->ip_offset));
-       
-       set_stack_value (stack_push (ctx), field->type, take_addr, FALSE);
+
+       set_stack_value (stack_push (ctx), field->type, take_addr);
 }
 
 static void
@@ -2453,7 +2566,7 @@ do_store_static_field (VerifyContext *ctx, int token) {
                CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Type at stack is not accessible at 0x%04x", ctx->ip_offset));
 
        if (!verify_type_compat (ctx, field->type, value))
-               CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Incompatible type %s in static field store at 0x%04x", type_names [value->stype & TYPE_MASK], ctx->ip_offset));     
+               CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Incompatible type %s in static field store at 0x%04x", type_names [UNMASK_TYPE (value->stype)], ctx->ip_offset));   
 }
 
 static gboolean
@@ -2465,13 +2578,12 @@ check_is_valid_type_for_field_ops (VerifyContext *ctx, int token, ILStackDesc *o
        /*must be one of: object type, managed pointer, unmanaged pointer (native int) or an instance of a value type */
        if (!((obj->stype == TYPE_COMPLEX)
                /* the managed reference must be to an object or value type */
-               || ((obj->stype & POINTER_MASK) && (UNMASK_TYPE (obj->stype) == TYPE_COMPLEX))
+               || (( IS_MANAGED_POINTER (obj->stype)) && (UNMASK_TYPE (obj->stype) == TYPE_COMPLEX))
                || (obj->stype == TYPE_NATIVE_INT)
                || (obj->stype == TYPE_PTR)
                || (obj->stype == TYPE_COMPLEX))) {
                CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid argument %s to load field at 0x%04x", type_names [UNMASK_TYPE (obj->stype)], ctx->ip_offset));
        }
-       
 
        field = mono_field_from_token (ctx->image, token, &klass, ctx->generic_context);
        if (!field) {
@@ -2495,6 +2607,9 @@ check_is_valid_type_for_field_ops (VerifyContext *ctx, int token, ILStackDesc *o
                if (!verify_stack_type_compatibility (ctx, type, obj->type, FALSE)) {
                        CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Type at stack is not compatible to reference the field at 0x%04x", ctx->ip_offset));
                }
+
+               if (!mono_method_can_access_field (ctx->method, field))
+                       CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Type at stack is not accessible at 0x%04x", ctx->ip_offset));
        }
 
        if (!mono_method_can_access_field (ctx->method, field))
@@ -2527,7 +2642,7 @@ do_push_field (VerifyContext *ctx, int token, gboolean take_addr)
                !(field->parent == ctx->method->klass && (ctx->method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) && !strcmp (".ctor", ctx->method->name)))
                CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot take the address of a init-only field at 0x%04x", ctx->ip_offset));
 
-       set_stack_value (stack_push (ctx), field->type, take_addr, FALSE);
+       set_stack_value (stack_push (ctx), field->type, take_addr);
 }
 
 static void
@@ -2546,7 +2661,178 @@ do_store_field (VerifyContext *ctx, int token)
                return;
 
        if (!verify_type_compat (ctx, field->type, value))
-               CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Incompatible type %s in field store at 0x%04x", type_names [value->stype & TYPE_MASK], ctx->ip_offset));    
+               CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Incompatible type %s in field store at 0x%04x", type_names [UNMASK_TYPE (value->stype)], ctx->ip_offset));  
+}
+
+/*TODO proper handle for Nullable<T>*/
+static void
+do_box_value (VerifyContext *ctx, int klass_token)
+{
+       ILStackDesc *value;
+       MonoType *type = get_boxable_mono_type (ctx, klass_token);
+
+       if (!type)
+               return;
+
+       if (!check_underflow (ctx, 1))
+               return;
+
+       value = stack_top (ctx);
+       /*box is a nop for reference types*/
+       if (value->stype == TYPE_COMPLEX && MONO_TYPE_IS_REFERENCE (value->type) && MONO_TYPE_IS_REFERENCE (type))
+               return;
+
+       value = stack_pop (ctx);
+
+       if (!verify_type_compat (ctx, type, value))
+               CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid type at stack for boxing operation at 0x%04x", ctx->ip_offset));
+
+       stack_push_val (ctx, TYPE_COMPLEX, mono_class_get_type (mono_defaults.object_class));
+}
+
+static void
+do_unbox_value (VerifyContext *ctx, int klass_token)
+{
+       ILStackDesc *value;
+       MonoType *type = get_boxable_mono_type (ctx, klass_token);
+
+       if (!type)
+               return;
+       if (!check_underflow (ctx, 1))
+               return;
+
+       value = stack_pop (ctx);
+
+       if (value->stype != TYPE_COMPLEX || value->type->type != MONO_TYPE_OBJECT)
+               CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid type %s at stack for unbox operation at 0x%04x", type_names [UNMASK_TYPE (value->stype)], ctx->ip_offset));
+
+       //TODO Pushed managed pointer is haver controled mutability (CMMP) 
+       set_stack_value (stack_push (ctx), mono_type_get_type_byref (type), FALSE);
+}
+
+static void
+do_unary_math_op (VerifyContext *ctx, int op)
+{
+       ILStackDesc *value;
+       if (!check_underflow (ctx, 1))
+               return;
+       value = stack_top (ctx);
+       switch(value->stype) {
+       case TYPE_I4:
+       case TYPE_I8:
+       case TYPE_NATIVE_INT:
+               break;
+       case TYPE_R8:
+               if (op == CEE_NEG)
+                       break;
+       case TYPE_COMPLEX: /*only enums are ok*/
+               if (value->type->type == MONO_TYPE_VALUETYPE && value->type->data.klass->enumtype)
+                       break;
+       default:
+               CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid type at stack for unary not at 0x%04x", ctx->ip_offset));
+       }
+}
+
+static void
+do_conversion (VerifyContext *ctx, int kind) 
+{
+       ILStackDesc *value;
+       if (!check_underflow (ctx, 1))
+               return;
+       value = stack_pop (ctx);
+
+       switch(value->stype) {
+       case TYPE_I4:
+       case TYPE_I8:
+       case TYPE_NATIVE_INT:
+       case TYPE_R8:
+               break;
+       default:
+               CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid type at stack for conversion operation at 0x%04x", ctx->ip_offset));
+       }
+
+       switch (kind) {
+       case TYPE_I4:
+               stack_push_val (ctx, TYPE_I4, &mono_defaults.int32_class->byval_arg);
+               break;
+       case TYPE_I8:
+               stack_push_val (ctx,TYPE_I8, &mono_defaults.int64_class->byval_arg);
+               break;
+       case TYPE_R8:
+               stack_push_val (ctx, TYPE_R8, &mono_defaults.double_class->byval_arg);
+               break;
+       case TYPE_NATIVE_INT:
+               stack_push_val (ctx, TYPE_NATIVE_INT, &mono_defaults.int_class->byval_arg);
+               break;
+       default:
+               g_error ("unknown type %02x in conversion", kind);
+
+       }
+}
+
+static void
+do_load_token (VerifyContext *ctx, int token) 
+{
+       gpointer handle;
+       MonoClass *handle_class;
+       if (!check_overflow (ctx))
+               return;
+       handle = mono_ldtoken (ctx->image, token, &handle_class, ctx->generic_context);
+       if (!handle) {
+               ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid token 0x%x for ldtoken at 0x%04x", token, ctx->ip_offset));
+               return;
+       }
+       stack_push_val (ctx, TYPE_COMPLEX, mono_class_get_type (handle_class));
+}
+
+static void
+do_ldobj_value (VerifyContext *ctx, int token) 
+{
+       ILStackDesc *value;
+       MonoType *type = get_boxable_mono_type (ctx, token);
+
+       if (!type)
+               return;
+
+       if (!check_underflow (ctx, 1))
+               return;
+
+       value = stack_pop (ctx);
+       if (!IS_MANAGED_POINTER (value->stype) 
+                       && value->stype != TYPE_NATIVE_INT
+                       && !(value->stype == TYPE_PTR && value->type->type != MONO_TYPE_FNPTR)) {
+               ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid argument %s to ldobj at 0x%04x", type_names [UNMASK_TYPE (value->stype)], ctx->ip_offset));
+               return;
+       }
+
+       if (value->stype == TYPE_NATIVE_INT)
+               CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Using native pointer to ldobj at 0x%04x", ctx->ip_offset));
+
+       /*We have a byval on the stack, we */
+       if (!verify_stack_type_compatibility (ctx, type, mono_type_get_type_byval (value->type), TRUE))
+               CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid type at stack for ldojb operation at 0x%04x", ctx->ip_offset));
+
+       set_stack_value (stack_push (ctx), type, FALSE);
+}
+
+static void
+do_newarr (VerifyContext *ctx, int token) 
+{
+       ILStackDesc *value;
+       MonoType *type = get_boxable_mono_type (ctx, token);
+
+       if (!type)
+               return;
+
+       if (!check_underflow (ctx, 1))
+               return;
+
+       value = stack_pop (ctx);
+       if (value->stype != TYPE_I4 && value->stype != TYPE_NATIVE_INT)
+               CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Array size type on stack (%s) is not a verifiable type at 0x%04x", type_names [UNMASK_TYPE (value->stype)], ctx->ip_offset));
+
+       set_stack_value (stack_push (ctx), mono_class_get_type (mono_array_class_get (mono_class_from_mono_type (type), 1)), FALSE);
 }
 
 /*Merge the stacks and perform compat checks*/
@@ -2582,23 +2868,30 @@ merge_stacks (VerifyContext *ctx, ILCodeDesc *from, ILCodeDesc *to, int start)
                int from_stype = from_slot->stype;
                int to_stype = to_slot->stype;
 
-               /* This is the only case of merging between verification types*/
-               if ((from_stype == TYPE_I4 && to_stype == TYPE_NATIVE_INT) ||
-                       (from_stype == TYPE_NATIVE_INT && to_stype == TYPE_I4)) {
+#define IS_NATIVE_INT_AND_I4(val0, val1) (UNMASK_TYPE(val0) == TYPE_NATIVE_INT && \
+                       UNMASK_TYPE(val1->stype) == TYPE_I4 && (val1->type->type == MONO_TYPE_I4 || val1->type->type == MONO_TYPE_U4))
+               /* This is the only case of merging between verification types.
+                * Both stack values must be either native int or int4, and both must be either byref or not.*/
+               if ((IS_NATIVE_INT_AND_I4 (from_stype, to_slot) || IS_NATIVE_INT_AND_I4 (to_stype, from_slot)) &&
+                       !(IS_MANAGED_POINTER (from_stype) ^ IS_MANAGED_POINTER (to_stype))) {
+                       printf ("----is native int\n");
                        to_slot->stype = TYPE_NATIVE_INT;
-                       continue;               
-               } 
+                       if (UNMASK_TYPE(from_stype) == TYPE_NATIVE_INT)
+                               to_slot->type = from_slot->type;
+                       continue;
+               }
+#undef IS_NATIVE_INT_OR_I4
 
                if (from_stype != to_stype) {
                        VERIFIER_DEBUG ( printf ("diferent stack types %d x %d\n", from_stype, to_stype); );
                        CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Could not merge stacks, diferent verification types (%s x %s)",
-                               type_names [from_stype & TYPE_MASK], type_names [to_stype & TYPE_MASK])); 
+                               type_names [UNMASK_TYPE (from_stype)], type_names [UNMASK_TYPE (to_stype)])); 
                        goto end_verify;
                }
 
-               if (from_stype & POINTER_MASK) {
-                       from_stype &= ~POINTER_MASK;
-                       to_stype &= ~POINTER_MASK;
+               if (IS_MANAGED_POINTER (from_stype)) {
+                       from_stype = UNMASK_TYPE (from_stype);
+                       to_stype = UNMASK_TYPE (to_stype);
 
                        if (from_slot->type && !verify_stack_type_compatibility (ctx, to_slot->type, from_slot->type, TRUE)) {
                                CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Could not merge stacks, managed pointer types not compatible")); 
@@ -2644,11 +2937,11 @@ mono_method_verify (MonoMethod *method, int level)
        const unsigned char *target = NULL; /* branch target */
        int i, n, need_merge = 0, start = 0;
        guint token, ip_offset = 0, prefix = 0;
-       MonoClass *klass;
        MonoMethod *cmethod;
        MonoGenericContext *generic_context = NULL;
        MonoImage *image;
        VerifyContext ctx;
+       VERIFIER_DEBUG ( printf ("Verify IL for method %s %s\n",  method->klass->name, method->name); );
 
        if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
                        (method->flags & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT))) {
@@ -2658,7 +2951,15 @@ mono_method_verify (MonoMethod *method, int level)
        memset (&ctx, 0, sizeof (VerifyContext));
 
        ctx.signature = mono_method_signature (method);
+       if (!ctx.signature) {
+               ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Could not decode method signature"));
+               return ctx.list;
+       }
        ctx.header = mono_method_get_header (method);
+       if (!ctx.header) {
+               ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Could not decode method header"));
+               return ctx.list;
+       }
        ctx.method = method;
        ip = ctx.header->code;
        end = ip + ctx.header->code_size;
@@ -2681,7 +2982,7 @@ mono_method_verify (MonoMethod *method, int level)
 
        if (ctx.signature->hasthis) {
                ctx.params = g_new0 (MonoType*, ctx.max_args);
-               ctx.params [0] = &method->klass->this_arg;
+               ctx.params [0] = method->klass->valuetype ? &method->klass->this_arg : &method->klass->byval_arg;
                memcpy (ctx.params + 1, ctx.signature->params, sizeof (MonoType *) * ctx.signature->param_count);
        } else {
                ctx.params = ctx.signature->params;
@@ -2690,18 +2991,30 @@ mono_method_verify (MonoMethod *method, int level)
        if (ctx.signature->is_inflated)
                ctx.generic_context = generic_context = mono_method_get_context (method);
 
-       stack_init(&ctx, &ctx.eval);
+       stack_init (&ctx, &ctx.eval);
 
 
-       /* TODO implement exception entry
-       for (i = 0; i < header->num_clauses; ++i) {
-               MonoExceptionClause *clause = &header->clauses [i];
-               // catch blocks have the exception on the stack. 
+       for (i = 0; i < ctx.header->num_clauses; ++i) {
+               MonoExceptionClause *clause = ctx.header->clauses + i;
+               /* catch blocks and filter have the exception on the stack. */
+               /* must check boundaries for handler_offset and handler_start < handler_start*/
                if (clause->flags == MONO_EXCEPTION_CLAUSE_NONE) {
-                       code [clause->handler_offset].size = 1;
-                       code [clause->handler_offset].flags |= IL_CODE_FLAG_SEEN;
+                       ILCodeDesc *code = ctx.code + clause->handler_offset;
+                       stack_init (&ctx, code);
+                       code->stack [0].stype = TYPE_COMPLEX;
+                       code->stack [0].type = &clause->data.catch_class->byval_arg;
+                       code->size = 1;
+                       code->flags = IL_CODE_FLAG_SEEN;
+               }
+               else if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
+                       ILCodeDesc *code = ctx.code + clause->data.filter_offset;
+                       stack_init (&ctx, code);
+                       code->stack [0].stype = TYPE_COMPLEX;
+                       code->stack [0].type = &mono_defaults.exception_class->byval_arg;
+                       code->size = 1;
+                       code->flags = IL_CODE_FLAG_SEEN;
                }
-       }*/
+       }
 
        while (ip < end && ctx.valid) {
                ctx.ip_offset = ip_offset = ip - ctx.header->code;
@@ -2833,19 +3146,19 @@ mono_method_verify (MonoMethod *method, int level)
                case CEE_LDC_I4_7:
                case CEE_LDC_I4_8:
                        if (check_overflow (&ctx))
-                               stack_push_val (&ctx, TYPE_I4, &mono_defaults.int_class->byval_arg);
+                               stack_push_val (&ctx, TYPE_I4, &mono_defaults.int32_class->byval_arg);
                        ++ip;
                        break;
 
                case CEE_LDC_I4_S:
                        if (check_overflow (&ctx))
-                               stack_push_val (&ctx, TYPE_I4, &mono_defaults.int_class->byval_arg);
+                               stack_push_val (&ctx, TYPE_I4, &mono_defaults.int32_class->byval_arg);
                        ip += 2;
                        break;
 
                case CEE_LDC_I4:
                        if (check_overflow (&ctx))
-                               stack_push_val (&ctx,TYPE_I4, &mono_defaults.int_class->byval_arg);
+                               stack_push_val (&ctx,TYPE_I4, &mono_defaults.int32_class->byval_arg);
                        ip += 5;
                        break;
 
@@ -3042,23 +3355,42 @@ mono_method_verify (MonoMethod *method, int level)
                        ++ip;
                        break;
 
-               //TODO: implement proper typecheck
-               case CEE_NEG:
                case CEE_NOT:
+               case CEE_NEG:
+                       do_unary_math_op (&ctx, *ip);
+                       ++ip;
+                       break;
+
+               //TODO: implement proper typecheck
                case CEE_CONV_I1:
                case CEE_CONV_I2:
                case CEE_CONV_I4:
+               case CEE_CONV_U1:
+               case CEE_CONV_U2:
+               case CEE_CONV_U4:
+                       do_conversion (&ctx, TYPE_I4);
+                       ++ip;
+                       break;                  
+
                case CEE_CONV_I8:
+               case CEE_CONV_U8:
+                       do_conversion (&ctx, TYPE_I8);
+                       ++ip;
+                       break;                  
+
                case CEE_CONV_R4:
                case CEE_CONV_R8:
-               case CEE_CONV_U4:
-               case CEE_CONV_U8:
-                       if (!check_underflow (&ctx, 1))
-                               break;
-                       if (type_from_op (*ip, stack_top (&ctx)) == TYPE_INV)
-                               ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid arguments to opcode 0x%02x at 0x%04x", *ip, ip_offset));
+               case CEE_CONV_R_UN:
+                       do_conversion (&ctx, TYPE_R8);
+                       ++ip;
+                       break;                  
+
+               case CEE_CONV_I:
+               case CEE_CONV_U:
+                       do_conversion (&ctx, TYPE_NATIVE_INT);
                        ++ip;
                        break;
+
                case CEE_CPOBJ:
                        token = read32 (ip + 1);
                        if (!check_underflow (&ctx, 2))
@@ -3066,21 +3398,12 @@ mono_method_verify (MonoMethod *method, int level)
                        ctx.eval.size -= 2;
                        ip += 5;
                        break;
+
                case CEE_LDOBJ:
-                       token = read32 (ip + 1);
-                       if (!check_underflow (&ctx, 1))
-                               break;
-                       if (stack_top (&ctx)->stype != TYPE_COMPLEX)
-                               ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid argument to ldobj at 0x%04x", ip_offset));
-                       klass = mono_class_get_full (image, token, generic_context);
-                       if (!klass)
-                               ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Cannot load class from token 0x%08x at 0x%04x", token, ip_offset));
-                       if (!klass->valuetype)
-                               ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Class is not a valuetype at 0x%04x", ip_offset));
-                       stack_top (&ctx)->stype = TYPE_COMPLEX;
-                       stack_top (&ctx)->type = &klass->byval_arg;
+                       do_ldobj_value (&ctx, read32 (ip + 1));
                        ip += 5;
                        break;
+
                case CEE_LDSTR:
                        /*TODO verify if token is a valid string literal*/
                        token = read32 (ip + 1);
@@ -3112,24 +3435,12 @@ mono_method_verify (MonoMethod *method, int level)
                                break;
                        ip += 5;
                        break;
-               case CEE_CONV_R_UN:
-                       if (!check_underflow (&ctx, 1))
-                               break;
-                       ++ip;
-                       break;
                case CEE_UNUSED58:
                case CEE_UNUSED1:
                        ++ip; /* warn, error ? */
                        break;
                case CEE_UNBOX:
-                       token = read32 (ip + 1);
-                       if (!check_underflow (&ctx, 1))
-                               break;
-                       if (stack_top (&ctx)->stype != TYPE_COMPLEX)
-                               ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid argument %s to unbox at 0x%04x", type_names [stack_top (&ctx)->stype], ip_offset));
-
-                       stack_top (&ctx)->stype = TYPE_COMPLEX;
-                       stack_top (&ctx)->type = NULL;
+                       do_unbox_value (&ctx, read32 (ip + 1));
                        ip += 5;
                        break;
                case CEE_THROW:
@@ -3168,44 +3479,45 @@ mono_method_verify (MonoMethod *method, int level)
                        token = read32 (ip + 1);
                        ip += 5;
                        break;
+
                case CEE_CONV_OVF_I1_UN:
                case CEE_CONV_OVF_I2_UN:
                case CEE_CONV_OVF_I4_UN:
-               case CEE_CONV_OVF_I8_UN:
                case CEE_CONV_OVF_U1_UN:
                case CEE_CONV_OVF_U2_UN:
                case CEE_CONV_OVF_U4_UN:
+                       do_conversion (&ctx, TYPE_I4);
+                       ++ip;
+                       break;                  
+
+               case CEE_CONV_OVF_I8_UN:
                case CEE_CONV_OVF_U8_UN:
+                       do_conversion (&ctx, TYPE_I8);
+                       ++ip;
+                       break;                  
+
                case CEE_CONV_OVF_I_UN:
                case CEE_CONV_OVF_U_UN:
-                       if (!check_underflow (&ctx, 1))
-                               break;
-                       if (type_from_op (*ip, stack_top (&ctx)) == TYPE_INV)
-                               ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid arguments to opcode 0x%02x at 0x%04x", *ip, ip_offset));
+                       do_conversion (&ctx, TYPE_NATIVE_INT);
                        ++ip;
                        break;
+
                case CEE_BOX:
-                       if (!check_underflow (&ctx, 1))
-                               break;
-                       token = read32 (ip + 1);
-                       if ( stack_top (&ctx)->stype == TYPE_COMPLEX)
-                               ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid argument %s to box at 0x%04x", type_names [stack_top (&ctx)->stype], ip_offset));
-                       stack_top (&ctx)->stype = TYPE_COMPLEX;
+                       do_box_value (&ctx, read32 (ip + 1));
                        ip += 5;
                        break;
+
                case CEE_NEWARR:
-                       if (!check_underflow (&ctx, 1))
-                               break;
-                       token = read32 (ip + 1);
-                       stack_top (&ctx)->stype = TYPE_COMPLEX;
+                       do_newarr (&ctx, read32 (ip + 1));
                        ip += 5;
                        break;
+
                case CEE_LDLEN:
                        if (!check_underflow (&ctx, 1))
                                break;
                        if (stack_top (&ctx)->stype != TYPE_COMPLEX)
                                ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid argument to ldlen at 0x%04x", ip_offset));
-                       stack_top (&ctx)->type = &mono_defaults.int_class->byval_arg; /* FIXME: use a native int type */
+                       stack_top (&ctx)->type = &mono_defaults.int32_class->byval_arg; /* FIXME: use a native int type */
                        stack_top (&ctx)->stype = TYPE_PTR;
                        ++ip;
                        break;
@@ -3273,20 +3585,29 @@ mono_method_verify (MonoMethod *method, int level)
                case CEE_UNUSED17:
                        ++ip; /* warn, error ? */
                        break;
+
                case CEE_CONV_OVF_I1:
                case CEE_CONV_OVF_U1:
                case CEE_CONV_OVF_I2:
                case CEE_CONV_OVF_U2:
                case CEE_CONV_OVF_I4:
                case CEE_CONV_OVF_U4:
+                       do_conversion (&ctx, TYPE_I4);
+                       ++ip;
+                       break;
+
                case CEE_CONV_OVF_I8:
                case CEE_CONV_OVF_U8:
-                       if (!check_underflow (&ctx, 1))
-                               break;
-                       if (type_from_op (*ip, stack_top (&ctx)) == TYPE_INV)
-                               ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid arguments to opcode 0x%02x at 0x%04x", *ip, ip_offset));
+                       do_conversion (&ctx, TYPE_I8);
                        ++ip;
                        break;
+
+               case CEE_CONV_OVF_I:
+               case CEE_CONV_OVF_U:
+                       do_conversion (&ctx, TYPE_NATIVE_INT);
+                       ++ip;
+                       break;
+
                case CEE_UNUSED50:
                case CEE_UNUSED18:
                case CEE_UNUSED19:
@@ -3328,23 +3649,10 @@ mono_method_verify (MonoMethod *method, int level)
                        ++ip; /* warn, error ? */
                        break;
                case CEE_LDTOKEN:
-                       if (!check_overflow (&ctx))
-                               break;
-                       token = read32 (ip + 1);
-                       ++ctx.eval.size;
+                       do_load_token (&ctx, read32 (ip + 1));
                        ip += 5;
                        break;
-               case CEE_CONV_U2:
-               case CEE_CONV_U1:
-               case CEE_CONV_I:
-               case CEE_CONV_OVF_I:
-               case CEE_CONV_OVF_U:
-                       if (!check_underflow (&ctx, 1))
-                               break;
-                       if (type_from_op (*ip, stack_top (&ctx)) == TYPE_INV)
-                               ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid arguments to opcode 0x%02x at 0x%04x", *ip, ip_offset));
-                       ++ip;
-                       break;
+
                case CEE_ADD_OVF:
                case CEE_ADD_OVF_UN:
                case CEE_MUL_OVF:
@@ -3384,11 +3692,6 @@ mono_method_verify (MonoMethod *method, int level)
                        ctx.eval.size -= 2;
                        ++ip;
                        break;
-               case CEE_CONV_U:
-                       if (!check_underflow (&ctx, 1))
-                               break;
-                       ++ip;
-                       break;
                case CEE_UNUSED26:
                case CEE_UNUSED27:
                case CEE_UNUSED28:
@@ -3551,7 +3854,7 @@ mono_method_verify (MonoMethod *method, int level)
                                        break;
                                token = read32 (ip + 1);
                                ip += 5;
-                               stack_top (&ctx)->type = &mono_defaults.uint_class->byval_arg;
+                               stack_top (&ctx)->type = &mono_defaults.uint32_class->byval_arg;
                                stack_top (&ctx)->stype = TYPE_I4;
                                ctx.eval.size++;
                                break;
@@ -3585,8 +3888,10 @@ invalid_cil:
                }
        }
 
-       g_free (ctx.eval.stack);
-       g_free (ctx.code);
+       if (ctx.eval.stack)
+               g_free (ctx.eval.stack);
+       if (ctx.code)
+               g_free (ctx.code);
        if (ctx.signature->hasthis)
                g_free (ctx.params);