2004-12-29 Martin Baulig <martin@ximian.com>
[mono.git] / mono / metadata / metadata.c
index f3e641d124993e077adbf1a83b5fd4e56f6b5e98..523bec047179b46f0e840cb2847a3fc09e0a45e5 100644 (file)
 #include "private.h"
 #include "class.h"
 
-static void do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *generic_container,
+static void do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContext *generic_context,
                                         const char *ptr, const char **rptr);
 
 static gboolean do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only);
-static gboolean _mono_metadata_generic_class_equal (MonoGenericClass *g1, MonoGenericClass *g2,
+static gboolean mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only);
+static gboolean _mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2,
                                                    gboolean signature_only);
 
 /*
@@ -1059,14 +1060,14 @@ mono_metadata_parse_custom_mod (MonoImage *m, MonoCustomMod *dest, const char *p
  * and dimensions.
  */
 MonoArrayType *
-mono_metadata_parse_array_full (MonoImage *m, MonoGenericContainer *generic_container,
+mono_metadata_parse_array_full (MonoImage *m, MonoGenericContext *generic_context,
                                const char *ptr, const char **rptr)
 {
        int i;
        MonoArrayType *array = g_new0 (MonoArrayType, 1);
        MonoType *etype;
        
-       etype = mono_metadata_parse_type_full (m, generic_container, MONO_PARSE_TYPE, 0, ptr, &ptr);
+       etype = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_TYPE, 0, ptr, &ptr);
        array->eklass = mono_class_from_mono_type (etype);
        array->rank = mono_metadata_decode_value (ptr, &ptr);
 
@@ -1116,7 +1117,7 @@ mono_metadata_free_array (MonoArrayType *array)
  * private static
  * private static literal
  */
-static MonoType
+static const MonoType
 builtin_types[] = {
        /* data, attrs, type,              nmods, byref, pinned */
        {{NULL}, 0,     MONO_TYPE_VOID,    0,     0,     0},
@@ -1211,7 +1212,7 @@ static guint
 mono_generic_class_hash (gconstpointer data)
 {
        const MonoGenericClass *gclass = (const MonoGenericClass *) data;
-       return mono_metadata_type_hash (gclass->generic_type);
+       return mono_metadata_type_hash (&gclass->container_class->byval_arg);
 }
 
 static gboolean
@@ -1238,7 +1239,7 @@ mono_metadata_init (void)
        generic_class_cache = g_hash_table_new (mono_generic_class_hash, mono_generic_class_equal);
 
        for (i = 0; i < NBUILTIN_TYPES (); ++i)
-               g_hash_table_insert (type_cache, &builtin_types [i], &builtin_types [i]);
+               g_hash_table_insert (type_cache, (gpointer) &builtin_types [i], (gpointer) &builtin_types [i]);
 }
 
 /**
@@ -1264,7 +1265,7 @@ mono_metadata_init (void)
  * Returns: a #MonoType structure representing the decoded type.
  */
 MonoType*
-mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *generic_container, MonoParseTypeMode mode,
+mono_metadata_parse_type_full (MonoImage *m, MonoGenericContext *generic_context, MonoParseTypeMode mode,
                               short opt_attrs, const char *ptr, const char **rptr)
 {
        MonoType *type, *cached;
@@ -1344,7 +1345,7 @@ mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *generic_conta
        type->byref = byref;
        type->pinned = pinned ? 1 : 0;
 
-       do_mono_metadata_parse_type (type, m, generic_container, ptr, &ptr);
+       do_mono_metadata_parse_type (type, m, generic_context, ptr, &ptr);
 
        if (rptr)
                *rptr = ptr;
@@ -1390,7 +1391,7 @@ mono_metadata_parse_type (MonoImage *m, MonoParseTypeMode mode, short opt_attrs,
  * Returns: a MonoMethodSignature describing the signature.
  */
 MonoMethodSignature *
-mono_metadata_parse_signature_full (MonoImage *image, MonoGenericContainer *generic_container, guint32 token)
+mono_metadata_parse_signature_full (MonoImage *image, MonoGenericContext *generic_context, guint32 token)
 {
        MonoTableInfo *tables = image->tables;
        guint32 idx = mono_metadata_token_index (token);
@@ -1407,7 +1408,7 @@ mono_metadata_parse_signature_full (MonoImage *image, MonoGenericContainer *gene
        ptr = mono_metadata_blob_heap (image, sig);
        mono_metadata_decode_blob_size (ptr, &ptr);
 
-       return mono_metadata_parse_method_signature_full (image, generic_container, FALSE, ptr, NULL); 
+       return mono_metadata_parse_method_signature_full (image, generic_context, FALSE, ptr, NULL); 
 }
 
 MonoMethodSignature *
@@ -1450,7 +1451,7 @@ mono_metadata_signature_dup (MonoMethodSignature *sig)
  * Returns: a MonoMethodSignature describing the signature.
  */
 MonoMethodSignature *
-mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *generic_container,
+mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContext *generic_context,
                                           int def, const char *ptr, const char **rptr)
 {
        MonoMethodSignature *method;
@@ -1458,7 +1459,7 @@ mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *g
        guint32 hasthis = 0, explicit_this = 0, call_convention, param_count;
        guint32 gen_param_count = 0;
        gboolean is_open = FALSE;
-       MonoGenericContainer *container = NULL;
+       MonoGenericContext *context = NULL;
 
        if (*ptr & 0x10)
                gen_param_count = 1;
@@ -1500,13 +1501,15 @@ mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *g
        if (gen_param_count)
                method->has_type_parameters = 1;
 
-       if (gen_param_count && (!generic_container || !generic_container->is_method)) {
-               container = g_new0 (MonoGenericContainer, 1);
-               container->parent = generic_container;
+       if (gen_param_count && (!generic_context || !generic_context->container->is_method)) {
+               MonoGenericContainer *container = g_new0 (MonoGenericContainer, 1);
+
+               if (generic_context)
+                       container->parent = generic_context->container;
                container->is_signature = 1;
 
-               container->context = g_new0 (MonoGenericContext, 1);
-               container->context->container = container;
+               context = &container->context;
+               container->context.container = container;
 
                container->type_argc = gen_param_count;
                container->type_params = g_new0 (MonoGenericParam, gen_param_count);
@@ -1516,10 +1519,10 @@ mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *g
                        container->type_params [i].num = i;
                }
        } else
-               container = generic_container;
+               context = generic_context;
 
        if (call_convention != 0xa) {
-               method->ret = mono_metadata_parse_type_full (m, container, MONO_PARSE_RET, ret_attrs, ptr, &ptr);
+               method->ret = mono_metadata_parse_type_full (m, context, MONO_PARSE_RET, ret_attrs, ptr, &ptr);
                is_open = mono_class_is_open_constructed_type (method->ret);
        }
 
@@ -1534,7 +1537,7 @@ mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *g
                                ptr++;
                        }
                        method->params [i] = mono_metadata_parse_type_full (
-                               m, container, MONO_PARSE_PARAM, pattrs [i], ptr, &ptr);
+                               m, context, MONO_PARSE_PARAM, pattrs [i], ptr, &ptr);
                        if (!is_open)
                                is_open = mono_class_is_open_constructed_type (method->params [i]);
                }
@@ -1636,7 +1639,7 @@ mono_metadata_inflate_generic_inst (MonoGenericInst *ginst, MonoGenericContext *
 }
 
 MonoGenericInst *
-mono_metadata_parse_generic_inst (MonoImage *m, MonoGenericContainer *generic_container,
+mono_metadata_parse_generic_inst (MonoImage *m, MonoGenericContext *generic_context,
                                  int count, const char *ptr, const char **rptr)
 {
        MonoGenericInst *ginst;
@@ -1647,7 +1650,7 @@ mono_metadata_parse_generic_inst (MonoImage *m, MonoGenericContainer *generic_co
        ginst->type_argv = g_new0 (MonoType*, count);
 
        for (i = 0; i < ginst->type_argc; i++) {
-               MonoType *t = mono_metadata_parse_type_full (m, generic_container, MONO_PARSE_TYPE, 0, ptr, &ptr);
+               MonoType *t = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_TYPE, 0, ptr, &ptr);
 
                ginst->type_argv [i] = t;
                if (!ginst->is_open)
@@ -1661,13 +1664,15 @@ mono_metadata_parse_generic_inst (MonoImage *m, MonoGenericContainer *generic_co
 }
 
 static void
-do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericContainer *generic_container,
+do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericContext *generic_context,
                                      const char *ptr, const char **rptr)
 {
        MonoGenericClass *gclass = g_new0 (MonoGenericClass, 1);
+       MonoGenericContainer *container;
        MonoGenericClass *cached;
        MonoGenericInst *ginst;
        MonoClass *gklass;
+       MonoType *gtype;
        int i, count;
 
        type->data.generic_class = gclass;
@@ -1677,11 +1682,10 @@ do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericC
 
        gclass->klass = g_new0 (MonoClass, 1);
 
-       gclass->generic_type = mono_metadata_parse_type_full (m, generic_container, MONO_PARSE_TYPE, 0, ptr, &ptr);
-
-       gklass = mono_class_from_mono_type (gclass->generic_type);
-       g_assert ((gclass->container = gklass->generic_container) != NULL);
+       gtype = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_TYPE, 0, ptr, &ptr);
+       gclass->container_class = gklass = mono_class_from_mono_type (gtype);
 
+       g_assert ((gclass->context->container = gklass->generic_container) != NULL);
        count = mono_metadata_decode_value (ptr, &ptr);
 
        /*
@@ -1694,7 +1698,7 @@ do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericC
 
        mono_class_create_generic (gclass);
 
-       gclass->inst = mono_metadata_parse_generic_inst (m, generic_container, count, ptr, &ptr);
+       gclass->inst = mono_metadata_parse_generic_inst (m, generic_context, count, ptr, &ptr);
 
        mono_class_create_generic_2 (gclass);
 
@@ -1741,15 +1745,24 @@ do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericC
  * Internal routine to parse a generic type parameter.
  */
 static MonoGenericParam *
-mono_metadata_parse_generic_param (MonoImage *m, MonoGenericContainer *generic_container,
+mono_metadata_parse_generic_param (MonoImage *m, MonoGenericContext *generic_context,
                                   gboolean is_mvar, const char *ptr, const char **rptr)
 {
+       MonoGenericContainer *generic_container;
        int index;
 
        index = mono_metadata_decode_value (ptr, &ptr);
        if (rptr)
                *rptr = ptr;
 
+       g_assert (generic_context);
+       if (generic_context->gmethod)
+               generic_container = generic_context->gmethod->container;
+       else if (generic_context->gclass)
+               generic_container = generic_context->gclass->container_class->generic_container;
+       else
+               generic_container = generic_context->container;
+
        if (!is_mvar) {
                g_assert (generic_container);
                if (generic_container->parent) {
@@ -1786,7 +1799,7 @@ mono_metadata_parse_generic_param (MonoImage *m, MonoGenericContainer *generic_c
  * This extracts a Type as specified in Partition II (22.2.12) 
  */
 static void
-do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *generic_container,
+do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContext *generic_context,
                             const char *ptr, const char **rptr)
 {
        type->type = mono_metadata_decode_value (ptr, &ptr);
@@ -1819,31 +1832,31 @@ do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer
                break;
        }
        case MONO_TYPE_SZARRAY: {
-               MonoType *etype = mono_metadata_parse_type_full (m, generic_container, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
+               MonoType *etype = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
                type->data.klass = mono_class_from_mono_type (etype);
                mono_metadata_free_type (etype);
                break;
        }
        case MONO_TYPE_PTR:
-               type->data.type = mono_metadata_parse_type_full (m, generic_container, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
+               type->data.type = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
                break;
        case MONO_TYPE_FNPTR:
-               type->data.method = mono_metadata_parse_method_signature_full (m, generic_container, 0, ptr, &ptr);
+               type->data.method = mono_metadata_parse_method_signature_full (m, generic_context, 0, ptr, &ptr);
                break;
        case MONO_TYPE_ARRAY:
-               type->data.array = mono_metadata_parse_array_full (m, generic_container, ptr, &ptr);
+               type->data.array = mono_metadata_parse_array_full (m, generic_context, ptr, &ptr);
                break;
 
        case MONO_TYPE_MVAR:
-               type->data.generic_param = mono_metadata_parse_generic_param (m, generic_container, TRUE, ptr, &ptr);
+               type->data.generic_param = mono_metadata_parse_generic_param (m, generic_context, TRUE, ptr, &ptr);
                break;
 
        case MONO_TYPE_VAR:
-               type->data.generic_param = mono_metadata_parse_generic_param (m, generic_container, FALSE, ptr, &ptr);
+               type->data.generic_param = mono_metadata_parse_generic_param (m, generic_context, FALSE, ptr, &ptr);
                break;
 
        case MONO_TYPE_GENERICINST:
-               do_mono_metadata_parse_generic_class (type, m, generic_container, ptr, &ptr);
+               do_mono_metadata_parse_generic_class (type, m, generic_context, ptr, &ptr);
                break;
                
        default:
@@ -2013,7 +2026,7 @@ parse_section_data (MonoImage *m, MonoMethodHeader *mh, const unsigned char *ptr
  * Returns: a MonoMethodHeader.
  */
 MonoMethodHeader *
-mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *generic_container, const char *ptr)
+mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContext *generic_context, const char *ptr)
 {
        MonoMethodHeader *mh;
        unsigned char flags = *(const unsigned char *) ptr;
@@ -2096,7 +2109,7 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *generic_contain
                mh->num_locals = len;
                for (i = 0; i < len; ++i)
                        mh->locals [i] = mono_metadata_parse_type_full (
-                               m, generic_container, MONO_PARSE_LOCAL, 0, locals_ptr, &locals_ptr);
+                               m, generic_context, MONO_PARSE_LOCAL, 0, locals_ptr, &locals_ptr);
        } else {
                mh = g_new0 (MonoMethodHeader, 1);
        }
@@ -2690,11 +2703,9 @@ mono_type_size (MonoType *t, gint *align)
 
                g_assert (!gclass->inst->is_open && !gclass->klass->generic_container);
 
-               if (MONO_TYPE_ISSTRUCT (gclass->generic_type)) {
-                       MonoClass *gklass = mono_class_from_mono_type (gclass->generic_type);
-
-                       if (gklass->enumtype)
-                               return mono_type_size (gklass->enum_basetype, align);
+               if (gclass->container_class->valuetype) {
+                       if (gclass->container_class->enumtype)
+                               return mono_type_size (gclass->container_class->enum_basetype, align);
                        else
                                return mono_class_value_size (gclass->klass, align);
                } else {
@@ -2789,11 +2800,9 @@ mono_type_stack_size (MonoType *t, gint *align)
 
                g_assert (!gclass->inst->is_open && !gclass->klass->generic_container);
 
-               if (MONO_TYPE_ISSTRUCT (gclass->generic_type)) {
-                       MonoClass *gklass = mono_class_from_mono_type (gclass->generic_type);
-
-                       if (gklass->enumtype)
-                               return mono_type_stack_size (gklass->enum_basetype, align);
+               if (gclass->container_class->valuetype) {
+                       if (gclass->container_class->enumtype)
+                               return mono_type_stack_size (gclass->container_class->enum_basetype, align);
                        else {
                                guint32 size = mono_class_value_size (gclass->klass, align);
 
@@ -2819,17 +2828,17 @@ mono_type_stack_size (MonoType *t, gint *align)
 gboolean
 mono_metadata_generic_class_is_valuetype (MonoGenericClass *gclass)
 {
-       return MONO_TYPE_ISSTRUCT (gclass->generic_type);
+       return gclass->container_class->valuetype;
 }
 
 static gboolean
-_mono_metadata_generic_class_equal (MonoGenericClass *g1, MonoGenericClass *g2, gboolean signature_only)
+_mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2, gboolean signature_only)
 {
        int i;
 
-       if (g1->inst->type_argc != g2->inst->type_argc)
+       if ((g1->inst->type_argc != g2->inst->type_argc) || (g1->is_dynamic != g2->is_dynamic))
                return FALSE;
-       if (!do_mono_metadata_type_equal (g1->generic_type, g2->generic_type, signature_only))
+       if (!mono_metadata_class_equal (g1->container_class, g2->container_class, signature_only))
                return FALSE;
        for (i = 0; i < g1->inst->type_argc; ++i) {
                if (!do_mono_metadata_type_equal (g1->inst->type_argv [i], g2->inst->type_argv [i], signature_only))
@@ -3379,7 +3388,7 @@ mono_metadata_implmap_from_method (MonoImage *meta, guint32 method_idx)
  * token.
  */
 MonoType *
-mono_type_create_from_typespec_full (MonoImage *image, MonoGenericContainer *generic_container, guint32 type_spec)
+mono_type_create_from_typespec_full (MonoImage *image, MonoGenericContext *generic_context, guint32 type_spec)
 {
        guint32 idx = mono_metadata_token_index (type_spec);
        MonoTableInfo *t;
@@ -3410,7 +3419,7 @@ mono_type_create_from_typespec_full (MonoImage *image, MonoGenericContainer *gen
                ptr++;
        }
 
-       do_mono_metadata_parse_type (type, image, generic_container, ptr, &ptr);
+       do_mono_metadata_parse_type (type, image, generic_context, ptr, &ptr);
 
        mono_loader_unlock ();
 
@@ -3777,12 +3786,13 @@ get_constraints (MonoImage *image, int owner, MonoGenericContext *context)
 }
 
 MonoGenericContainer *
-mono_metadata_load_generic_params (MonoImage *image, guint32 token)
+mono_metadata_load_generic_params (MonoImage *image, guint32 token, MonoGenericContainer *parent_container)
 {
        MonoTableInfo *tdef  = &image->tables [MONO_TABLE_GENERICPARAM];
        guint32 cols [MONO_GENERICPARAM_SIZE];
        guint32 i, owner = 0, last_num, n;
        MonoGenericContainer *container;
+       MonoGenericClass *gclass;
        MonoGenericParam *params;
 
        if (mono_metadata_token_table (token) == MONO_TABLE_TYPEDEF)
@@ -3802,7 +3812,7 @@ mono_metadata_load_generic_params (MonoImage *image, guint32 token)
                if (cols [MONO_GENERICPARAM_OWNER] == owner)
                        break;
        }
-       last_num = 0;
+       last_num = i;
        if (i >= tdef->rows)
                return NULL;
        params = NULL;
@@ -3824,12 +3834,15 @@ mono_metadata_load_generic_params (MonoImage *image, guint32 token)
 
        container->type_argc = n;
        container->type_params = params;
+       container->parent = parent_container;
+
+       if (mono_metadata_token_table (token) == MONO_TABLE_METHOD)
+               container->is_method = 1;
 
-       container->context = g_new0 (MonoGenericContext, 1);
-       container->context->container = container;
+       container->context.container = container;
 
        for (i = 0; i < n; i++)
-               params [i].constraints = get_constraints (image, i + 1, container->context);
+               params [i].constraints = get_constraints (image, last_num + i + 1, &container->context);
 
        return container;
 }