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