X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fmetadata.c;h=3d44463cde90be1fab9068944735fdeb6b6dd1ab;hb=dac1a705ea8721eeff8b2a91da1747d04706f0bb;hp=5b20bbdb0a754a105292726428741165f420afe3;hpb=4301d72d8c3a0edca19278c2c8c9f5b1d4e67477;p=mono.git diff --git a/mono/metadata/metadata.c b/mono/metadata/metadata.c index 5b20bbdb0a7..3d44463cde9 100644 --- a/mono/metadata/metadata.c +++ b/mono/metadata/metadata.c @@ -17,6 +17,8 @@ #include "mono-endian.h" #include "cil-coff.h" #include "tokentype.h" +#include "metadata-internals.h" +#include "class-internals.h" #include "private.h" #include "class.h" @@ -35,7 +37,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 +50,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 +75,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 +83,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 +104,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 +140,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 +178,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 +192,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 +209,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 +232,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 +278,44 @@ 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_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 +360,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 +374,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 +413,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){ @@ -435,7 +462,8 @@ mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bit break; case MONO_TABLE_EXPORTEDTYPE: g_assert (i == 1); - field_size = idx_size (MONO_TABLE_TYPEDEF); break; + /* the index is in another metadata file, so it must be 4 */ + field_size = 4; break; case MONO_TABLE_FIELDLAYOUT: g_assert (i == 1); field_size = idx_size (MONO_TABLE_FIELD); break; @@ -468,12 +496,26 @@ 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 (); } - if (field_size != idx_size (tableindex)) + if (tableindex != MONO_TABLE_EXPORTEDTYPE && field_size != idx_size (tableindex)) g_warning ("size changed (%d to %d)", idx_size (tableindex), field_size); break; @@ -733,7 +775,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; @@ -804,7 +846,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 } /** @@ -1011,8 +1057,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); @@ -1041,7 +1089,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); @@ -1091,8 +1138,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])) @@ -1121,6 +1166,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 @@ -1141,74 +1202,88 @@ MonoType* mono_metadata_parse_type (MonoImage *m, MonoParseTypeMode mode, short opt_attrs, const char *ptr, const char **rptr) { MonoType *type, *cached; + gboolean byref = FALSE; + gboolean pinned = FALSE; + const char *tmp_ptr; + int count = 0; + gboolean found; + + /* + * According to the spec, custom modifiers should come before the byref + * flag, but the IL produced by ilasm from the following signature: + * object modopt(...) & + * starts with a byref flag, followed by the modifiers. (bug #49802) + * Also, this type seems to be different from 'object & modopt(...)'. Maybe + * it would be better to treat byref as real type constructor instead of + * a modifier... + * Also, pinned should come before anything else, but some MSV++ produced + * assemblies violate this (#bug 61990). + */ - 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: - case MONO_PARSE_RET: - case MONO_PARSE_FIELD: { - /* count the modifiers */ - const char *tmp_ptr = ptr; - int count = 0; - 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->num_mods = count; - if (count > 64) - g_warning ("got more than 64 modifiers in type"); - /* save them this time */ - count = 0; - while (mono_metadata_parse_custom_mod (m, &(type->modifiers [count]), ptr, &ptr)) - count++; + /* Count the modifiers first */ + tmp_ptr = ptr; + found = TRUE; + while (found) { + switch (*tmp_ptr) { + case MONO_TYPE_PINNED: + case MONO_TYPE_BYREF: + ++tmp_ptr; + break; + case MONO_TYPE_CMOD_REQD: + case MONO_TYPE_CMOD_OPT: + count ++; + mono_metadata_parse_custom_mod (m, NULL, tmp_ptr, &tmp_ptr); break; - } /* fall through */ + default: + found = FALSE; + } } - case MONO_PARSE_LOCAL: - case MONO_PARSE_TYPE: + + if (count) { + 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"); + } + else /* * Later we can avoid doing this allocation. */ type = g_new0 (MonoType, 1); - break; - default: - g_assert_not_reached (); - } - - type->attrs = opt_attrs; - if (mode == MONO_PARSE_LOCAL) { - /* - * check for pinned flag - */ - if (*ptr == MONO_TYPE_PINNED) { - type->pinned = 1; + + /* Parse pinned, byref and custom modifiers */ + found = TRUE; + count = 0; + while (found) { + switch (*ptr) { + case MONO_TYPE_PINNED: + pinned = TRUE; + ++ptr; + break; + case MONO_TYPE_BYREF: + byref = TRUE; ++ptr; + break; + case MONO_TYPE_CMOD_REQD: + case MONO_TYPE_CMOD_OPT: + count ++; + mono_metadata_parse_custom_mod (m, &(type->modifiers [count]), ptr, &ptr); + break; + default: + found = FALSE; } } + + type->attrs = opt_attrs; + type->byref = byref; + type->pinned = pinned ? 1 : 0; + + do_mono_metadata_parse_type (type, m, ptr, &ptr); - switch (*ptr) { - case MONO_TYPE_BYREF: - if (mode == MONO_PARSE_FIELD) - g_warning ("A field type cannot be byref"); - type->byref = 1; - ptr++; - /* follow through */ - default: - /*if (*ptr == MONO_TYPE_VOID && mode != MONO_PARSE_RET) - g_error ("void not allowed in param");*/ - do_mono_metadata_parse_type (type, m, ptr, &ptr); - break; - } 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; @@ -1234,6 +1309,9 @@ mono_metadata_parse_signature (MonoImage *image, guint32 token) guint32 sig; const char *ptr; + if (image->dynamic) + return mono_lookup_dynamic_token (image, token); + g_assert (mono_metadata_token_table(token) == MONO_TABLE_STANDALONESIG); sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0); @@ -1244,10 +1322,32 @@ mono_metadata_parse_signature (MonoImage *image, guint32 token) return mono_metadata_parse_method_signature (image, FALSE, ptr, NULL); } +MonoMethodSignature* +mono_metadata_signature_alloc (MonoImage *m, guint32 nparams) +{ + MonoMethodSignature *sig; + + /* later we want to allocate signatures with mempools */ + sig = g_malloc0 (sizeof (MonoMethodSignature) + ((gint32)nparams - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*)); + sig->param_count = nparams; + sig->sentinelpos = -1; + + return sig; +} + +MonoMethodSignature* +mono_metadata_signature_dup (MonoMethodSignature *sig) +{ + int sigsize; + + sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *); + return g_memdup (sig, sigsize); +} + /* * mono_metadata_parse_method_signature: * @m: metadata context - * @def: use #TRUE when parsing MethodDef, #FALSE with MethodRef signatures. + * @def: the MethodDef index or 0 for Ref signatures. * @ptr: pointer to the signature metadata representation * @rptr: pointer updated to match the end of the decoded stream * @@ -1259,23 +1359,48 @@ MonoMethodSignature * mono_metadata_parse_method_signature (MonoImage *m, int def, const char *ptr, const char **rptr) { MonoMethodSignature *method; - int i; + 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); - method = g_malloc0 (sizeof (MonoMethodSignature) + (param_count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*)); - method->param_count = param_count; + if (def) { + MonoTableInfo *paramt = &m->tables [MONO_TABLE_PARAM]; + MonoTableInfo *methodt = &m->tables [MONO_TABLE_METHOD]; + guint32 cols [MONO_PARAM_SIZE]; + guint lastp, param_index = mono_metadata_decode_row_col (methodt, def - 1, MONO_METHOD_PARAMLIST); + + if (def < methodt->rows) + lastp = mono_metadata_decode_row_col (methodt, def, MONO_METHOD_PARAMLIST); + else + 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]) + ret_attrs = cols [MONO_PARAM_FLAGS]; + else + pattrs [cols [MONO_PARAM_SEQUENCE] - 1] = cols [MONO_PARAM_FLAGS]; + } + } + method = mono_metadata_signature_alloc (m, param_count); method->hasthis = hasthis; method->explicit_this = explicit_this; method->call_convention = call_convention; - method->ret = mono_metadata_parse_type (m, MONO_PARSE_RET, 0, ptr, &ptr); + method->generic_param_count = gen_param_count; + 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; @@ -1287,10 +1412,15 @@ mono_metadata_parse_method_signature (MonoImage *m, int def, const char *ptr, co method->sentinelpos = i; ptr++; } - method->params [i] = mono_metadata_parse_type (m, MONO_PARSE_PARAM, 0, ptr, &ptr); + method->params [i] = mono_metadata_parse_type (m, MONO_PARSE_PARAM, pattrs [i], ptr, &ptr); } } + if (def && (method->call_convention == MONO_CALL_VARARG)) + method->sentinelpos = method->param_count; + + g_free (pattrs); + if (rptr) *rptr = ptr; /* @@ -1316,6 +1446,97 @@ mono_metadata_free_method_signature (MonoMethodSignature *sig) g_free (sig); } +static void +do_mono_metadata_parse_generic_inst (MonoType *type, MonoImage *m, const char *ptr, const char **rptr) +{ + MonoGenericInst *ginst = g_new0 (MonoGenericInst, 1); + MonoType *cached; + int i, count; + + type->data.generic_inst = ginst; + + ginst->context = g_new0 (MonoGenericContext, 1); + ginst->context->ginst = ginst; + + ginst->klass = g_new0 (MonoClass, 1); + + ginst->generic_type = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, ptr, &ptr); + ginst->type_argc = count = mono_metadata_decode_value (ptr, &ptr); + ginst->type_argv = g_new0 (MonoType*, count); + + /* + * Create the klass before parsing the type arguments. + * This is required to support "recursive" definitions. + * See mcs/tests/gen-23.cs for an example. + */ + + ginst->init_pending = TRUE; + + mono_class_create_generic (ginst); + + for (i = 0; i < ginst->type_argc; i++) { + MonoType *t = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, ptr, &ptr); + + ginst->type_argv [i] = t; + if (!ginst->is_open) + ginst->is_open = mono_class_is_open_constructed_type (t); + } + + + if (rptr) + *rptr = ptr; + + /* + * We may be called multiple times on different metadata to create the same + * instantiated type. This happens for instance if we're part of a method or + * local variable signature. + * + * It's important to return the same MonoGenericInst * for each particualar + * instantiation of a generic type (ie "Stack") to make static fields + * work. + * + * According to the spec ($26.1.5), a static variable in a generic class + * declaration is shared amongst all instances of the same closed constructed + * type. + */ + + cached = g_hash_table_lookup (m->generic_inst_cache, ginst); + if (cached) { + g_free (ginst->klass); + g_free (ginst->type_argv); + g_free (ginst); + + type->data.generic_inst = cached->data.generic_inst; + return; + } else { + cached = g_new0 (MonoType, 1); + cached->type = MONO_TYPE_GENERICINST; + cached->data.generic_inst = ginst; + + g_hash_table_insert (m->generic_inst_cache, ginst, cached); + + mono_stats.generic_instance_count++; + mono_stats.generics_metadata_size += sizeof (MonoGenericInst) + + sizeof (MonoGenericContext) + + ginst->type_argc * sizeof (MonoType); + } + + ginst->init_pending = FALSE; +} + +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 @@ -1362,7 +1583,12 @@ 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); + mono_metadata_free_type (etype); + break; + } case MONO_TYPE_PTR: type->data.type = mono_metadata_parse_type (m, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr); break; @@ -1372,8 +1598,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: + do_mono_metadata_parse_generic_inst (type, 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) @@ -1392,7 +1628,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; @@ -1711,8 +1946,6 @@ typedef struct { guint32 result; } locator_t; -#define CSIZE(x) (sizeof (x) / 4) - /* * How the row locator works. * @@ -1941,37 +2174,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; + start = start_index; - if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) - return 0; - - start = loc.result; - - 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; } /* @@ -2010,8 +2239,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 /* @@ -2084,11 +2363,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: + return mono_class_value_size (mono_defaults.typed_reference_class, align); + case MONO_TYPE_GENERICINST: { + MonoGenericInst *ginst = t->data.generic_inst; + MonoClass *iclass = mono_class_from_mono_type (ginst->generic_type); + 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; } @@ -2133,9 +2422,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) * 3; case MONO_TYPE_R4: *align = __alignof__(float); return sizeof (float); @@ -2157,83 +2448,43 @@ mono_type_stack_size (MonoType *t, gint *align) *align = *align + __alignof__(gpointer) - 1; *align &= ~(__alignof__(gpointer) - 1); + size += sizeof (gpointer) - 1; + size &= ~(sizeof (gpointer) - 1); + return size; } } + case MONO_TYPE_GENERICINST: { + MonoGenericInst *ginst = t->data.generic_inst; + MonoClass *iclass = mono_class_from_mono_type (ginst->generic_type); + return mono_type_stack_size (&iclass->byval_arg, align); + } 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) +guint +mono_metadata_generic_inst_hash (MonoGenericInst *ginst) { - int tmp; - - g_assert (t != NULL); - - if (!align) - align = &tmp; - - if (t->byref) { - *align = 4; - return 4; - } + return mono_metadata_type_hash (ginst->generic_type); +} - 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; +gboolean +mono_metadata_generic_inst_equal (MonoGenericInst *g1, MonoGenericInst *g2) +{ + int i; - 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; - } - } - default: - g_error ("type 0x%02x unknown", t->type); + if (g1->type_argc != g2->type_argc) + return FALSE; + if (!mono_metadata_type_equal (g1->generic_type, g2->generic_type)) + return FALSE; + for (i = 0; i < g1->type_argc; ++i) { + if (!mono_metadata_type_equal (g1->type_argv [i], g2->type_argv [i])) + return FALSE; } - return 0; + return TRUE; } /* @@ -2251,15 +2502,33 @@ 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_generic_inst_hash (t1->data.generic_inst); } return hash; } +static gboolean +mono_metadata_class_equal (MonoClass *c1, MonoClass *c2) +{ + if (c1 == c2) + return TRUE; + if (c1->generic_inst && c2->generic_inst) + return mono_metadata_generic_inst_equal (c1->generic_inst, c2->generic_inst); + if ((c1->byval_arg.type == MONO_TYPE_VAR) && (c2->byval_arg.type == MONO_TYPE_VAR)) + return c1->byval_arg.data.generic_param->num == c2->byval_arg.data.generic_param->num; + if ((c1->byval_arg.type == MONO_TYPE_MVAR) && (c2->byval_arg.type == MONO_TYPE_MVAR)) + return c1->byval_arg.data.generic_param->num == c2->byval_arg.data.generic_param->num; + return FALSE; +} + /* * mono_metadata_type_equal: * @t1: a type @@ -2293,17 +2562,24 @@ mono_metadata_type_equal (MonoType *t1, MonoType *t2) case MONO_TYPE_I: case MONO_TYPE_U: case MONO_TYPE_OBJECT: + case MONO_TYPE_TYPEDBYREF: return TRUE; case MONO_TYPE_VALUETYPE: case MONO_TYPE_CLASS: - return t1->data.klass == t2->data.klass; - case MONO_TYPE_PTR: case MONO_TYPE_SZARRAY: + return mono_metadata_class_equal (t1->data.klass, t2->data.klass); + case MONO_TYPE_PTR: 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 mono_metadata_class_equal (t1->data.array->eklass, t2->data.array->eklass); + case MONO_TYPE_GENERICINST: + return mono_metadata_generic_inst_equal (t1->data.generic_inst, + t2->data.generic_inst); + case MONO_TYPE_VAR: + case MONO_TYPE_MVAR: + return t1->data.generic_param->num == t2->data.generic_param->num; default: g_error ("implement type compare for %0x!", t1->type); return FALSE; @@ -2334,9 +2610,9 @@ mono_metadata_signature_equal (MonoMethodSignature *sig1, MonoMethodSignature *s MonoType *p1 = sig1->params[i]; MonoType *p2 = sig2->params[i]; - if (p1->attrs != p2->attrs) + /* if (p1->attrs != p2->attrs) return FALSE; - + */ if (!mono_metadata_type_equal (p1, p2)) return FALSE; } @@ -2372,9 +2648,9 @@ mono_metadata_encode_value (guint32 value, char *buf, char **endbuf) { char *p = buf; - if (value <= 127) + if (value < 0x80) *p++ = value; - else if (value <= 16384) { + else if (value < 0x4000) { p [0] = 0x80 | (value >> 8); p [1] = value & 0xff; p += 2; @@ -2443,17 +2719,8 @@ mono_metadata_field_info (MonoImage *meta, guint32 index, guint32 *offset, guint if (marshal_spec) { const char *p; - tdef = &meta->tables [MONO_TABLE_FIELDMARSHAL]; - - loc.col_idx = MONO_FIELD_MARSHAL_PARENT; - loc.t = tdef; - loc.idx = (loc.idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_FIELDSREF; - - if (tdef->base && bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) { - p = mono_metadata_blob_heap (meta, mono_metadata_decode_row_col (tdef, loc.result, MONO_FIELD_MARSHAL_NATIVE_TYPE)); + if ((p = mono_metadata_get_marshal_info (meta, index, TRUE))) { *marshal_spec = mono_metadata_parse_marshal_spec (meta, p); - } else { - *marshal_spec = NULL; } } @@ -2463,29 +2730,30 @@ mono_metadata_field_info (MonoImage *meta, guint32 index, guint32 *offset, guint * mono_metadata_get_constant_index: * @meta: the Image the field is defined in * @index: the token that may have a row defined in the constants table + * @hint: possible position for the row * * @token must be a FieldDef, ParamDef or PropertyDef token. * - * Returns: the index into the Constsnts table or 0 if not found. + * Returns: the index into the Constants table or 0 if not found. */ guint32 -mono_metadata_get_constant_index (MonoImage *meta, guint32 token) +mono_metadata_get_constant_index (MonoImage *meta, guint32 token, guint32 hint) { MonoTableInfo *tdef; locator_t loc; guint32 index = mono_metadata_token_index (token); tdef = &meta->tables [MONO_TABLE_CONSTANT]; - index <<= HASCONSTANT_BITS; + index <<= MONO_HASCONSTANT_BITS; switch (mono_metadata_token_table (token)) { case MONO_TABLE_FIELD: - index |= HASCONSTANT_FIEDDEF; + index |= MONO_HASCONSTANT_FIEDDEF; break; case MONO_TABLE_PARAM: - index |= HASCONSTANT_PARAM; + index |= MONO_HASCONSTANT_PARAM; break; case MONO_TABLE_PROPERTY: - index |= HASCONSTANT_PROPERTY; + index |= MONO_HASCONSTANT_PROPERTY; break; default: g_warning ("Not a valid token for the constant table: 0x%08x", token); @@ -2495,6 +2763,9 @@ mono_metadata_get_constant_index (MonoImage *meta, guint32 token) loc.col_idx = MONO_CONSTANT_PARENT; loc.t = tdef; + if ((hint > 0) && (hint < tdef->rows) && (mono_metadata_decode_row_col (tdef, hint - 1, MONO_CONSTANT_PARENT) == index)) + return hint; + if (tdef->base && bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) { return loc.result + 1; } @@ -2563,7 +2834,7 @@ mono_metadata_methods_from_event (MonoImage *meta, guint32 index, guint *end_i loc.t = msemt; loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION; - loc.idx = ((index + 1) << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT; /* Method association coded index */ + loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT; /* Method association coded index */ if (!bsearch (&loc, msemt->base, msemt->rows, msemt->row_size, table_locator)) return 0; @@ -2651,7 +2922,7 @@ mono_metadata_methods_from_property (MonoImage *meta, guint32 index, guint *en loc.t = msemt; loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION; - loc.idx = ((index + 1) << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY; /* Method association coded index */ + loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY; /* Method association coded index */ if (!bsearch (&loc, msemt->base, msemt->rows, msemt->row_size, table_locator)) return 0; @@ -2688,7 +2959,7 @@ mono_metadata_implmap_from_method (MonoImage *meta, guint32 method_idx) loc.t = tdef; loc.col_idx = MONO_IMPLMAP_MEMBER; - loc.idx = ((method_idx + 1) << MEMBERFORWD_BITS) | MEMBERFORWD_METHODDEF; + loc.idx = ((method_idx + 1) << MONO_MEMBERFORWD_BITS) | MONO_MEMBERFORWD_METHODDEF; if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) return 0; @@ -2713,12 +2984,31 @@ mono_type_create_from_typespec (MonoImage *image, guint32 type_spec) guint32 len; MonoType *type; + mono_loader_lock (); + + if ((type = g_hash_table_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec)))) { + mono_loader_unlock (); + return type; + } + t = &image->tables [MONO_TABLE_TYPESPEC]; mono_metadata_decode_row (t, idx-1, cols, MONO_TYPESPEC_SIZE); ptr = mono_metadata_blob_heap (image, cols [MONO_TYPESPEC_SIGNATURE]); len = mono_metadata_decode_value (ptr, &ptr); - type = mono_metadata_parse_type (image, MONO_PARSE_TYPE, 0, ptr, &ptr); + + type = g_new0 (MonoType, 1); + + g_hash_table_insert (image->typespec_cache, GUINT_TO_POINTER (type_spec), type); + + if (*ptr == MONO_TYPE_BYREF) { + type->byref = 1; + ptr++; + } + + do_mono_metadata_parse_type (type, image, ptr, &ptr); + + mono_loader_unlock (); return type; } @@ -2739,21 +3029,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; @@ -2785,8 +3091,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); } @@ -2882,11 +3189,23 @@ handle_enum: case MONO_NATIVE_IUNKNOWN: *conv = MONO_MARSHAL_CONV_OBJECT_IUNKNOWN; return MONO_NATIVE_IUNKNOWN; + case MONO_NATIVE_FUNC: + 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; + } + else + /* Fall through */ + ; default: 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; } @@ -2901,86 +3220,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) { @@ -2992,7 +3231,7 @@ mono_metadata_get_marshal_info (MonoImage *meta, guint32 idx, gboolean is_field) loc.t = tdef; loc.col_idx = MONO_FIELD_MARSHAL_PARENT; - loc.idx = ((idx + 1) << HAS_FIELD_MARSHAL_BITS) | (is_field? HAS_FIELD_MARSHAL_FIELDSREF: HAS_FIELD_MARSHAL_PARAMDEF); + loc.idx = ((idx + 1) << MONO_HAS_FIELD_MARSHAL_BITS) | (is_field? MONO_HAS_FIELD_MARSHAL_FIELDSREF: MONO_HAS_FIELD_MARSHAL_PARAMDEF); if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) return NULL; @@ -3003,11 +3242,11 @@ mono_metadata_get_marshal_info (MonoImage *meta, guint32 idx, gboolean is_field) static MonoMethod* method_from_method_def_or_ref (MonoImage *m, guint32 tok) { - guint32 idx = tok >> METHODDEFORREF_BITS; - switch (tok & METHODDEFORREF_MASK) { - case METHODDEFORREF_METHODDEF: + guint32 idx = tok >> MONO_METHODDEFORREF_BITS; + switch (tok & MONO_METHODDEFORREF_MASK) { + case MONO_METHODDEFORREF_METHODDEF: return mono_get_method (m, MONO_TOKEN_METHOD_DEF | idx, NULL); - case METHODDEFORREF_METHODREF: + case MONO_METHODDEFORREF_METHODREF: return mono_get_method (m, MONO_TOKEN_MEMBER_REF | idx, NULL); } g_assert_not_reached (); @@ -3067,3 +3306,204 @@ mono_class_get_overrides (MonoImage *image, guint32 type_token, gint32 *num_over return result; } +/** + * mono_guid_to_string: + * + * Converts a 16 byte Microsoft GUID to the standard string representation. + */ +char * +mono_guid_to_string (const guint8 *guid) +{ + return g_strdup_printf ("%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X", + guid[3], guid[2], guid[1], guid[0], + guid[5], guid[4], + guid[7], guid[6], + guid[8], guid[9], + 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) +{ + 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 = 0; + do { + n++; + params = g_realloc (params, sizeof (MonoGenericParam) * n); + params [n - 1].pklass = NULL; + params [n - 1].method = NULL; + 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); + } while (cols [MONO_GENERICPARAM_OWNER] == owner); + + if (num) + *num = n; + return params; +} + +gboolean +mono_type_is_byref (MonoType *type) +{ + return type->byref; +} + +int +mono_type_get_type (MonoType *type) +{ + return type->type; +} + +/* For MONO_TYPE_FNPTR */ +MonoMethodSignature* +mono_type_get_signature (MonoType *type) +{ + return type->data.method; +} + +/* For MONO_TYPE_CLASS, VALUETYPE */ +MonoClass* +mono_type_get_class (MonoType *type) +{ + return type->data.klass; +} + +/* For MONO_TYPE_ARRAY */ +MonoArrayType* +mono_type_get_array_type (MonoType *type) +{ + return type->data.array; +} + +MonoClass* +mono_type_get_modifiers (MonoType *type, gboolean *is_required, gpointer *iter) +{ + /* FIXME: implement */ + return NULL; +} + +MonoType* +mono_signature_get_return_type (MonoMethodSignature *sig) +{ + return sig->ret; +} + +MonoType* +mono_signature_get_params (MonoMethodSignature *sig, gpointer *iter) +{ + MonoType** type; + if (!iter) + return NULL; + if (!*iter) { + /* start from the first */ + if (sig->param_count) { + *iter = &sig->params [0]; + return sig->params [0]; + } else { + /* no method */ + return NULL; + } + } + type = *iter; + type++; + if (type < &sig->params [sig->param_count]) { + *iter = type; + return *type; + } + return NULL; +} + +guint32 +mono_signature_get_param_count (MonoMethodSignature *sig) +{ + return sig->param_count; +} + +guint32 +mono_signature_get_call_conv (MonoMethodSignature *sig) +{ + return sig->call_convention; +} + +int +mono_signature_vararg_start (MonoMethodSignature *sig) +{ + return sig->sentinelpos; +} + +gboolean +mono_signature_is_instance (MonoMethodSignature *sig) +{ + return sig->hasthis; +} + +gboolean +mono_signature_explicit_this (MonoMethodSignature *sig) +{ + return sig->explicit_this; +} +