2003-10-15 Martin Baulig <martin@ximian.com>
[mono.git] / mono / metadata / metadata.c
index 05302ad51e8be2050cb086dba7316a5f1dc2b364..c5fb89d4984a7a3226da76a21afb49319ee54a5a 100644 (file)
@@ -35,7 +35,7 @@ static void do_mono_metadata_parse_type (MonoType *type, MonoImage *m, const cha
  * information might refer to different tables.
  */
 
-static MonoMetaTable AssemblySchema [] = {
+const static MonoMetaTable AssemblySchema [] = {
        { MONO_MT_UINT32,     "HashId" },
        { MONO_MT_UINT16,     "Major" },  
        { MONO_MT_UINT16,     "Minor" },
@@ -48,19 +48,19 @@ static MonoMetaTable AssemblySchema [] = {
        { MONO_MT_END, NULL }
 };
        
-static MonoMetaTable AssemblyOSSchema [] = {
+const static MonoMetaTable AssemblyOSSchema [] = {
        { MONO_MT_UINT32,     "OSPlatformID" },
        { MONO_MT_UINT32,     "OSMajor" },
        { MONO_MT_UINT32,     "OSMinor" },
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable AssemblyProcessorSchema [] = {
+const static MonoMetaTable AssemblyProcessorSchema [] = {
        { MONO_MT_UINT32,     "Processor" },
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable AssemblyRefSchema [] = {
+const static MonoMetaTable AssemblyRefSchema [] = {
        { MONO_MT_UINT16,     "Major" },
        { MONO_MT_UINT16,     "Minor" },
        { MONO_MT_UINT16,     "Build" },
@@ -73,7 +73,7 @@ static MonoMetaTable AssemblyRefSchema [] = {
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable AssemblyRefOSSchema [] = {
+const static MonoMetaTable AssemblyRefOSSchema [] = {
        { MONO_MT_UINT32,     "OSPlatformID" },
        { MONO_MT_UINT32,     "OSMajorVersion" },
        { MONO_MT_UINT32,     "OSMinorVersion" },
@@ -81,20 +81,20 @@ static MonoMetaTable AssemblyRefOSSchema [] = {
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable AssemblyRefProcessorSchema [] = {
+const static MonoMetaTable AssemblyRefProcessorSchema [] = {
        { MONO_MT_UINT32,     "Processor" },
        { MONO_MT_TABLE_IDX,  "AssemblyRef:AssemblyRef" },
        { MONO_MT_END, NULL }   
 };
 
-static MonoMetaTable ClassLayoutSchema [] = {
+const static MonoMetaTable ClassLayoutSchema [] = {
        { MONO_MT_UINT16,     "PackingSize" },
        { MONO_MT_UINT32,     "ClassSize" },
        { MONO_MT_TABLE_IDX,  "Parent:TypeDef" },
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable ConstantSchema [] = {
+const static MonoMetaTable ConstantSchema [] = {
        { MONO_MT_UINT8,      "Type" },
        { MONO_MT_UINT8,      "PaddingZero" },
        { MONO_MT_CONST_IDX,  "Parent" },
@@ -102,34 +102,34 @@ static MonoMetaTable ConstantSchema [] = {
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable CustomAttributeSchema [] = {
+const static MonoMetaTable CustomAttributeSchema [] = {
        { MONO_MT_HASCAT_IDX, "Parent" },
        { MONO_MT_CAT_IDX,    "Type" },
        { MONO_MT_BLOB_IDX,   "Value" },
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable DeclSecuritySchema [] = {
+const static MonoMetaTable DeclSecuritySchema [] = {
        { MONO_MT_UINT16,     "Action" },
        { MONO_MT_HASDEC_IDX, "Parent" },
        { MONO_MT_BLOB_IDX,   "PermissionSet" },
        { MONO_MT_END, NULL }   
 };
 
-static MonoMetaTable EventMapSchema [] = {
+const static MonoMetaTable EventMapSchema [] = {
        { MONO_MT_TABLE_IDX,  "Parent:TypeDef" },
        { MONO_MT_TABLE_IDX,  "EventList:Event" },
        { MONO_MT_END, NULL }   
 };
 
-static MonoMetaTable EventSchema [] = {
+const static MonoMetaTable EventSchema [] = {
        { MONO_MT_UINT16,     "EventFlags#EventAttribute" },
        { MONO_MT_STRING_IDX, "Name" },
        { MONO_MT_TABLE_IDX,  "EventType" }, /* TypeDef or TypeRef */
        { MONO_MT_END, NULL }   
 };
 
-static MonoMetaTable ExportedTypeSchema [] = {
+const static MonoMetaTable ExportedTypeSchema [] = {
        { MONO_MT_UINT32,     "Flags" },
        { MONO_MT_TABLE_IDX,  "TypeDefId" },
        { MONO_MT_STRING_IDX, "TypeName" },
@@ -138,37 +138,37 @@ static MonoMetaTable ExportedTypeSchema [] = {
        { MONO_MT_END, NULL }   
 };
 
-static MonoMetaTable FieldSchema [] = {
+const static MonoMetaTable FieldSchema [] = {
        { MONO_MT_UINT16,     "Flags" },
        { MONO_MT_STRING_IDX, "Name" },
        { MONO_MT_BLOB_IDX,   "Signature" },
        { MONO_MT_END, NULL }   
 };
-static MonoMetaTable FieldLayoutSchema [] = {
+const static MonoMetaTable FieldLayoutSchema [] = {
        { MONO_MT_UINT32,     "Offset" },
        { MONO_MT_TABLE_IDX,  "Field:Field" },
        { MONO_MT_END, NULL }   
 };
 
-static MonoMetaTable FieldMarshalSchema [] = {
+const static MonoMetaTable FieldMarshalSchema [] = {
        { MONO_MT_HFM_IDX,    "Parent" },
        { MONO_MT_BLOB_IDX,   "NativeType" },
        { MONO_MT_END, NULL }   
 };
-static MonoMetaTable FieldRVASchema [] = {
+const static MonoMetaTable FieldRVASchema [] = {
        { MONO_MT_UINT32,     "RVA" },
        { MONO_MT_TABLE_IDX,  "Field:Field" },
        { MONO_MT_END, NULL }   
 };
 
-static MonoMetaTable FileSchema [] = {
+const static MonoMetaTable FileSchema [] = {
        { MONO_MT_UINT32,     "Flags" },
        { MONO_MT_STRING_IDX, "Name" },
        { MONO_MT_BLOB_IDX,   "Value" }, 
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable ImplMapSchema [] = {
+const static MonoMetaTable ImplMapSchema [] = {
        { MONO_MT_UINT16,     "MappingFlag" },
        { MONO_MT_MF_IDX,     "MemberForwarded" },
        { MONO_MT_STRING_IDX, "ImportName" },
@@ -176,13 +176,13 @@ static MonoMetaTable ImplMapSchema [] = {
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable InterfaceImplSchema [] = {
+const static MonoMetaTable InterfaceImplSchema [] = {
        { MONO_MT_TABLE_IDX,  "Class:TypeDef" }, 
        { MONO_MT_TDOR_IDX,  "Interface=TypeDefOrRef" },
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable ManifestResourceSchema [] = {
+const static MonoMetaTable ManifestResourceSchema [] = {
        { MONO_MT_UINT32,     "Offset" },
        { MONO_MT_UINT32,     "Flags" },
        { MONO_MT_STRING_IDX, "Name" },
@@ -190,14 +190,14 @@ static MonoMetaTable ManifestResourceSchema [] = {
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable MemberRefSchema [] = {
+const static MonoMetaTable MemberRefSchema [] = {
        { MONO_MT_MRP_IDX,    "Class" },
        { MONO_MT_STRING_IDX, "Name" },
        { MONO_MT_BLOB_IDX,   "Signature" },
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable MethodSchema [] = {
+const static MonoMetaTable MethodSchema [] = {
        { MONO_MT_UINT32,     "RVA" },
        { MONO_MT_UINT16,     "ImplFlags#MethodImplAttributes" },
        { MONO_MT_UINT16,     "Flags#MethodAttribute" },
@@ -207,21 +207,21 @@ static MonoMetaTable MethodSchema [] = {
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable MethodImplSchema [] = {
+const static MonoMetaTable MethodImplSchema [] = {
        { MONO_MT_TABLE_IDX,  "Class:TypeDef" },
        { MONO_MT_MDOR_IDX,   "MethodBody" },
        { MONO_MT_MDOR_IDX,   "MethodDeclaration" },
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable MethodSemanticsSchema [] = {
+const static MonoMetaTable MethodSemanticsSchema [] = {
        { MONO_MT_UINT16,     "MethodSemantic" },
        { MONO_MT_TABLE_IDX,  "Method:Method" },
        { MONO_MT_HS_IDX,     "Association" },
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable ModuleSchema [] = {
+const static MonoMetaTable ModuleSchema [] = {
        { MONO_MT_UINT16,     "Generation" },
        { MONO_MT_STRING_IDX, "Name" },
        { MONO_MT_GUID_IDX,   "MVID" },
@@ -230,43 +230,43 @@ static MonoMetaTable ModuleSchema [] = {
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable ModuleRefSchema [] = {
+const static MonoMetaTable ModuleRefSchema [] = {
        { MONO_MT_STRING_IDX, "Name" },
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable NestedClassSchema [] = {
+const static MonoMetaTable NestedClassSchema [] = {
        { MONO_MT_TABLE_IDX,  "NestedClass:TypeDef" },
        { MONO_MT_TABLE_IDX,  "EnclosingClass:TypeDef" },
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable ParamSchema [] = {
+const static MonoMetaTable ParamSchema [] = {
        { MONO_MT_UINT16,     "Flags" },
        { MONO_MT_UINT16,     "Sequence" },
        { MONO_MT_STRING_IDX, "Name" },
        { MONO_MT_END, NULL }   
 };
 
-static MonoMetaTable PropertySchema [] = {
+const static MonoMetaTable PropertySchema [] = {
        { MONO_MT_UINT16,     "Flags" },
        { MONO_MT_STRING_IDX, "Name" },
        { MONO_MT_BLOB_IDX,   "Type" },
        { MONO_MT_END, NULL }   
 };
 
-static MonoMetaTable PropertyMapSchema [] = {
+const static MonoMetaTable PropertyMapSchema [] = {
        { MONO_MT_TABLE_IDX,  "Parent:TypeDef" },
        { MONO_MT_TABLE_IDX,  "PropertyList:Property" },
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable StandaloneSigSchema [] = {
+const static MonoMetaTable StandaloneSigSchema [] = {
        { MONO_MT_BLOB_IDX,   "Signature" },
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable TypeDefSchema [] = {
+const static MonoMetaTable TypeDefSchema [] = {
        { MONO_MT_UINT32,     "Flags" },
        { MONO_MT_STRING_IDX, "Name" },
        { MONO_MT_STRING_IDX, "Namespace" },
@@ -276,20 +276,45 @@ static MonoMetaTable TypeDefSchema [] = {
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable TypeRefSchema [] = {
+const static MonoMetaTable TypeRefSchema [] = {
        { MONO_MT_RS_IDX,     "ResolutionScope=ResolutionScope" },
        { MONO_MT_STRING_IDX, "Name" },
        { MONO_MT_STRING_IDX, "Namespace" },
        { MONO_MT_END, NULL }
 };
 
-static MonoMetaTable TypeSpecSchema [] = {
+const static MonoMetaTable TypeSpecSchema [] = {
        { MONO_MT_BLOB_IDX,   "Signature" },
        { MONO_MT_END, NULL }
 };
 
-static struct {
-       MonoMetaTable *table;
+const static MonoMetaTable GenericParamSchema [] = {
+       { MONO_MT_UINT16,     "Number" },
+       { MONO_MT_UINT16,     "Flags" },
+       { MONO_MT_TABLE_IDX,  "Owner" }, /* TypeDef or MethodDef */
+       { MONO_MT_STRING_IDX, "Name" },
+
+       /* soon to be removed */
+       { MONO_MT_TABLE_IDX,  "Kind" }, 
+       { MONO_MT_TABLE_IDX,  "DeprecatedConstraint" },
+       
+       { MONO_MT_END, NULL }
+};
+
+const static MonoMetaTable MethodSpecSchema [] = {
+       { MONO_MT_MDOR_IDX,   "Method" },
+       { MONO_MT_BLOB_IDX,   "Signature" },
+       { MONO_MT_END, NULL }
+};
+
+const static MonoMetaTable GenericParamConstraintSchema [] = {
+       { MONO_MT_TABLE_IDX,  "GenericParam" },
+       { MONO_MT_TDOR_IDX,   "Constraint" },
+       { MONO_MT_END, NULL }
+};
+
+const static struct {
+       const MonoMetaTable *table;
        const char    *name;
 } tables [] = {
        /*  0 */ { ModuleSchema,               "Module" },
@@ -334,8 +359,9 @@ static struct {
        /* 27 */ { ExportedTypeSchema,         "ExportedType" },
        /* 28 */ { ManifestResourceSchema,     "ManifestResource" },
        /* 29 */ { NestedClassSchema,          "NestedClass" },
-       /* 2A */ { NULL,                       NULL },
-       /* 2B */ { NULL,                       NULL },
+       /* 2A */ { GenericParamSchema,         "GenericParam" },
+       /* 2B */ { MethodSpecSchema,           "MethodSpec" },
+       /* 2C */ { GenericParamConstraintSchema, "GenericParamConstraint" },
 };
 
 /**
@@ -347,7 +373,7 @@ static struct {
 const char *
 mono_meta_table_name (int table)
 {
-       if ((table < 0) || (table > 0x29))
+       if ((table < 0) || (table > 0x2c))
                return "";
        
        return tables [table].name;
@@ -386,7 +412,7 @@ mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bit
        int size = 0, field_size;
        int i, n, code;
        int shift = 0;
-       MonoMetaTable *table = tables [tableindex].table;
+       const MonoMetaTable *table = tables [tableindex].table;
 
        for (i = 0; (code = table [i].code) != MONO_MT_END; i++){
                switch (code){
@@ -469,8 +495,22 @@ mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bit
                        case MONO_TABLE_TYPEDEF:
                                g_assert (i == 4 || i == 5);
                                field_size = i == 4 ? idx_size (MONO_TABLE_FIELD):
-                                       idx_size(MONO_TABLE_METHOD); 
+                                       idx_size(MONO_TABLE_METHOD);
+                       case MONO_TABLE_GENERICPARAM:
+                               g_assert (i == 2 || i == 4 || i == 5);
+                               if (i == 2)
+                                       field_size = MAX (idx_size (MONO_TABLE_METHOD), idx_size (MONO_TABLE_TYPEDEF));
+                               else if (i == 4)
+                                       field_size = idx_size (MONO_TABLE_TYPEDEF);
+                               else if (i == 5)
+                                       field_size = idx_size (MONO_TABLE_TYPEDEF);
                                break;
+
+                       case MONO_TABLE_GENERICPARAMCONSTRAINT:
+                               g_assert (i == 0);
+                               field_size = idx_size (MONO_TABLE_GENERICPARAM);
+                               break;
+                               
                        default:
                                g_assert_not_reached ();
                        }
@@ -734,7 +774,7 @@ mono_metadata_locate_token (MonoImage *meta, guint32 token)
  *
  * Returns the MonoMetaTable structure for table @table
  */
-MonoMetaTable *
+const MonoMetaTable *
 mono_metadata_get_table (MonoMetaTableEnum table)
 {
        int x = (int) table;
@@ -805,7 +845,11 @@ mono_metadata_guid_heap (MonoImage *meta, guint32 index)
 static const char *
 dword_align (const char *ptr)
 {
+#if SIZEOF_VOID_P == 8
+       return (const char *) (((guint64) (ptr + 3)) & ~3);
+#else
        return (const char *) (((guint32) (ptr + 3)) & ~3);
+#endif
 }
 
 /**
@@ -1012,8 +1056,10 @@ mono_metadata_parse_array (MonoImage *m, const char *ptr, const char **rptr)
 {
        int i;
        MonoArrayType *array = g_new0 (MonoArrayType, 1);
+       MonoType *etype;
        
-       array->type = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, ptr, &ptr);
+       etype = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, ptr, &ptr);
+       array->eklass = mono_class_from_mono_type (etype);
        array->rank = mono_metadata_decode_value (ptr, &ptr);
 
        array->numsizes = mono_metadata_decode_value (ptr, &ptr);
@@ -1042,7 +1088,6 @@ mono_metadata_parse_array (MonoImage *m, const char *ptr, const char **rptr)
 void
 mono_metadata_free_array (MonoArrayType *array)
 {
-       mono_metadata_free_type (array->type);
        g_free (array->sizes);
        g_free (array->lobounds);
        g_free (array);
@@ -1092,8 +1137,6 @@ builtin_types[] = {
        {{NULL}, 0,     MONO_TYPE_I,       0,     1,     0},
        {{NULL}, 0,     MONO_TYPE_U,       0,     0,     0},
        {{NULL}, 0,     MONO_TYPE_U,       0,     1,     0},
-       {{NULL}, 0,     MONO_TYPE_OBJECT,  0,     0,     0},
-       {{NULL}, 0,     MONO_TYPE_OBJECT,  0,     1,     0}
 };
 
 #define NBUILTIN_TYPES() (sizeof (builtin_types) / sizeof (builtin_types [0]))
@@ -1122,6 +1165,22 @@ mono_type_equal (gconstpointer ka, gconstpointer kb)
        return 1;
 }
 
+/**
+ * mono_metadata_init:
+ *
+ *  Initialize the global variables of this module.
+ */
+void
+mono_metadata_init (void)
+{
+       int i;
+
+       type_cache = g_hash_table_new (mono_type_hash, mono_type_equal);
+
+       for (i = 0; i < NBUILTIN_TYPES (); ++i)
+               g_hash_table_insert (type_cache, &builtin_types [i], &builtin_types [i]);
+}
+
 /*
  * mono_metadata_parse_type:
  * @m: metadata context
@@ -1143,14 +1202,6 @@ mono_metadata_parse_type (MonoImage *m, MonoParseTypeMode mode, short opt_attrs,
 {
        MonoType *type, *cached;
 
-       if (!type_cache) {
-               int i;
-               type_cache = g_hash_table_new (mono_type_hash, mono_type_equal);
-
-               for (i = 0; i < NBUILTIN_TYPES (); ++i)
-                       g_hash_table_insert (type_cache, &builtin_types [i], &builtin_types [i]);
-       }
-
        switch (mode) {
        case MONO_PARSE_MOD_TYPE:
        case MONO_PARSE_PARAM:
@@ -1163,7 +1214,7 @@ mono_metadata_parse_type (MonoImage *m, MonoParseTypeMode mode, short opt_attrs,
                while (mono_metadata_parse_custom_mod (m, NULL, tmp_ptr, &tmp_ptr))
                        count++;
                if (count) {
-                       type = g_malloc0 (sizeof (MonoType) + (count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod));
+                       type = g_malloc0 (sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod));
                        type->num_mods = count;
                        if (count > 64)
                                g_warning ("got more than 64 modifiers in type");
@@ -1210,6 +1261,8 @@ mono_metadata_parse_type (MonoImage *m, MonoParseTypeMode mode, short opt_attrs,
        }
        if (rptr)
                *rptr = ptr;
+
+       /* No need to use locking since nobody is modifying the hash table */
        if (mode != MONO_PARSE_PARAM && !type->num_mods && (cached = g_hash_table_lookup (type_cache, type))) {
                mono_metadata_free_type (type);
                return cached;
@@ -1254,7 +1307,7 @@ mono_metadata_signature_alloc (MonoImage *m, guint32 nparams)
        MonoMethodSignature *sig;
 
        /* later we want to allocate signatures with mempools */
-       sig = g_malloc0 (sizeof (MonoMethodSignature) + (nparams - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
+       sig = g_malloc0 (sizeof (MonoMethodSignature) + ((gint32)nparams - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
        sig->param_count = nparams;
 
        return sig;
@@ -1277,13 +1330,18 @@ mono_metadata_parse_method_signature (MonoImage *m, int def, const char *ptr, co
        MonoMethodSignature *method;
        int i, ret_attrs = 0, *pattrs = NULL;
        guint32 hasthis = 0, explicit_this = 0, call_convention, param_count;
+       guint32 gen_param_count = 0;
 
+       if (*ptr & 0x10)
+               gen_param_count = 1;
        if (*ptr & 0x20)
                hasthis = 1;
        if (*ptr & 0x40)
                explicit_this = 1;
        call_convention = *ptr & 0x0F;
        ptr++;
+       if (gen_param_count)
+               gen_param_count = mono_metadata_decode_value (ptr, &ptr);
        param_count = mono_metadata_decode_value (ptr, &ptr);
        pattrs = g_new0 (int, param_count);
 
@@ -1296,7 +1354,7 @@ mono_metadata_parse_method_signature (MonoImage *m, int def, const char *ptr, co
                if (def < methodt->rows)
                        lastp = mono_metadata_decode_row_col (methodt, def, MONO_METHOD_PARAMLIST);
                else
-                       lastp = paramt->rows;
+                       lastp = paramt->rows + 1;
                for (i = param_index; i < lastp; ++i) {
                        mono_metadata_decode_row (paramt, i - 1, cols, MONO_PARAM_SIZE);
                        if (!cols [MONO_PARAM_SEQUENCE])
@@ -1309,7 +1367,8 @@ mono_metadata_parse_method_signature (MonoImage *m, int def, const char *ptr, co
        method->hasthis = hasthis;
        method->explicit_this = explicit_this;
        method->call_convention = call_convention;
-       method->ret = mono_metadata_parse_type (m, MONO_PARSE_RET, ret_attrs, ptr, &ptr);
+       if (call_convention != 0xa)
+               method->ret = mono_metadata_parse_type (m, MONO_PARSE_RET, ret_attrs, ptr, &ptr);
 
        if (method->param_count) {
                method->sentinelpos = -1;
@@ -1351,6 +1410,38 @@ mono_metadata_free_method_signature (MonoMethodSignature *sig)
        g_free (sig);
 }
 
+static MonoGenericInst *
+mono_metadata_parse_generic_inst (MonoImage *m, const char *ptr, const char **rptr)
+{
+       MonoGenericInst *generic_inst = g_new0 (MonoGenericInst, 1);
+       int i, count;
+       
+       generic_inst->generic_type = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, ptr, &ptr);
+       generic_inst->type_argc = count = mono_metadata_decode_value (ptr, &ptr);
+       generic_inst->type_argv = g_new0 (MonoType*, count);
+
+       for (i = 0; i < generic_inst->type_argc; i++)
+               generic_inst->type_argv [i] = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, ptr, &ptr);
+       
+       if (rptr)
+               *rptr = ptr;
+
+       return generic_inst;
+}
+
+static MonoGenericParam *
+mono_metadata_parse_generic_param (MonoImage *m, const char *ptr, const char **rptr)
+{
+       MonoGenericParam *generic_param = g_new0 (MonoGenericParam, 1);
+       
+       generic_param->num = mono_metadata_decode_value (ptr, &ptr);
+
+       if (rptr)
+               *rptr = ptr;
+
+       return generic_param;
+}
+
 /* 
  * do_mono_metadata_parse_type:
  * @type: MonoType to be filled in with the return value
@@ -1397,7 +1488,11 @@ do_mono_metadata_parse_type (MonoType *type, MonoImage *m, const char *ptr, cons
                type->data.klass = mono_class_get (m, token);
                break;
        }
-       case MONO_TYPE_SZARRAY:
+       case MONO_TYPE_SZARRAY: {
+               MonoType *etype = mono_metadata_parse_type (m, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
+               type->data.klass = mono_class_from_mono_type (etype);
+               break;
+       }
        case MONO_TYPE_PTR:
                type->data.type = mono_metadata_parse_type (m, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
                break;
@@ -1407,8 +1502,18 @@ do_mono_metadata_parse_type (MonoType *type, MonoImage *m, const char *ptr, cons
        case MONO_TYPE_ARRAY:
                type->data.array = mono_metadata_parse_array (m, ptr, &ptr);
                break;
+
+       case MONO_TYPE_MVAR:
+       case MONO_TYPE_VAR:
+               type->data.generic_param = mono_metadata_parse_generic_param (m, ptr, &ptr);
+               break;
+
+       case MONO_TYPE_GENERICINST:
+               type->data.generic_inst = mono_metadata_parse_generic_inst (m, ptr, &ptr);
+               break;
+               
        default:
-               g_error ("type 0x%02x not handled in mono_metadata_parse_type", type->type);
+               g_error ("type 0x%02x not handled in do_mono_metadata_parse_type", type->type);
        }
        
        if (rptr)
@@ -1427,7 +1532,6 @@ mono_metadata_free_type (MonoType *type)
        if (type >= builtin_types && type < builtin_types + NBUILTIN_TYPES ())
                return;
        switch (type->type){
-       case MONO_TYPE_SZARRAY:
        case MONO_TYPE_PTR:
                mono_metadata_free_type (type->data.type);
                break;
@@ -1976,37 +2080,33 @@ mono_metadata_nested_in_typedef (MonoImage *meta, guint32 index)
  * @index: typedef token
  * 
  * Returns: the 1-based index into the TypeDef table of the first type
- * that is nested inside the type described by @index.
- * Retruns 0 if @index doesn't have nested types.
+ * that is nested inside the type described by @index. The search starts at
+ * @start_index.
+ * Returns 0 if no such type is found.
  */
 guint32
-mono_metadata_nesting_typedef (MonoImage *meta, guint32 index)
+mono_metadata_nesting_typedef (MonoImage *meta, guint32 index, guint32 start_index)
 {
        MonoTableInfo *tdef = &meta->tables [MONO_TABLE_NESTEDCLASS];
-       locator_t loc;
        guint32 start;
+       guint32 class_index = mono_metadata_token_index (index);
        
        if (!tdef->base)
                return 0;
 
-       loc.idx = mono_metadata_token_index (index);
-       loc.col_idx = MONO_NESTED_CLASS_ENCLOSING;
-       loc.t = tdef;
-
-       if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
-               return 0;
-
-       start = loc.result;
+       start = start_index;
 
-       while (start > 0) {
-               if (loc.idx == mono_metadata_decode_row_col (tdef, start - 1, MONO_NESTED_CLASS_ENCLOSING))
-                       start--;
-               else
+       while (start <= tdef->rows) {
+               if (class_index == mono_metadata_decode_row_col (tdef, start - 1, MONO_NESTED_CLASS_ENCLOSING))
                        break;
+               else
+                       start++;
        }
 
-       /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
-       return start + 1;
+       if (start > tdef->rows)
+               return 0;
+       else
+               return start;
 }
 
 /*
@@ -2045,8 +2145,58 @@ mono_metadata_packing_from_typedef (MonoImage *meta, guint32 index, guint32 *pac
        return loc.result + 1;
 }
 
+/*
+ * mono_metadata_custom_attrs_from_index:
+ * @meta: metadata context
+ * @index: token representing the parent
+ * 
+ * Returns: the 1-based index into the CustomAttribute table of the first 
+ * attribute which belongs to the metadata object described by @index.
+ * Returns 0 if no such attribute is found.
+ */
+guint32
+mono_metadata_custom_attrs_from_index (MonoImage *meta, guint32 index)
+{
+       MonoTableInfo *tdef = &meta->tables [MONO_TABLE_CUSTOMATTRIBUTE];
+       locator_t loc;
+       
+       if (!tdef->base)
+               return 0;
+
+       loc.idx = index;
+       loc.col_idx = MONO_CUSTOM_ATTR_PARENT;
+       loc.t = tdef;
+
+       if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
+               return 0;
+
+       /* Find the first entry by searching backwards */
+       while ((loc.result > 0) && (mono_metadata_decode_row_col (tdef, loc.result - 1, MONO_CUSTOM_ATTR_PARENT) == index))
+               loc.result --;
+
+       /* loc_result is 0..1, needs to be mapped to table index (that is +1) */
+       return loc.result + 1;
+}
+
+#ifdef DEBUG
+static void
+mono_backtrace (int limit)
+{
+       void *array[limit];
+       char **names;
+       int i;
+       backtrace (array, limit);
+       names = backtrace_symbols (array, limit);
+       for (i =0; i < limit; ++i) {
+               g_print ("\t%s\n", names [i]);
+       }
+       g_free (names);
+}
+#endif
+
 #ifndef __GNUC__
-#define __alignof__(a) sizeof(a)
+/*#define __alignof__(a) sizeof(a)*/
+#define __alignof__(type) G_STRUCT_OFFSET(struct { char c; type x; }, x)
 #endif
 
 /*
@@ -2119,11 +2269,21 @@ mono_type_size (MonoType *t, gint *align)
        case MONO_TYPE_PTR:
        case MONO_TYPE_FNPTR:
        case MONO_TYPE_ARRAY:
-       case MONO_TYPE_TYPEDBYREF: /* we may want to use a struct {MonoType* type, void *data } instead ...*/
+               *align = __alignof__(gpointer);
+               return sizeof (gpointer);
+       case MONO_TYPE_TYPEDBYREF:
+               *align = __alignof__(gpointer);
+               return sizeof (gpointer) * 2;
+       case MONO_TYPE_GENERICINST: {
+               MonoClass *iclass = mono_class_from_mono_type (t);
+               return mono_type_size (&iclass->byval_arg, align);
+       }
+       case MONO_TYPE_VAR:
+       case MONO_TYPE_MVAR:
                *align = __alignof__(gpointer);
                return sizeof (gpointer);
        default:
-               g_error ("type 0x%02x unknown", t->type);
+               g_error ("mono_type_size: type 0x%02x unknown", t->type);
        }
        return 0;
 }
@@ -2168,9 +2328,11 @@ mono_type_stack_size (MonoType *t, gint *align)
        case MONO_TYPE_PTR:
        case MONO_TYPE_FNPTR:
        case MONO_TYPE_ARRAY:
-       case MONO_TYPE_TYPEDBYREF:
                *align = __alignof__(gpointer);
                return sizeof (gpointer);
+       case MONO_TYPE_TYPEDBYREF:
+               *align = __alignof__(gpointer);
+               return sizeof (gpointer) * 2;
        case MONO_TYPE_R4:
                *align = __alignof__(float);
                return sizeof (float);          
@@ -2192,79 +2354,16 @@ mono_type_stack_size (MonoType *t, gint *align)
                        *align = *align + __alignof__(gpointer) - 1;
                        *align &= ~(__alignof__(gpointer) - 1);
 
-                       return size;
-               }
-       }
-       default:
-               g_error ("type 0x%02x unknown", t->type);
-       }
-       return 0;
-}
-
-/*
- * mono_type_native_stack_size:
- * @t: the type to return the size it uses on the stack
- *
- * Returns: the number of bytes required to hold an instance of this
- * type on the native stack
- */
-int
-mono_type_native_stack_size (MonoType *t, gint *align)
-{
-       int tmp;
-
-       g_assert (t != NULL);
-
-       if (!align)
-               align = &tmp;
-
-       if (t->byref) {
-               *align = 4;
-               return 4;
-       }
-
-       switch (t->type){
-       case MONO_TYPE_BOOLEAN:
-       case MONO_TYPE_CHAR:
-       case MONO_TYPE_I1:
-       case MONO_TYPE_U1:
-       case MONO_TYPE_I2:
-       case MONO_TYPE_U2:
-       case MONO_TYPE_I4:
-       case MONO_TYPE_U4:
-       case MONO_TYPE_I:
-       case MONO_TYPE_U:
-       case MONO_TYPE_STRING:
-       case MONO_TYPE_OBJECT:
-       case MONO_TYPE_CLASS:
-       case MONO_TYPE_SZARRAY:
-       case MONO_TYPE_PTR:
-       case MONO_TYPE_FNPTR:
-       case MONO_TYPE_ARRAY:
-       case MONO_TYPE_TYPEDBYREF:
-               *align = 4;
-               return 4;
-       case MONO_TYPE_R4:
-               *align = 4;
-               return 4;
-       case MONO_TYPE_I8:
-       case MONO_TYPE_U8:
-       case MONO_TYPE_R8:
-               *align = 4;
-               return 8;
-       case MONO_TYPE_VALUETYPE: {
-               guint32 size;
+                       size += sizeof (gpointer) - 1;
+                       size &= ~(sizeof (gpointer) - 1);
 
-               if (t->data.klass->enumtype)
-                       return mono_type_native_stack_size (t->data.klass->enum_basetype, align);
-               else {
-                       size = mono_class_native_size (t->data.klass, align);
-                       *align = *align + 3;
-                       *align &= ~3;
-                       
                        return size;
                }
        }
+       case MONO_TYPE_GENERICINST: {
+               MonoClass *iclass = mono_class_from_mono_type (t);
+               return mono_type_stack_size (&iclass->byval_arg, align);
+       }
        default:
                g_error ("type 0x%02x unknown", t->type);
        }
@@ -2286,11 +2385,15 @@ mono_metadata_type_hash (MonoType *t1)
        switch (t1->type) {
        case MONO_TYPE_VALUETYPE:
        case MONO_TYPE_CLASS:
+       case MONO_TYPE_SZARRAY:
                /* check if the distribution is good enough */
-               return hash << 7 | g_str_hash (t1->data.klass->name);
+               return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
        case MONO_TYPE_PTR:
-       case MONO_TYPE_SZARRAY:
-               return hash << 7 | mono_metadata_type_hash (t1->data.type);
+               return ((hash << 5) - hash) ^ mono_metadata_type_hash (t1->data.type);
+       case MONO_TYPE_ARRAY:
+               return ((hash << 5) - hash) ^ mono_metadata_type_hash (&t1->data.array->eklass->byval_arg);
+       case MONO_TYPE_GENERICINST:
+               return ((hash << 5) - hash) ^ mono_metadata_type_hash (t1->data.generic_inst->generic_type);
        }
        return hash;
 }
@@ -2332,14 +2435,29 @@ mono_metadata_type_equal (MonoType *t1, MonoType *t2)
                return TRUE;
        case MONO_TYPE_VALUETYPE:
        case MONO_TYPE_CLASS:
+       case MONO_TYPE_SZARRAY:
                return t1->data.klass == t2->data.klass;
        case MONO_TYPE_PTR:
-       case MONO_TYPE_SZARRAY:
                return mono_metadata_type_equal (t1->data.type, t2->data.type);
        case MONO_TYPE_ARRAY:
                if (t1->data.array->rank != t2->data.array->rank)
                        return FALSE;
-               return mono_metadata_type_equal (t1->data.array->type, t2->data.array->type);
+               return t1->data.array->eklass == t2->data.array->eklass;
+       case MONO_TYPE_GENERICINST: {
+               int i;
+               if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
+                       return FALSE;
+               if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
+                       return FALSE;
+               for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
+                       if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
+                               return FALSE;
+               }
+               return TRUE;
+       }
+       case MONO_TYPE_VAR:
+       case MONO_TYPE_MVAR:
+               return t1->data.generic_param == t2->data.generic_param;
        default:
                g_error ("implement type compare for %0x!", t1->type);
                return FALSE;
@@ -2766,21 +2884,37 @@ mono_metadata_parse_marshal_spec (MonoImage *image, const char *ptr)
 
        if (res->native == MONO_NATIVE_LPARRAY) {
                if (ptr - start <= len)
-                       res->elem_type = *ptr++;
+                       res->data.array_data.elem_type = *ptr++;
                if (ptr - start <= len)
-                       res->param_num = mono_metadata_decode_value (ptr, &ptr);
+                       res->data.array_data.param_num = mono_metadata_decode_value (ptr, &ptr);
                if (ptr - start <= len)
-                       res->num_elem = mono_metadata_decode_value (ptr, &ptr);
+                       res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
        } 
 
        if (res->native == MONO_NATIVE_BYVALTSTR) {
                if (ptr - start <= len)
-                       res->num_elem = mono_metadata_decode_value (ptr, &ptr);
+                       res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
        }
 
        if (res->native == MONO_NATIVE_BYVALARRAY) {
                if (ptr - start <= len)
-                       res->num_elem = mono_metadata_decode_value (ptr, &ptr);
+                       res->data.array_data.num_elem = mono_metadata_decode_value (ptr, &ptr);
+       }
+       
+       if (res->native == MONO_NATIVE_CUSTOM) {
+               /* skip unused type guid */
+               len = mono_metadata_decode_value (ptr, &ptr);
+               ptr += len;
+               /* skip unused native type name */
+               len = mono_metadata_decode_value (ptr, &ptr);
+               ptr += len;
+               /* read custom marshaler type name */
+               len = mono_metadata_decode_value (ptr, &ptr);
+               res->data.custom_data.custom_name = g_strndup (ptr, len);               
+               ptr += len;
+               /* read cookie string */
+               len = mono_metadata_decode_value (ptr, &ptr);
+               res->data.custom_data.cookie = g_strndup (ptr, len);
        }
 
        return res;
@@ -2812,8 +2946,9 @@ handle_enum:
                        case MONO_NATIVE_BOOLEAN:
                                *conv = MONO_MARSHAL_CONV_BOOL_I4;
                                return MONO_NATIVE_BOOLEAN;
+                       case MONO_NATIVE_I1:
                        case MONO_NATIVE_U1:
-                               return MONO_NATIVE_U1;
+                               return mspec->native;
                        default:
                                g_error ("cant marshal bool to native type %02x", mspec->native);
                        }
@@ -2913,7 +3048,9 @@ handle_enum:
                                g_error ("cant marshal object as native type %02x", mspec->native);
                        }
                }
-               if (type->data.klass->parent == mono_defaults.multicastdelegate_class) {
+               if (t == MONO_TYPE_CLASS && (type->data.klass == mono_defaults.multicastdelegate_class ||
+                                            type->data.klass == mono_defaults.delegate_class || 
+                                            type->data.klass->parent == mono_defaults.multicastdelegate_class)) {
                        *conv = MONO_MARSHAL_CONV_DEL_FTN;
                        return MONO_NATIVE_FUNC;
                }
@@ -2928,86 +3065,6 @@ handle_enum:
        return MONO_NATIVE_MAX;
 }
 
-gint32
-mono_marshal_type_size (MonoType *type, MonoMarshalSpec *mspec, gint32 *align, 
-                       gboolean as_field, gboolean unicode)
-{
-       MonoMarshalNative native_type = mono_type_to_unmanaged (type, mspec, as_field, unicode, NULL);
-       MonoClass *klass;
-
-       switch (native_type) {
-       case MONO_NATIVE_BOOLEAN:
-               *align = 4;
-               return 4;
-       case MONO_NATIVE_I1:
-       case MONO_NATIVE_U1:
-               *align = 1;
-               return 1;
-       case MONO_NATIVE_I2:
-       case MONO_NATIVE_U2:
-               *align = 2;
-               return 2;
-       case MONO_NATIVE_I4:
-       case MONO_NATIVE_U4:
-       case MONO_NATIVE_ERROR:
-               *align = 4;
-               return 4;
-       case MONO_NATIVE_I8:
-       case MONO_NATIVE_U8:
-               *align = 4;
-               return 8;
-       case MONO_NATIVE_R4:
-               *align = 4;
-               return 4;
-       case MONO_NATIVE_R8:
-               *align = 4;
-               return 8;
-       case MONO_NATIVE_INT:
-       case MONO_NATIVE_UINT:
-       case MONO_NATIVE_LPSTR:
-       case MONO_NATIVE_LPWSTR:
-       case MONO_NATIVE_LPTSTR:
-       case MONO_NATIVE_BSTR:
-       case MONO_NATIVE_ANSIBSTR:
-       case MONO_NATIVE_TBSTR:
-       case MONO_NATIVE_LPARRAY:
-       case MONO_NATIVE_SAFEARRAY:
-       case MONO_NATIVE_IUNKNOWN:
-       case MONO_NATIVE_IDISPATCH:
-       case MONO_NATIVE_INTERFACE:
-       case MONO_NATIVE_ASANY:
-       case MONO_NATIVE_VARIANTBOOL:
-       case MONO_NATIVE_FUNC:
-       case MONO_NATIVE_LPSTRUCT:
-               *align =  4;
-               return sizeof (gpointer);
-       case MONO_NATIVE_STRUCT: 
-               klass = mono_class_from_mono_type (type);
-               return mono_class_native_size (klass, align);
-       case MONO_NATIVE_BYVALTSTR: {
-               int esize = unicode ? 2: 1;
-               g_assert (mspec);
-               *align = esize;
-               return mspec->num_elem * esize;
-       }
-       case MONO_NATIVE_BYVALARRAY: {
-               int esize;
-               klass = mono_class_from_mono_type (type);
-               esize = mono_class_native_size (klass->element_class, align);
-               g_assert (mspec);
-               return mspec->num_elem * esize;
-       }
-       case MONO_NATIVE_CURRENCY:
-       case MONO_NATIVE_VBBYREFSTR:
-       case MONO_NATIVE_CUSTOM:
-       default:
-               g_error ("native type %02x not implemented", native_type); 
-               break;
-       }
-       g_assert_not_reached ();
-       return 0;
-}
-
 const char*
 mono_metadata_get_marshal_info (MonoImage *meta, guint32 idx, gboolean is_field)
 {
@@ -3110,3 +3167,86 @@ mono_guid_to_string (const guint8 *guid)
                                guid[10], guid[11], guid[12], guid[13], guid[14], guid[15]);
 }
 
+static MonoClass**
+get_constraints (MonoImage *image, int owner)
+{
+       MonoTableInfo *tdef  = &image->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
+       guint32 cols [MONO_GENPARCONSTRAINT_SIZE];
+       guint32 i, token, found;
+       MonoClass *klass, **res;
+       GList *cons = NULL, *tmp;
+       
+
+       found = 0;
+       for (i = 0; i < tdef->rows; ++i) {
+               mono_metadata_decode_row (tdef, i, cols, MONO_GENPARCONSTRAINT_SIZE);
+               if (cols [MONO_GENPARCONSTRAINT_GENERICPAR] == owner) {
+                       token = mono_metadata_token_from_dor (cols [MONO_GENPARCONSTRAINT_CONSTRAINT]);
+                       klass = mono_class_get (image, token);
+                       cons = g_list_append (cons, klass);
+                       ++found;
+               } else {
+                       /* contiguous list finished */
+                       if (found)
+                               break;
+               }
+       }
+       if (!found)
+               return NULL;
+       res = g_new0 (MonoClass*, found + 1);
+       for (i = 0, tmp = cons; i < found; ++i, tmp = tmp->next) {
+               res [i] = tmp->data;
+       }
+       g_list_free (cons);
+       return res;
+}
+
+MonoGenericParam *
+mono_metadata_load_generic_params (MonoImage *image, guint32 token, guint32 *num, MonoMethod *method)
+{
+       MonoTableInfo *tdef  = &image->tables [MONO_TABLE_GENERICPARAM];
+       guint32 cols [MONO_GENERICPARAM_SIZE];
+       guint32 i, owner, last_num, n;
+       MonoGenericParam *params;
+
+       if (mono_metadata_token_table (token) == MONO_TABLE_TYPEDEF)
+               owner = MONO_TYPEORMETHOD_TYPE;
+       else if (mono_metadata_token_table (token) == MONO_TABLE_METHOD)
+               owner = MONO_TYPEORMETHOD_METHOD;
+       else {
+               g_error ("wrong token %x to load_generics_params", token);
+       }
+       owner |= mono_metadata_token_index (token) << MONO_TYPEORMETHOD_BITS;
+       if (num)
+               *num = 0;
+       if (!tdef->base)
+               return NULL;
+
+       for (i = 0; i < tdef->rows; ++i) {
+               mono_metadata_decode_row (tdef, i, cols, MONO_GENERICPARAM_SIZE);
+               if (cols [MONO_GENERICPARAM_OWNER] == owner)
+                       break;
+       }
+       last_num = 0;
+       if (i >= tdef->rows)
+               return NULL;
+       params = NULL;
+       n = 1;
+       do {
+               params = g_realloc (params, sizeof (MonoGenericParam) * n);
+               params [n - 1].method = method;
+               params [n - 1].flags = cols [MONO_GENERICPARAM_FLAGS];
+               params [n - 1].num = cols [MONO_GENERICPARAM_NUMBER];
+               params [n - 1].name = mono_metadata_string_heap (image, cols [MONO_GENERICPARAM_NAME]);
+               params [n - 1].constraints = get_constraints (image, i + 1);
+               if (++i >= tdef->rows)
+                       break;
+               mono_metadata_decode_row (tdef, i, cols, MONO_GENERICPARAM_SIZE);
+               n++;
+       } while (cols [MONO_GENERICPARAM_OWNER] == owner);
+       
+       if (num)
+               *num = n;
+       return params;
+}
+