Author: kumpera
Date: 2008-02-07 09:40:26 -0500 (Thu, 07 Feb 2008)
New Revision: 95142

Modified:
   trunk/mono/mono/metadata/ChangeLog
   trunk/mono/mono/metadata/verify.c
Log:
2008-02-07 Rodrigo Kumpera  <[EMAIL PROTECTED]>

        * verify.c (mono_type_is_enum_type): Added. Test if a type is an enum.

        * verify.c (mono_type_get_underlying_type_any): Added. Return the 
underlying
        type of an enum even if the argument is byref.

        * verify.c: Replace all explicit uses of enumtype and enum_basetype
        to calls to mono_type_is_enum_type and 
mono_type_get_underlying_type_any.

        * verify.c: Check for an enum in all cases of MONO_TYPE_GENERICINST.

        *verify.c (verify_type_compatibility_full): Make enum types
        compatible with their base types.

        * verify.c (is_compatible_boxed_valuetype): Added. Check if both
        types are compatible for the special case of a boxed valuetype and
        System.Object.

        * verify.c (verify_stack_type_compatibility): The function
        is_compatible_boxed_valuetype was extracted from here.

        * verify.c (push_arg): Only set ctx->has_this_store if the method
        is not static.

        * verify.c (do_ldelem): Fixed a typo in an error message and added
        strict check for mixing int32 and native int as the array type
        and ldelem type.

        * verify.c (merge_stacks): Consider boxed valuetypes in the
        compatibility checks.



Modified: trunk/mono/mono/metadata/ChangeLog
===================================================================
--- trunk/mono/mono/metadata/ChangeLog  2008-02-07 14:18:06 UTC (rev 95141)
+++ trunk/mono/mono/metadata/ChangeLog  2008-02-07 14:40:26 UTC (rev 95142)
@@ -1,3 +1,35 @@
+2008-02-07 Rodrigo Kumpera  <[EMAIL PROTECTED]>
+
+       * verify.c (mono_type_is_enum_type): Added. Test if a type is an enum.
+
+       * verify.c (mono_type_get_underlying_type_any): Added. Return the 
underlying
+       type of an enum even if the argument is byref.
+
+       * verify.c: Replace all explicit uses of enumtype and enum_basetype
+       to calls to mono_type_is_enum_type and 
mono_type_get_underlying_type_any.
+
+       * verify.c: Check for an enum in all cases of MONO_TYPE_GENERICINST.
+
+       *verify.c (verify_type_compatibility_full): Make enum types
+       compatible with their base types.
+
+       * verify.c (is_compatible_boxed_valuetype): Added. Check if both
+       types are compatible for the special case of a boxed valuetype and
+       System.Object.
+
+       * verify.c (verify_stack_type_compatibility): The function
+       is_compatible_boxed_valuetype was extracted from here.
+
+       * verify.c (push_arg): Only set ctx->has_this_store if the method
+       is not static.
+
+       * verify.c (do_ldelem): Fixed a typo in an error message and added
+       strict check for mixing int32 and native int as the array type
+       and ldelem type.
+
+       * verify.c (merge_stacks): Consider boxed valuetypes in the
+       compatibility checks.
+
 2008-02-07  Massimiliano Mantione  <[EMAIL PROTECTED]>
        * profiler.h: (MonoGCEvent): Added start-stop the world events.
 

Modified: trunk/mono/mono/metadata/verify.c
===================================================================
--- trunk/mono/mono/metadata/verify.c   2008-02-07 14:18:06 UTC (rev 95141)
+++ trunk/mono/mono/metadata/verify.c   2008-02-07 14:40:26 UTC (rev 95142)
@@ -226,6 +226,38 @@
        return res;
 }
 
+/*
+ * mono_type_is_enum_type:
+ * 
+ * Returns TRUE if @type is an enum type. 
+ */
+static gboolean
+mono_type_is_enum_type (MonoType *type)
+{
+       if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
+               return TRUE;
+       if (type->type == MONO_TYPE_GENERICINST && 
type->data.generic_class->container_class->enumtype)
+               return TRUE;
+       return FALSE;
+}
+
+/*
+ * mono_type_get_underlying_type_any:
+ * 
+ * This functions is just like mono_type_get_underlying_type but it doesn't 
care if the type is byref.
+ * 
+ * Returns the underlying type of @type regardless if it is byref or not.
+ */
+static MonoType*
+mono_type_get_underlying_type_any (MonoType *type)
+{
+       if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
+               return type->data.klass->enum_basetype;
+       if (type->type == MONO_TYPE_GENERICINST && 
type->data.generic_class->container_class->enumtype)
+               return type->data.generic_class->container_class->enum_basetype;
+       return type;
+}
+
 #define CTOR_REQUIRED_FLAGS (METHOD_ATTRIBUTE_SPECIAL_NAME | 
METHOD_ATTRIBUTE_RT_SPECIAL_NAME)
 #define CTOR_INVALID_FLAGS (METHOD_ATTRIBUTE_STATIC)
 
@@ -1660,9 +1692,17 @@
        case MONO_TYPE_OBJECT:
        case MONO_TYPE_SZARRAY:
        case MONO_TYPE_ARRAY:
-       case MONO_TYPE_GENERICINST:
                return TYPE_COMPLEX | mask;
 
+       case MONO_TYPE_GENERICINST:
+               if (mono_type_is_enum_type (type)) {
+                       type = mono_type_get_underlying_type_any (type);
+                       type_kind = type->type;
+                       goto handle_enum;
+               } else {
+                       return TYPE_COMPLEX | mask;
+               }
+
        case MONO_TYPE_I8:
        case MONO_TYPE_U8:
                return TYPE_I8 | mask;
@@ -1672,12 +1712,13 @@
                return TYPE_R8 | mask;
 
        case MONO_TYPE_VALUETYPE:
-               if (type->data.klass->enumtype) {
-                       type = type->data.klass->enum_basetype;
+               if (mono_type_is_enum_type (type)) {
+                       type = mono_type_get_underlying_type_any (type);
                        type_kind = type->type;
                        goto handle_enum;
-               } else 
+               } else {
                        return TYPE_COMPLEX | mask;
+               }
 
        default:
                VERIFIER_DEBUG ( printf ("unknown type %02x in eval stack 
type\n", type->type); );
@@ -1729,11 +1770,21 @@
        case MONO_TYPE_SZARRAY:
        case MONO_TYPE_ARRAY:
 
-       case MONO_TYPE_GENERICINST:
        case MONO_TYPE_VAR:
        case MONO_TYPE_MVAR: 
                stack->stype = TYPE_COMPLEX | mask;
                break;
+               
+       case MONO_TYPE_GENERICINST:
+               if (mono_type_is_enum_type (type)) {
+                       type = mono_type_get_underlying_type_any (type);
+                       type_kind = type->type;
+                       goto handle_enum;
+               } else {
+                       stack->stype = TYPE_COMPLEX | mask;
+                       break;
+               }
+
        case MONO_TYPE_I8:
        case MONO_TYPE_U8:
                stack->stype = TYPE_I8 | mask;
@@ -1743,8 +1794,8 @@
                stack->stype = TYPE_R8 | mask;
                break;
        case MONO_TYPE_VALUETYPE:
-               if (type->data.klass->enumtype) {
-                       type = type->data.klass->enum_basetype;
+               if (mono_type_is_enum_type (type)) {
+                       type = mono_type_get_underlying_type_any (type);
                        type_kind = type->type;
                        goto handle_enum;
                } else {
@@ -1804,8 +1855,8 @@
                return mono_class_is_assignable_from (target->data.klass, 
candidate->data.klass);
 
        case MONO_TYPE_VALUETYPE:
-               if (target->data.klass->enumtype) {
-                       target = target->data.klass->enum_basetype;
+               if (mono_type_is_enum_type (target)) {
+                       target = mono_type_get_underlying_type_any (target);
                        goto handle_enum;
                } else {
                        if (candidate->type != MONO_TYPE_VALUETYPE)
@@ -1946,6 +1997,7 @@
 #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)
 
+       MonoType *original_candidate = candidate;
        VERIFIER_DEBUG ( printf ("checking type compatibility %p %p[%x][%x] 
%p[%x][%x]\n", ctx, target, target->type, target->byref, candidate, 
candidate->type, candidate->byref); );
 
        /*only one is byref */
@@ -1958,6 +2010,8 @@
                return FALSE;
        }
        strict |= target->byref;
+       /*From now on we don't care about byref anymore, so it's ok to discard 
it here*/
+       candidate = mono_type_get_underlying_type_any (candidate);
 
 handle_enum:
        switch (target->type) {
@@ -2018,6 +2072,11 @@
        case MONO_TYPE_GENERICINST: {
                MonoGenericClass *left;
                MonoGenericClass *right;
+               if (mono_type_is_enum_type (target)) {
+                       target = mono_type_get_underlying_type_any (target);
+                       goto handle_enum;
+               }
+
                if (candidate->type != MONO_TYPE_GENERICINST)
                        return mono_class_is_assignable_from 
(mono_class_from_mono_type (target), mono_class_from_mono_type (candidate));
                left = target->data.generic_class;
@@ -2030,7 +2089,10 @@
                return candidate->type == MONO_TYPE_STRING;
 
        case MONO_TYPE_CLASS:
-               return mono_class_is_assignable_from (target->data.klass, 
mono_class_from_mono_type (candidate));
+               /* If candidate is an enum it should return true for 
System.Enum and supertypes.
+                * That's why here we use the original type and not the 
underlying type.
+                */ 
+               return mono_class_is_assignable_from (target->data.klass, 
mono_class_from_mono_type (original_candidate));
 
        case MONO_TYPE_OBJECT:
                return MONO_TYPE_IS_REFERENCE (candidate);
@@ -2057,8 +2119,8 @@
        case MONO_TYPE_VALUETYPE:
                if (candidate->type == MONO_TYPE_VALUETYPE && 
target->data.klass == candidate->data.klass)
                        return TRUE;
-               if (target->data.klass->enumtype) {
-                       target = target->data.klass->enum_basetype;
+               if (mono_type_is_enum_type (target)) {
+                       target = mono_type_get_underlying_type_any (target);
                        goto handle_enum;
                }
                return FALSE;
@@ -2089,6 +2151,16 @@
        return verify_type_compatibility_full (ctx, target, candidate, FALSE);
 }
 
+/*
+ * is_compatible_boxed_valuetype:
+ * 
+ * Returns TRUE if @candidate / @stack is a boxed valuetype and @type is 
System.Object. 
+ */
+static gboolean
+is_compatible_boxed_valuetype (MonoType *type, MonoType *candidate, 
ILStackDesc *stack)
+{
+       return type->type == MONO_TYPE_OBJECT && !type->byref && 
mono_class_from_mono_type (candidate)->valuetype && !candidate->byref && 
stack_slot_is_boxed_value (stack);
+}
 
 static int
 verify_stack_type_compatibility (VerifyContext *ctx, MonoType *type, 
ILStackDesc *stack)
@@ -2097,7 +2169,7 @@
        if (MONO_TYPE_IS_REFERENCE (type) && !type->byref && 
stack_slot_is_null_literal (stack))
                return TRUE;
 
-       if (type->type == MONO_TYPE_OBJECT && mono_class_from_mono_type 
(candidate)->valuetype && !candidate->byref && stack_slot_is_boxed_value 
(stack))
+       if (is_compatible_boxed_valuetype (type, candidate, stack))
                return TRUE;
 
        return verify_type_compatibility_full (ctx, type, candidate, FALSE);
@@ -2290,7 +2362,7 @@
                        CODE_NOT_VERIFIABLE (ctx, g_strdup_printf 
("Incompatible type %s in argument store at 0x%04x", stack_slot_get_name 
(value), ctx->ip_offset));
                }
        }
-       if (arg == 0)
+       if (arg == 0 && !(ctx->method->flags & METHOD_ATTRIBUTE_STATIC))
                ctx->has_this_store = 1;
 }
 
@@ -2867,7 +2939,7 @@
                if (op == CEE_NEG)
                        break;
        case TYPE_COMPLEX: /*only enums are ok*/
-               if (value->type->type == MONO_TYPE_VALUETYPE && 
value->type->data.klass->enumtype)
+               if (mono_type_is_enum_type (value->type))
                        break;
        default:
                CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid type at 
stack for unary not at 0x%04x", ctx->ip_offset));
@@ -3318,6 +3390,7 @@
 static void
 do_ldelem (VerifyContext *ctx, int opcode, int token)
 {
+#define IS_ONE_OF2(T, A, B) (T == A || T == B)
        ILStackDesc *index, *array;
        MonoType *type;
        if (!check_underflow (ctx, 2))
@@ -3337,7 +3410,7 @@
        array = stack_pop (ctx);
 
        if (stack_slot_get_type (index) != TYPE_I4 && stack_slot_get_type 
(index) != TYPE_NATIVE_INT)
-               CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Index type(%s) for 
ldelema is not an int or a native int at 0x%04x", stack_slot_get_name (index), 
ctx->ip_offset));
+               CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Index type(%s) for 
ldelem.X is not an int or a native int at 0x%04x", stack_slot_get_name (index), 
ctx->ip_offset));
 
        if (!stack_slot_is_null_literal (array)) {
                if (stack_slot_get_type (array) != TYPE_COMPLEX || 
array->type->type != MONO_TYPE_SZARRAY)
@@ -3347,13 +3420,23 @@
                                if (array->type->data.klass->valuetype)
                                        CODE_NOT_VERIFIABLE (ctx, 
g_strdup_printf ("Invalid array type is not a reference type for ldelem.ref 
0x%04x", ctx->ip_offset));
                                type = &array->type->data.klass->byval_arg;
-                       } else if (!verify_type_compatibility_full (ctx, type, 
&array->type->data.klass->byval_arg, TRUE)) {
-                               CODE_NOT_VERIFIABLE (ctx, g_strdup_printf 
("Invalid array type on stack for ldelem.X at 0x%04x", ctx->ip_offset));
+                       } else {
+                               MonoType *candidate = 
&array->type->data.klass->byval_arg;
+                               if (IS_STRICT_MODE (ctx)) {
+                                       MonoType *underlying_type = 
mono_type_get_underlying_type_any (type);
+                                       MonoType *underlying_candidate = 
mono_type_get_underlying_type_any (candidate);
+                                       if ((IS_ONE_OF2 (underlying_type->type, 
MONO_TYPE_I4, MONO_TYPE_U4) && IS_ONE_OF2 (underlying_candidate->type, 
MONO_TYPE_I, MONO_TYPE_U)) ||
+                                               (IS_ONE_OF2 
(underlying_candidate->type, MONO_TYPE_I4, MONO_TYPE_U4) && IS_ONE_OF2 
(underlying_type->type, MONO_TYPE_I, MONO_TYPE_U)))
+                                               CODE_NOT_VERIFIABLE (ctx, 
g_strdup_printf ("Invalid array type on stack for ldelem.X at 0x%04x", 
ctx->ip_offset));
+                               }
+                               if (!verify_type_compatibility_full (ctx, type, 
candidate, TRUE))
+                                       CODE_NOT_VERIFIABLE (ctx, 
g_strdup_printf ("Invalid array type on stack for ldelem.X at 0x%04x", 
ctx->ip_offset));
                        }
                }
        }
 
        set_stack_value (ctx, stack_push (ctx), type, FALSE);
+#undef IS_ONE_OF2
 }
 
 /*FIXME handle arrays that are not 0-indexed*/
@@ -3666,7 +3749,7 @@
        }
 
        //FIXME we need to preserve CMMP attributes
-       //FIXME we must take null literals and boxes values into consideration.
+       //FIXME we must take null literals into consideration.
        for (i = 0; i < from->size; ++i) {
                ILStackDesc *new_slot = from->stack + i;
                ILStackDesc *old_slot = to->stack + i;
@@ -3713,7 +3796,10 @@
                        //No decent super type found, use object
                        match_class = mono_defaults.object_class;
                        goto match_found;
-               }
+               } else if (is_compatible_boxed_valuetype (old_type, new_type, 
new_slot) || is_compatible_boxed_valuetype (new_type, old_type, old_slot)) {
+                       match_class = mono_defaults.object_class;
+                       goto match_found;
+               } 
 
                CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Could not merge 
stacks, types not compatible at 0x%04x", ctx->ip_offset)); 
                goto end_verify;

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to