*/
#include <config.h>
-#include <stdio.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include "class-internals.h"
#include "class.h"
-static void do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContext *generic_context,
+static gboolean do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container,
const char *ptr, const char **rptr);
static gboolean do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only);
static gboolean mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only);
+static gboolean mono_metadata_fnptr_equal (MonoMethodSignature *s1, MonoMethodSignature *s2, gboolean signature_only);
static gboolean _mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2,
gboolean signature_only);
MONO_MT_RS_IDX
};
-const static unsigned char AssemblySchema [] = {
+const static unsigned char TableSchemas [] = {
+#define ASSEMBLY_SCHEMA_OFFSET 0
MONO_MT_UINT32, /* "HashId" }, */
MONO_MT_UINT16, /* "Major" }, */
MONO_MT_UINT16, /* "Minor" }, */
MONO_MT_BLOB_IDX, /* "PublicKey" }, */
MONO_MT_STRING_IDX, /* "Name" }, */
MONO_MT_STRING_IDX, /* "Culture" }, */
- MONO_MT_END
-};
-
-const static unsigned char AssemblyOSSchema [] = {
+ MONO_MT_END,
+
+#define ASSEMBLYOS_SCHEMA_OFFSET ASSEMBLY_SCHEMA_OFFSET + 10
MONO_MT_UINT32, /* "OSPlatformID" }, */
MONO_MT_UINT32, /* "OSMajor" }, */
MONO_MT_UINT32, /* "OSMinor" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
-const static unsigned char AssemblyProcessorSchema [] = {
+#define ASSEMBLYPROC_SCHEMA_OFFSET ASSEMBLYOS_SCHEMA_OFFSET + 4
MONO_MT_UINT32, /* "Processor" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
-const static unsigned char AssemblyRefSchema [] = {
+#define ASSEMBLYREF_SCHEMA_OFFSET ASSEMBLYPROC_SCHEMA_OFFSET + 2
MONO_MT_UINT16, /* "Major" }, */
MONO_MT_UINT16, /* "Minor" }, */
MONO_MT_UINT16, /* "Build" }, */
MONO_MT_STRING_IDX, /* "Name" }, */
MONO_MT_STRING_IDX, /* "Culture" }, */
MONO_MT_BLOB_IDX, /* "HashValue" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
-const static unsigned char AssemblyRefOSSchema [] = {
+#define ASSEMBLYREFOS_SCHEMA_OFFSET ASSEMBLYREF_SCHEMA_OFFSET + 10
MONO_MT_UINT32, /* "OSPlatformID" }, */
MONO_MT_UINT32, /* "OSMajorVersion" }, */
MONO_MT_UINT32, /* "OSMinorVersion" }, */
MONO_MT_TABLE_IDX, /* "AssemblyRef:AssemblyRef" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
-const static unsigned char AssemblyRefProcessorSchema [] = {
+#define ASSEMBLYREFPROC_SCHEMA_OFFSET ASSEMBLYREFOS_SCHEMA_OFFSET + 5
MONO_MT_UINT32, /* "Processor" }, */
MONO_MT_TABLE_IDX, /* "AssemblyRef:AssemblyRef" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
-const static unsigned char ClassLayoutSchema [] = {
+#define CLASS_LAYOUT_SCHEMA_OFFSET ASSEMBLYREFPROC_SCHEMA_OFFSET + 3
MONO_MT_UINT16, /* "PackingSize" }, */
MONO_MT_UINT32, /* "ClassSize" }, */
MONO_MT_TABLE_IDX, /* "Parent:TypeDef" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
-const static unsigned char ConstantSchema [] = {
+#define CONSTANT_SCHEMA_OFFSET CLASS_LAYOUT_SCHEMA_OFFSET + 4
MONO_MT_UINT8, /* "Type" }, */
MONO_MT_UINT8, /* "PaddingZero" }, */
MONO_MT_CONST_IDX, /* "Parent" }, */
MONO_MT_BLOB_IDX, /* "Value" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
-const static unsigned char CustomAttributeSchema [] = {
+#define CUSTOM_ATTR_SCHEMA_OFFSET CONSTANT_SCHEMA_OFFSET + 5
MONO_MT_HASCAT_IDX, /* "Parent" }, */
MONO_MT_CAT_IDX, /* "Type" }, */
MONO_MT_BLOB_IDX, /* "Value" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
-const static unsigned char DeclSecuritySchema [] = {
+#define DECL_SEC_SCHEMA_OFFSET CUSTOM_ATTR_SCHEMA_OFFSET + 4
MONO_MT_UINT16, /* "Action" }, */
MONO_MT_HASDEC_IDX, /* "Parent" }, */
MONO_MT_BLOB_IDX, /* "PermissionSet" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
-const static unsigned char EventMapSchema [] = {
+#define EVENTMAP_SCHEMA_OFFSET DECL_SEC_SCHEMA_OFFSET + 4
MONO_MT_TABLE_IDX, /* "Parent:TypeDef" }, */
MONO_MT_TABLE_IDX, /* "EventList:Event" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
-const static unsigned char EventSchema [] = {
+#define EVENT_SCHEMA_OFFSET EVENTMAP_SCHEMA_OFFSET + 3
MONO_MT_UINT16, /* "EventFlags#EventAttribute" }, */
MONO_MT_STRING_IDX, /* "Name" }, */
MONO_MT_TABLE_IDX, /* "EventType" }, TypeDef or TypeRef */
- MONO_MT_END
-};
+ MONO_MT_END,
+
+#define EVENT_POINTER_SCHEMA_OFFSET EVENT_SCHEMA_OFFSET + 4
+ MONO_MT_TABLE_IDX, /* "Event" }, */
+ MONO_MT_END,
-const static unsigned char ExportedTypeSchema [] = {
+#define EXPORTED_TYPE_SCHEMA_OFFSET EVENT_POINTER_SCHEMA_OFFSET + 2
MONO_MT_UINT32, /* "Flags" }, */
MONO_MT_TABLE_IDX, /* "TypeDefId" }, */
MONO_MT_STRING_IDX, /* "TypeName" }, */
MONO_MT_STRING_IDX, /* "TypeNameSpace" }, */
MONO_MT_IMPL_IDX, /* "Implementation" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
-const static unsigned char FieldSchema [] = {
+#define FIELD_SCHEMA_OFFSET EXPORTED_TYPE_SCHEMA_OFFSET + 6
MONO_MT_UINT16, /* "Flags" }, */
MONO_MT_STRING_IDX, /* "Name" }, */
MONO_MT_BLOB_IDX, /* "Signature" }, */
- MONO_MT_END
-};
-const static unsigned char FieldLayoutSchema [] = {
+ MONO_MT_END,
+
+#define FIELD_LAYOUT_SCHEMA_OFFSET FIELD_SCHEMA_OFFSET + 4
MONO_MT_UINT32, /* "Offset" }, */
MONO_MT_TABLE_IDX, /* "Field:Field" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
-const static unsigned char FieldMarshalSchema [] = {
+#define FIELD_MARSHAL_SCHEMA_OFFSET FIELD_LAYOUT_SCHEMA_OFFSET + 3
MONO_MT_HFM_IDX, /* "Parent" }, */
MONO_MT_BLOB_IDX, /* "NativeType" }, */
- MONO_MT_END
-};
-const static unsigned char FieldRVASchema [] = {
+ MONO_MT_END,
+
+#define FIELD_RVA_SCHEMA_OFFSET FIELD_MARSHAL_SCHEMA_OFFSET + 3
MONO_MT_UINT32, /* "RVA" }, */
MONO_MT_TABLE_IDX, /* "Field:Field" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
+
+#define FIELD_POINTER_SCHEMA_OFFSET FIELD_RVA_SCHEMA_OFFSET + 3
+ MONO_MT_TABLE_IDX, /* "Field" }, */
+ MONO_MT_END,
-const static unsigned char FileSchema [] = {
+#define FILE_SCHEMA_OFFSET FIELD_POINTER_SCHEMA_OFFSET + 2
MONO_MT_UINT32, /* "Flags" }, */
MONO_MT_STRING_IDX, /* "Name" }, */
MONO_MT_BLOB_IDX, /* "Value" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
-const static unsigned char ImplMapSchema [] = {
+#define IMPLMAP_SCHEMA_OFFSET FILE_SCHEMA_OFFSET + 4
MONO_MT_UINT16, /* "MappingFlag" }, */
MONO_MT_MF_IDX, /* "MemberForwarded" }, */
MONO_MT_STRING_IDX, /* "ImportName" }, */
MONO_MT_TABLE_IDX, /* "ImportScope:ModuleRef" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
-const static unsigned char InterfaceImplSchema [] = {
+#define IFACEMAP_SCHEMA_OFFSET IMPLMAP_SCHEMA_OFFSET + 5
MONO_MT_TABLE_IDX, /* "Class:TypeDef" }, */
MONO_MT_TDOR_IDX, /* "Interface=TypeDefOrRef" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
-const static unsigned char ManifestResourceSchema [] = {
+#define MANIFEST_SCHEMA_OFFSET IFACEMAP_SCHEMA_OFFSET + 3
MONO_MT_UINT32, /* "Offset" }, */
MONO_MT_UINT32, /* "Flags" }, */
MONO_MT_STRING_IDX, /* "Name" }, */
MONO_MT_IMPL_IDX, /* "Implementation" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
-const static unsigned char MemberRefSchema [] = {
+#define MEMBERREF_SCHEMA_OFFSET MANIFEST_SCHEMA_OFFSET + 5
MONO_MT_MRP_IDX, /* "Class" }, */
MONO_MT_STRING_IDX, /* "Name" }, */
MONO_MT_BLOB_IDX, /* "Signature" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
-const static unsigned char MethodSchema [] = {
+#define METHOD_SCHEMA_OFFSET MEMBERREF_SCHEMA_OFFSET + 4
MONO_MT_UINT32, /* "RVA" }, */
MONO_MT_UINT16, /* "ImplFlags#MethodImplAttributes" }, */
MONO_MT_UINT16, /* "Flags#MethodAttribute" }, */
MONO_MT_STRING_IDX, /* "Name" }, */
MONO_MT_BLOB_IDX, /* "Signature" }, */
MONO_MT_TABLE_IDX, /* "ParamList:Param" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
-const static unsigned char MethodImplSchema [] = {
+#define METHOD_IMPL_SCHEMA_OFFSET METHOD_SCHEMA_OFFSET + 7
MONO_MT_TABLE_IDX, /* "Class:TypeDef" }, */
MONO_MT_MDOR_IDX, /* "MethodBody" }, */
MONO_MT_MDOR_IDX, /* "MethodDeclaration" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
-const static unsigned char MethodSemanticsSchema [] = {
+#define METHOD_SEMA_SCHEMA_OFFSET METHOD_IMPL_SCHEMA_OFFSET + 4
MONO_MT_UINT16, /* "MethodSemantic" }, */
MONO_MT_TABLE_IDX, /* "Method:Method" }, */
MONO_MT_HS_IDX, /* "Association" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
-const static unsigned char ModuleSchema [] = {
+#define METHOD_POINTER_SCHEMA_OFFSET METHOD_SEMA_SCHEMA_OFFSET + 4
+ MONO_MT_TABLE_IDX, /* "Method" }, */
+ MONO_MT_END,
+
+#define MODULE_SCHEMA_OFFSET METHOD_POINTER_SCHEMA_OFFSET + 2
MONO_MT_UINT16, /* "Generation" }, */
MONO_MT_STRING_IDX, /* "Name" }, */
MONO_MT_GUID_IDX, /* "MVID" }, */
MONO_MT_GUID_IDX, /* "EncID" }, */
MONO_MT_GUID_IDX, /* "EncBaseID" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
-const static unsigned char ModuleRefSchema [] = {
+#define MODULEREF_SCHEMA_OFFSET MODULE_SCHEMA_OFFSET + 6
MONO_MT_STRING_IDX, /* "Name" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
-const static unsigned char NestedClassSchema [] = {
+#define NESTED_CLASS_SCHEMA_OFFSET MODULEREF_SCHEMA_OFFSET + 2
MONO_MT_TABLE_IDX, /* "NestedClass:TypeDef" }, */
MONO_MT_TABLE_IDX, /* "EnclosingClass:TypeDef" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
-const static unsigned char ParamSchema [] = {
+#define PARAM_SCHEMA_OFFSET NESTED_CLASS_SCHEMA_OFFSET + 3
MONO_MT_UINT16, /* "Flags" }, */
MONO_MT_UINT16, /* "Sequence" }, */
MONO_MT_STRING_IDX, /* "Name" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
-const static unsigned char PropertySchema [] = {
+#define PARAM_POINTER_SCHEMA_OFFSET PARAM_SCHEMA_OFFSET + 4
+ MONO_MT_TABLE_IDX, /* "Param" }, */
+ MONO_MT_END,
+
+#define PROPERTY_SCHEMA_OFFSET PARAM_POINTER_SCHEMA_OFFSET + 2
MONO_MT_UINT16, /* "Flags" }, */
MONO_MT_STRING_IDX, /* "Name" }, */
MONO_MT_BLOB_IDX, /* "Type" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
+
+#define PROPERTY_POINTER_SCHEMA_OFFSET PROPERTY_SCHEMA_OFFSET + 4
+ MONO_MT_TABLE_IDX, /* "Property" }, */
+ MONO_MT_END,
-const static unsigned char PropertyMapSchema [] = {
+#define PROPERTY_MAP_SCHEMA_OFFSET PROPERTY_POINTER_SCHEMA_OFFSET + 2
MONO_MT_TABLE_IDX, /* "Parent:TypeDef" }, */
MONO_MT_TABLE_IDX, /* "PropertyList:Property" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
-const static unsigned char StandaloneSigSchema [] = {
+#define STDALON_SIG_SCHEMA_OFFSET PROPERTY_MAP_SCHEMA_OFFSET + 3
MONO_MT_BLOB_IDX, /* "Signature" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
-const static unsigned char TypeDefSchema [] = {
+#define TYPEDEF_SCHEMA_OFFSET STDALON_SIG_SCHEMA_OFFSET + 2
MONO_MT_UINT32, /* "Flags" }, */
MONO_MT_STRING_IDX, /* "Name" }, */
MONO_MT_STRING_IDX, /* "Namespace" }, */
MONO_MT_TDOR_IDX, /* "Extends" }, */
MONO_MT_TABLE_IDX, /* "FieldList:Field" }, */
MONO_MT_TABLE_IDX, /* "MethodList:Method" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
-const static unsigned char TypeRefSchema [] = {
+#define TYPEREF_SCHEMA_OFFSET TYPEDEF_SCHEMA_OFFSET + 7
MONO_MT_RS_IDX, /* "ResolutionScope=ResolutionScope" }, */
MONO_MT_STRING_IDX, /* "Name" }, */
MONO_MT_STRING_IDX, /* "Namespace" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
-const static unsigned char TypeSpecSchema [] = {
+#define TYPESPEC_SCHEMA_OFFSET TYPEREF_SCHEMA_OFFSET + 4
MONO_MT_BLOB_IDX, /* "Signature" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
-const static unsigned char GenericParamSchema [] = {
+#define GENPARAM_SCHEMA_OFFSET TYPESPEC_SCHEMA_OFFSET + 2
MONO_MT_UINT16, /* "Number" }, */
MONO_MT_UINT16, /* "Flags" }, */
MONO_MT_TABLE_IDX, /* "Owner" }, TypeDef or MethodDef */
MONO_MT_STRING_IDX, /* "Name" }, */
+ MONO_MT_END,
- /* soon to be removed */
- MONO_MT_TABLE_IDX, /* "Kind" }, */
-
- MONO_MT_END
-};
-
-const static unsigned char MethodSpecSchema [] = {
+#define METHOD_SPEC_SCHEMA_OFFSET GENPARAM_SCHEMA_OFFSET + 5
MONO_MT_MDOR_IDX, /* "Method" }, */
MONO_MT_BLOB_IDX, /* "Signature" }, */
- MONO_MT_END
-};
+ MONO_MT_END,
-const static unsigned char GenericParamConstraintSchema [] = {
+#define GEN_CONSTRAINT_SCHEMA_OFFSET METHOD_SPEC_SCHEMA_OFFSET + 3
MONO_MT_TABLE_IDX, /* "GenericParam" }, */
MONO_MT_TDOR_IDX, /* "Constraint" }, */
+ MONO_MT_END,
+
+#define NULL_SCHEMA_OFFSET GEN_CONSTRAINT_SCHEMA_OFFSET + 3
MONO_MT_END
};
-const static struct {
- const unsigned char *description;
- const char *name;
-} tables [] = {
- /* 0 */ { ModuleSchema, "Module" },
- /* 1 */ { TypeRefSchema, "TypeRef" },
- /* 2 */ { TypeDefSchema, "TypeDef" },
- /* 3 */ { NULL, NULL },
- /* 4 */ { FieldSchema, "Field" },
- /* 5 */ { NULL, NULL },
- /* 6 */ { MethodSchema, "Method" },
- /* 7 */ { NULL, NULL },
- /* 8 */ { ParamSchema, "Param" },
- /* 9 */ { InterfaceImplSchema, "InterfaceImpl" },
- /* A */ { MemberRefSchema, "MemberRef" },
- /* B */ { ConstantSchema, "Constant" },
- /* C */ { CustomAttributeSchema, "CustomAttribute" },
- /* D */ { FieldMarshalSchema, "FieldMarshal" },
- /* E */ { DeclSecuritySchema, "DeclSecurity" },
- /* F */ { ClassLayoutSchema, "ClassLayout" },
- /* 10 */ { FieldLayoutSchema, "FieldLayout" },
- /* 11 */ { StandaloneSigSchema, "StandaloneSig" },
- /* 12 */ { EventMapSchema, "EventMap" },
- /* 13 */ { NULL, NULL },
- /* 14 */ { EventSchema, "Event" },
- /* 15 */ { PropertyMapSchema, "PropertyMap" },
- /* 16 */ { NULL, NULL },
- /* 17 */ { PropertySchema, "PropertyTable" },
- /* 18 */ { MethodSemanticsSchema, "MethodSemantics" },
- /* 19 */ { MethodImplSchema, "MethodImpl" },
- /* 1A */ { ModuleRefSchema, "ModuleRef" },
- /* 1B */ { TypeSpecSchema, "TypeSpec" },
- /* 1C */ { ImplMapSchema, "ImplMap" },
- /* 1D */ { FieldRVASchema, "FieldRVA" },
- /* 1E */ { NULL, NULL },
- /* 1F */ { NULL, NULL },
- /* 20 */ { AssemblySchema, "Assembly" },
- /* 21 */ { AssemblyProcessorSchema, "AssemblyProcessor" },
- /* 22 */ { AssemblyOSSchema, "AssemblyOS" },
- /* 23 */ { AssemblyRefSchema, "AssemblyRef" },
- /* 24 */ { AssemblyRefProcessorSchema, "AssemblyRefProcessor" },
- /* 25 */ { AssemblyRefOSSchema, "AssemblyRefOS" },
- /* 26 */ { FileSchema, "File" },
- /* 27 */ { ExportedTypeSchema, "ExportedType" },
- /* 28 */ { ManifestResourceSchema, "ManifestResource" },
- /* 29 */ { NestedClassSchema, "NestedClass" },
- /* 2A */ { GenericParamSchema, "GenericParam" },
- /* 2B */ { MethodSpecSchema, "MethodSpec" },
- /* 2C */ { GenericParamConstraintSchema, "GenericParamConstraint" },
+/* Must be the same order as MONO_TABLE_* */
+const static unsigned char
+table_description [] = {
+ MODULE_SCHEMA_OFFSET,
+ TYPEREF_SCHEMA_OFFSET,
+ TYPEDEF_SCHEMA_OFFSET,
+ FIELD_POINTER_SCHEMA_OFFSET,
+ FIELD_SCHEMA_OFFSET,
+ METHOD_POINTER_SCHEMA_OFFSET,
+ METHOD_SCHEMA_OFFSET,
+ PARAM_POINTER_SCHEMA_OFFSET,
+ PARAM_SCHEMA_OFFSET,
+ IFACEMAP_SCHEMA_OFFSET,
+ MEMBERREF_SCHEMA_OFFSET, /* 0xa */
+ CONSTANT_SCHEMA_OFFSET,
+ CUSTOM_ATTR_SCHEMA_OFFSET,
+ FIELD_MARSHAL_SCHEMA_OFFSET,
+ DECL_SEC_SCHEMA_OFFSET,
+ CLASS_LAYOUT_SCHEMA_OFFSET,
+ FIELD_LAYOUT_SCHEMA_OFFSET, /* 0x10 */
+ STDALON_SIG_SCHEMA_OFFSET,
+ EVENTMAP_SCHEMA_OFFSET,
+ EVENT_POINTER_SCHEMA_OFFSET,
+ EVENT_SCHEMA_OFFSET,
+ PROPERTY_MAP_SCHEMA_OFFSET,
+ PROPERTY_POINTER_SCHEMA_OFFSET,
+ PROPERTY_SCHEMA_OFFSET,
+ METHOD_SEMA_SCHEMA_OFFSET,
+ METHOD_IMPL_SCHEMA_OFFSET,
+ MODULEREF_SCHEMA_OFFSET, /* 0x1a */
+ TYPESPEC_SCHEMA_OFFSET,
+ IMPLMAP_SCHEMA_OFFSET,
+ FIELD_RVA_SCHEMA_OFFSET,
+ NULL_SCHEMA_OFFSET,
+ NULL_SCHEMA_OFFSET,
+ ASSEMBLY_SCHEMA_OFFSET, /* 0x20 */
+ ASSEMBLYPROC_SCHEMA_OFFSET,
+ ASSEMBLYOS_SCHEMA_OFFSET,
+ ASSEMBLYREF_SCHEMA_OFFSET,
+ ASSEMBLYREFPROC_SCHEMA_OFFSET,
+ ASSEMBLYREFOS_SCHEMA_OFFSET,
+ FILE_SCHEMA_OFFSET,
+ EXPORTED_TYPE_SCHEMA_OFFSET,
+ MANIFEST_SCHEMA_OFFSET,
+ NESTED_CLASS_SCHEMA_OFFSET,
+ GENPARAM_SCHEMA_OFFSET, /* 0x2a */
+ METHOD_SPEC_SCHEMA_OFFSET,
+ GEN_CONSTRAINT_SCHEMA_OFFSET
};
+#ifdef HAVE_ARRAY_ELEM_INIT
+#define MSGSTRFIELD(line) MSGSTRFIELD1(line)
+#define MSGSTRFIELD1(line) str##line
+static const struct msgstr_t {
+#define TABLEDEF(a,b) char MSGSTRFIELD(__LINE__) [sizeof (b)];
+#include "mono/cil/tables.def"
+#undef TABLEDEF
+} tablestr = {
+#define TABLEDEF(a,b) b,
+#include "mono/cil/tables.def"
+#undef TABLEDEF
+};
+static const gint16 tableidx [] = {
+#define TABLEDEF(a,b) [a] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
+#include "mono/cil/tables.def"
+#undef TABLEDEF
+};
+
+#else
+#define TABLEDEF(a,b) b,
+static const char* const
+mono_tables_names [] = {
+#include "mono/cil/tables.def"
+ NULL
+};
+
+#endif
+
/**
* mono_meta_table_name:
* @table: table index
const char *
mono_meta_table_name (int table)
{
- if ((table < 0) || (table > 0x2c))
+ if ((table < 0) || (table > MONO_TABLE_LAST))
return "";
-
- return tables [table].name;
+
+#ifdef HAVE_ARRAY_ELEM_INIT
+ return (const char*)&tablestr + tableidx [table];
+#else
+ return mono_tables_names [table];
+#endif
}
/* The guy who wrote the spec for this should not be allowed near a
* @result_bitfield return value along with the number of columns in the table.
* the resulting bitfield should be handed to the mono_metadata_table_size()
* and mono_metadata_table_count() macros.
+ * This is a Mono runtime internal only function.
*/
int
mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bitfield)
int size = 0, field_size = 0;
int i, n, code;
int shift = 0;
- const unsigned char *description = tables [tableindex].description;
+ const unsigned char *description = TableSchemas + table_description [tableindex];
for (i = 0; (code = description [i]) != MONO_MT_END; i++){
switch (code){
field_size = MAX (idx_size (MONO_TABLE_TYPEDEF), idx_size(MONO_TABLE_TYPEREF));
field_size = MAX (field_size, idx_size(MONO_TABLE_TYPESPEC));
break;
+ case MONO_TABLE_EVENT_POINTER:
+ g_assert (i == 0);
+ field_size = idx_size (MONO_TABLE_EVENT); break;
case MONO_TABLE_EXPORTEDTYPE:
g_assert (i == 1);
/* the index is in another metadata file, so it must be 4 */
case MONO_TABLE_FIELDRVA:
g_assert (i == 1);
field_size = idx_size (MONO_TABLE_FIELD); break;
+ case MONO_TABLE_FIELD_POINTER:
+ g_assert (i == 0);
+ field_size = idx_size (MONO_TABLE_FIELD); break;
case MONO_TABLE_IMPLMAP:
g_assert (i == 3);
field_size = idx_size (MONO_TABLE_MODULEREF); break;
case MONO_TABLE_METHODSEMANTICS:
g_assert (i == 1);
field_size = idx_size (MONO_TABLE_METHOD); break;
+ case MONO_TABLE_METHOD_POINTER:
+ g_assert (i == 0);
+ field_size = idx_size (MONO_TABLE_METHOD); break;
case MONO_TABLE_NESTEDCLASS:
g_assert (i == 0 || i == 1);
field_size = idx_size (MONO_TABLE_TYPEDEF); break;
+ case MONO_TABLE_PARAM_POINTER:
+ g_assert (i == 0);
+ field_size = idx_size (MONO_TABLE_PARAM); break;
case MONO_TABLE_PROPERTYMAP:
g_assert (i == 0 || i == 1);
field_size = i ? idx_size (MONO_TABLE_PROPERTY):
idx_size(MONO_TABLE_TYPEDEF);
break;
+ case MONO_TABLE_PROPERTY_POINTER:
+ g_assert (i == 0);
+ field_size = idx_size (MONO_TABLE_PROPERTY); break;
case MONO_TABLE_TYPEDEF:
g_assert (i == 4 || i == 5);
field_size = i == 4 ? idx_size (MONO_TABLE_FIELD):
int i;
const char *base = meta->tables_base;
- for (i = 0; i < MONO_TABLE_NUM; i++){
- if (meta->tables [i].rows == 0)
+ for (i = 0; i < MONO_TABLE_NUM; i++) {
+ MonoTableInfo *table = &meta->tables [i];
+ if (table->rows == 0)
continue;
- meta->tables [i].row_size = mono_metadata_compute_size (
- meta, i, &meta->tables [i].size_bitfield);
- meta->tables [i].base = base;
- base += meta->tables [i].rows * meta->tables [i].row_size;
+ table->row_size = mono_metadata_compute_size (meta, i, &table->size_bitfield);
+ table->base = base;
+ base += table->rows * table->row_size;
}
}
g_assert (res_size == count);
- for (i = 0; i < count; i++){
+ for (i = 0; i < count; i++) {
int n = mono_metadata_table_size (bitfield, i);
switch (n){
res [i] = *data; break;
case 2:
res [i] = read16 (data); break;
-
case 4:
res [i] = read32 (data); break;
-
default:
g_assert_not_reached ();
}
data += n;
n = mono_metadata_table_size (bitfield, i + 1);
}
- switch (n){
+ switch (n) {
case 1:
return *data;
case 2:
}
return 0;
}
+
/**
* mono_metadata_decode_blob_size:
* @ptr: pointer to a blob object
return size;
}
-
/**
* mono_metadata_decode_value:
* @ptr: pointer to decode from
return len;
}
+/**
+ * mono_metadata_decode_signed_value:
+ * @ptr: pointer to decode from
+ * @rptr: the new position of the pointer
+ *
+ * This routine decompresses 32-bit signed values
+ * (not specified in the spec)
+ *
+ * Returns: the decoded value
+ */
+gint32
+mono_metadata_decode_signed_value (const char *ptr, const char **rptr)
+{
+ guint32 uval = mono_metadata_decode_value (ptr, rptr);
+ gint32 ival = uval >> 1;
+ if (!(uval & 1))
+ return ival;
+ /* ival is a truncated 2's complement negative number. */
+ if (ival < 0x40)
+ /* 6 bits = 7 bits for compressed representation (top bit is '0') - 1 sign bit */
+ return ival - 0x40;
+ if (ival < 0x2000)
+ /* 13 bits = 14 bits for compressed representation (top bits are '10') - 1 sign bit */
+ return ival - 0x2000;
+ if (ival < 0x10000000)
+ /* 28 bits = 29 bits for compressed representation (top bits are '110') - 1 sign bit */
+ return ival - 0x10000000;
+ g_assert (ival < 0x20000000);
+ g_warning ("compressed signed value appears to use 29 bits for compressed representation: %x (raw: %8x)", ival, uval);
+ return ival - 0x20000000;
+}
+
+/*
+ * Translates the given 1-based index into the Method, Field, Event, or Param tables
+ * using the *Ptr tables in uncompressed metadata, if they are available.
+ *
+ * FIXME: The caller is not forced to call this function, which is error-prone, since
+ * forgetting to call it would only show up as a bug on uncompressed metadata.
+ */
+guint32
+mono_metadata_translate_token_index (MonoImage *image, int table, guint32 idx)
+{
+ if (!image->uncompressed_metadata)
+ return idx;
+
+ switch (table) {
+ case MONO_TABLE_METHOD:
+ if (image->tables [MONO_TABLE_METHOD_POINTER].rows)
+ return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD_POINTER], idx - 1, MONO_METHOD_POINTER_METHOD);
+ else
+ return idx;
+ case MONO_TABLE_FIELD:
+ if (image->tables [MONO_TABLE_FIELD_POINTER].rows)
+ return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_FIELD_POINTER], idx - 1, MONO_FIELD_POINTER_FIELD);
+ else
+ return idx;
+ case MONO_TABLE_EVENT:
+ if (image->tables [MONO_TABLE_EVENT_POINTER].rows)
+ return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_EVENT_POINTER], idx - 1, MONO_EVENT_POINTER_EVENT);
+ else
+ return idx;
+ case MONO_TABLE_PROPERTY:
+ if (image->tables [MONO_TABLE_PROPERTY_POINTER].rows)
+ return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_PROPERTY_POINTER], idx - 1, MONO_PROPERTY_POINTER_PROPERTY);
+ else
+ return idx;
+ case MONO_TABLE_PARAM:
+ if (image->tables [MONO_TABLE_PARAM_POINTER].rows)
+ return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_PARAM_POINTER], idx - 1, MONO_PARAM_POINTER_PARAM);
+ else
+ return idx;
+ default:
+ return idx;
+ }
+}
+
+/**
+ * mono_metadata_decode_table_row:
+ *
+ * Same as mono_metadata_decode_row, but takes an IMAGE+TABLE ID pair, and takes
+ * uncompressed metadata into account, so it should be used to access the
+ * Method, Field, Param and Event tables when the access is made from metadata, i.e.
+ * IDX is retrieved from a metadata table, like MONO_TYPEDEF_FIELD_LIST.
+ */
+void
+mono_metadata_decode_table_row (MonoImage *image, int table, int idx, guint32 *res, int res_size)
+{
+ if (image->uncompressed_metadata)
+ idx = mono_metadata_translate_token_index (image, table, idx + 1) - 1;
+
+ mono_metadata_decode_row (&image->tables [table], idx, res, res_size);
+}
+
+/**
+ * mono_metadata_decode_table_row_col:
+ *
+ * Same as mono_metadata_decode_row_col, but takes an IMAGE+TABLE ID pair, and takes
+ * uncompressed metadata into account, so it should be used to access the
+ * Method, Field, Param and Event tables.
+ */
+guint32 mono_metadata_decode_table_row_col (MonoImage *image, int table, int idx, guint col)
+{
+ if (image->uncompressed_metadata)
+ idx = mono_metadata_translate_token_index (image, table, idx + 1) - 1;
+
+ return mono_metadata_decode_row_col (&image->tables [table], idx, col);
+}
+
/*
* mono_metadata_parse_typedef_or_ref:
* @m: a metadata context.
mono_metadata_parse_custom_mod (MonoImage *m, MonoCustomMod *dest, const char *ptr, const char **rptr)
{
MonoCustomMod local;
- if ((*ptr == MONO_TYPE_CMOD_OPT) ||
- (*ptr == MONO_TYPE_CMOD_REQD)) {
+ if ((*ptr == MONO_TYPE_CMOD_OPT) || (*ptr == MONO_TYPE_CMOD_REQD)) {
if (!dest)
dest = &local;
dest->required = *ptr == MONO_TYPE_CMOD_REQD ? 1 : 0;
* and dimensions.
*/
MonoArrayType *
-mono_metadata_parse_array_full (MonoImage *m, MonoGenericContext *generic_context,
+mono_metadata_parse_array_full (MonoImage *m, MonoGenericContainer *container,
const char *ptr, const char **rptr)
{
int i;
MonoArrayType *array = g_new0 (MonoArrayType, 1);
MonoType *etype;
- etype = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_TYPE, 0, ptr, &ptr);
+ etype = mono_metadata_parse_type_full (m, container, MONO_PARSE_TYPE, 0, ptr, &ptr);
+ if (!etype)
+ return NULL;
array->eklass = mono_class_from_mono_type (etype);
array->rank = mono_metadata_decode_value (ptr, &ptr);
if (array->numlobounds)
array->lobounds = g_new0 (int, array->numlobounds);
for (i = 0; i < array->numlobounds; ++i)
- array->lobounds [i] = mono_metadata_decode_value (ptr, &ptr);
+ array->lobounds [i] = mono_metadata_decode_signed_value (ptr, &ptr);
if (rptr)
*rptr = ptr;
static GHashTable *generic_class_cache = NULL;
static int next_generic_inst_id = 0;
+static guint mono_generic_class_hash (gconstpointer data);
+
/*
* MonoTypes with modifies are never cached, so we never check or use that field.
*/
mono_type_hash (gconstpointer data)
{
const MonoType *type = (const MonoType *) data;
- return type->type | (type->byref << 8) | (type->attrs << 9);
+ if (type->type == MONO_TYPE_GENERICINST)
+ return mono_generic_class_hash (type->data.generic_class);
+ else
+ return type->type | (type->byref << 8) | (type->attrs << 9);
}
static gint
mono_generic_inst_hash (gconstpointer data)
{
const MonoGenericInst *ginst = (const MonoGenericInst *) data;
- return ginst->type_argc | (ginst->is_open << 8);
+ guint hash = 0;
+ int i;
+
+ for (i = 0; i < ginst->type_argc; ++i) {
+ hash *= 13;
+ hash += mono_metadata_type_hash (ginst->type_argv [i]);
+ }
+
+ return hash ^ (ginst->is_open << 8);
}
static gboolean
mono_generic_class_hash (gconstpointer data)
{
const MonoGenericClass *gclass = (const MonoGenericClass *) data;
- return mono_metadata_type_hash (&gclass->container_class->byval_arg);
+ guint hash = mono_metadata_type_hash (&gclass->container_class->byval_arg);
+
+ hash *= 13;
+ hash += mono_generic_inst_hash (gclass->inst);
+
+ return hash;
}
static gboolean
/**
* mono_metadata_init:
*
- * Initialize the global variables of this module.
+ * Initialize the global variables of this module.
+ * This is a Mono runtime internal function.
*/
void
mono_metadata_init (void)
g_hash_table_insert (type_cache, (gpointer) &builtin_types [i], (gpointer) &builtin_types [i]);
}
+/**
+ * mono_metadata_cleanup:
+ *
+ * Free all resources used by this module.
+ * This is a Mono runtime internal function.
+ */
+void
+mono_metadata_cleanup (void)
+{
+ g_hash_table_destroy (type_cache);
+ g_hash_table_destroy (generic_inst_cache);
+ g_hash_table_destroy (generic_class_cache);
+}
+
/**
* mono_metadata_parse_type:
* @m: metadata context
* (the `generic_container' field in the MonoMethodNormal) generic container.
* When we encounter any MONO_TYPE_VAR or MONO_TYPE_MVAR's, they're looked up in
* this MonoGenericContainer.
+ * This is a Mono runtime internal function.
+ *
+ * LOCKING: Assumes the loader lock is held.
*
* Returns: a #MonoType structure representing the decoded type.
*/
MonoType*
-mono_metadata_parse_type_full (MonoImage *m, MonoGenericContext *generic_context, MonoParseTypeMode mode,
+mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *container, MonoParseTypeMode mode,
short opt_attrs, const char *ptr, const char **rptr)
{
MonoType *type, *cached;
int count = 0;
gboolean found;
+ mono_loader_lock ();
/*
* According to the spec, custom modifiers should come before the byref
* flag, but the IL produced by ilasm from the following signature:
}
if (count) {
- type = g_malloc0 (sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod));
+ type = mono_mempool_alloc0 (m->mempool, 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 {
+ } else {
type = &stype;
memset (type, 0, sizeof (MonoType));
}
type->byref = byref;
type->pinned = pinned ? 1 : 0;
- do_mono_metadata_parse_type (type, m, generic_context, ptr, &ptr);
+ if (!do_mono_metadata_parse_type (type, m, container, ptr, &ptr)) {
+ if (type != &stype)
+ g_free (type);
+ mono_loader_unlock ();
+ return NULL;
+ }
if (rptr)
*rptr = ptr;
-
- /* FIXME: remove the != MONO_PARSE_PARAM condition, this accounts for
- * almost 10k (about 2/3rds) of all MonoType's we create.
- */
- if (mode != MONO_PARSE_PARAM && !type->num_mods) {
+ if (!type->num_mods) {
/* no need to free type here, because it is on the stack */
if ((type->type == MONO_TYPE_CLASS || type->type == MONO_TYPE_VALUETYPE) && !type->pinned && !type->attrs) {
- if (type->byref)
- return &type->data.klass->this_arg;
- else
- return &type->data.klass->byval_arg;
+ MonoType *ret = type->byref ? &type->data.klass->this_arg : &type->data.klass->byval_arg;
+
+ /* Consider the case:
+
+ class Foo<T> { class Bar {} }
+ class Test : Foo<Test>.Bar {}
+
+ When Foo<Test> is being expanded, 'Test' isn't yet initialized. It's actually in
+ a really pristine state: it doesn't even know whether 'Test' is a reference or a value type.
+
+ We ensure that the MonoClass is in a state that we can canonicalize to:
+
+ klass->byval_arg.data.klass == klass
+ klass->this_arg.data.klass == klass
+
+ If we can't canonicalize 'type', it doesn't matter, since later users of 'type' will do it.
+
+ LOCKING: even though we don't explicitly hold a lock, in the problematic case 'ret' is a field
+ of a MonoClass which currently holds the loader lock. 'type' is local.
+ */
+ if (ret->data.klass == type->data.klass) {
+ mono_loader_unlock ();
+ return ret;
+ }
}
/* No need to use locking since nobody is modifying the hash table */
- if ((cached = g_hash_table_lookup (type_cache, type)))
+ if ((cached = g_hash_table_lookup (type_cache, type))) {
+ mono_loader_unlock ();
return cached;
+ }
}
- /*printf ("%x%c %s\n", type->attrs, type->pinned ? 'p' : ' ', mono_type_full_name (type));*/
+ /* printf ("%x %x %c %s\n", type->attrs, type->num_mods, type->pinned ? 'p' : ' ', mono_type_full_name (type)); */
- if (type == &stype)
- type = g_memdup (&stype, sizeof (MonoType));
+ if (type == &stype) {
+ type = mono_mempool_alloc (m->mempool, sizeof (MonoType));
+ memcpy (type, &stype, sizeof (MonoType));
+ }
+ mono_loader_unlock ();
return type;
}
+/*
+ * LOCKING: Assumes the loader lock is held.
+ */
MonoType*
mono_metadata_parse_type (MonoImage *m, MonoParseTypeMode mode, short opt_attrs,
const char *ptr, const char **rptr)
}
/*
- * mono_metadata_parse_signature:
+ * mono_metadata_get_param_attrs:
+ *
+ * Return the parameter attributes for the method whose MethodDef index is DEF. The
+ * returned memory needs to be freed by the caller. If all the param attributes are
+ * 0, then NULL is returned.
+ */
+int*
+mono_metadata_get_param_attrs (MonoImage *m, int def)
+{
+ MonoTableInfo *paramt = &m->tables [MONO_TABLE_PARAM];
+ MonoTableInfo *methodt = &m->tables [MONO_TABLE_METHOD];
+ guint32 cols [MONO_PARAM_SIZE];
+ guint lastp, i, param_index = mono_metadata_decode_row_col (&m->tables [MONO_TABLE_METHOD], def - 1, MONO_METHOD_PARAMLIST);
+ int *pattrs = NULL;
+
+ if (def < methodt->rows)
+ lastp = mono_metadata_decode_row_col (&m->tables [MONO_TABLE_METHOD], def, MONO_METHOD_PARAMLIST);
+ else
+ lastp = paramt->rows + 1;
+
+ for (i = param_index; i < lastp; ++i) {
+ mono_metadata_decode_row (&m->tables [MONO_TABLE_PARAM], i - 1, cols, MONO_PARAM_SIZE);
+ if (cols [MONO_PARAM_FLAGS]) {
+ if (!pattrs)
+ pattrs = g_new0 (int, 1 + (lastp - param_index));
+ pattrs [cols [MONO_PARAM_SEQUENCE]] = cols [MONO_PARAM_FLAGS];
+ }
+ }
+
+ return pattrs;
+}
+
+/*
+ * mono_metadata_parse_signature_full:
* @image: metadata context
+ * @generic_container: generic container
* @toke: metadata token
*
* Decode a method signature stored in the STANDALONESIG table
*
+ * LOCKING: Assumes the loader lock is held.
+ *
* Returns: a MonoMethodSignature describing the signature.
*/
-MonoMethodSignature *
-mono_metadata_parse_signature_full (MonoImage *image, MonoGenericContext *generic_context, guint32 token)
+MonoMethodSignature*
+mono_metadata_parse_signature_full (MonoImage *image, MonoGenericContainer *generic_container, guint32 token)
{
MonoTableInfo *tables = image->tables;
guint32 idx = mono_metadata_token_index (token);
ptr = mono_metadata_blob_heap (image, sig);
mono_metadata_decode_blob_size (ptr, &ptr);
- return mono_metadata_parse_method_signature_full (image, generic_context, FALSE, ptr, NULL);
+ return mono_metadata_parse_method_signature_full (image, generic_container, 0, ptr, NULL);
}
-MonoMethodSignature *
+/*
+ * mono_metadata_parse_signature:
+ * @image: metadata context
+ * @toke: metadata token
+ *
+ * Decode a method signature stored in the STANDALONESIG table
+ *
+ * Returns: a MonoMethodSignature describing the signature.
+ */
+MonoMethodSignature*
mono_metadata_parse_signature (MonoImage *image, guint32 token)
{
return mono_metadata_parse_signature_full (image, NULL, token);
}
+/*
+ * mono_metadata_signature_alloc:
+ * @image: metadata context
+ * @nparmas: number of parameters in the signature
+ *
+ * Allocate a MonoMethodSignature structure with the specified number of params.
+ * The return type and the params types need to be filled later.
+ * This is a Mono runtime internal function.
+ *
+ * LOCKING: Assumes the loader lock is held.
+ *
+ * Returns: the new MonoMethodSignature structure.
+ */
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*));
+ mono_loader_lock ();
+ sig = mono_mempool_alloc0 (m->mempool, sizeof (MonoMethodSignature) + ((gint32)nparams - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
sig->param_count = nparams;
sig->sentinelpos = -1;
+ mono_loader_unlock ();
return sig;
}
+/*
+ * mono_metadata_signature_dup:
+ * @sig: method signature
+ *
+ * Duplicate an existing MonoMethodSignature so it can be modified.
+ * This is a Mono runtime internal function.
+ *
+ * Returns: the new MonoMethodSignature structure.
+ */
MonoMethodSignature*
mono_metadata_signature_dup (MonoMethodSignature *sig)
{
int sigsize;
- sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
+ sigsize = sizeof (MonoMethodSignature) + (sig->param_count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType *);
return g_memdup (sig, sigsize);
}
/*
* mono_metadata_parse_method_signature:
* @m: metadata context
+ * @generic_container: generics container
* @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
*
* Decode a method signature stored at @ptr.
+ * This is a Mono runtime internal function.
+ *
+ * LOCKING: Assumes the loader lock is held.
*
* Returns: a MonoMethodSignature describing the signature.
*/
MonoMethodSignature *
-mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContext *generic_context,
+mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *container,
int def, const char *ptr, const char **rptr)
{
MonoMethodSignature *method;
- int i, ret_attrs = 0, *pattrs = NULL;
+ int i, *pattrs = NULL;
guint32 hasthis = 0, explicit_this = 0, call_convention, param_count;
guint32 gen_param_count = 0;
gboolean is_open = FALSE;
- MonoGenericContext *context = NULL;
if (*ptr & 0x10)
gen_param_count = 1;
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);
-
- 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];
- }
- }
+ if (def)
+ pattrs = mono_metadata_get_param_attrs (m, def);
method = mono_metadata_signature_alloc (m, param_count);
method->hasthis = hasthis;
method->explicit_this = explicit_this;
method->call_convention = call_convention;
method->generic_param_count = gen_param_count;
- if (gen_param_count)
- method->has_type_parameters = 1;
-
- if (gen_param_count && (!generic_context || !generic_context->container->is_method)) {
- MonoGenericContainer *container = g_new0 (MonoGenericContainer, 1);
-
- if (generic_context)
- container->parent = generic_context->container;
- container->is_signature = 1;
-
- context = &container->context;
- container->context.container = container;
-
- container->type_argc = gen_param_count;
- container->type_params = g_new0 (MonoGenericParam, gen_param_count);
-
- for (i = 0; i < gen_param_count; i++) {
- container->type_params [i].owner = container;
- container->type_params [i].num = i;
- }
- } else
- context = generic_context;
-
if (call_convention != 0xa) {
- method->ret = mono_metadata_parse_type_full (m, context, MONO_PARSE_RET, ret_attrs, ptr, &ptr);
+ method->ret = mono_metadata_parse_type_full (m, container, MONO_PARSE_RET, pattrs ? pattrs [0] : 0, ptr, &ptr);
+ if (!method->ret) {
+ mono_metadata_free_method_signature (method);
+ g_free (pattrs);
+ return NULL;
+ }
is_open = mono_class_is_open_constructed_type (method->ret);
}
- if (method->param_count) {
- method->sentinelpos = -1;
-
- for (i = 0; i < method->param_count; ++i) {
- if (*ptr == MONO_TYPE_SENTINEL) {
- if (method->call_convention != MONO_CALL_VARARG || def)
- g_error ("found sentinel for methoddef or no vararg method");
- method->sentinelpos = i;
- ptr++;
- }
- method->params [i] = mono_metadata_parse_type_full (
- m, context, MONO_PARSE_PARAM, pattrs [i], ptr, &ptr);
- if (!is_open)
- is_open = mono_class_is_open_constructed_type (method->params [i]);
+ for (i = 0; i < method->param_count; ++i) {
+ if (*ptr == MONO_TYPE_SENTINEL) {
+ if (method->call_convention != MONO_CALL_VARARG || def)
+ g_error ("found sentinel for methoddef or no vararg method");
+ if (method->sentinelpos >= 0)
+ g_error ("found sentinel twice in the same signature");
+ method->sentinelpos = i;
+ ptr++;
+ }
+ method->params [i] = mono_metadata_parse_type_full (m, container, MONO_PARSE_PARAM, pattrs ? pattrs [i+1] : 0, ptr, &ptr);
+ if (!method->params [i]) {
+ mono_metadata_free_method_signature (method);
+ g_free (pattrs);
+ return NULL;
}
+ if (!is_open)
+ is_open = mono_class_is_open_constructed_type (method->params [i]);
}
+ /* The sentinel could be missing if the caller does not pass any additional arguments */
+ if (!def && method->call_convention == MONO_CALL_VARARG && method->sentinelpos < 0)
+ method->sentinelpos = method->param_count;
+
method->has_type_parameters = is_open;
if (def && (method->call_convention == MONO_CALL_VARARG))
/*
* Add signature to a cache and increase ref count...
*/
+
return method;
}
+/*
+ * mono_metadata_parse_method_signature:
+ * @m: metadata context
+ * @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
+ *
+ * Decode a method signature stored at @ptr.
+ * This is a Mono runtime internal function.
+ *
+ * LOCKING: Assumes the loader lock is held.
+ *
+ * Returns: a MonoMethodSignature describing the signature.
+ */
MonoMethodSignature *
mono_metadata_parse_method_signature (MonoImage *m, int def, const char *ptr, const char **rptr)
{
* @sig: signature to destroy
*
* Free the memory allocated in the signature @sig.
+ * This method needs to be robust and work also on partially-built
+ * signatures, so it does extra checks.
*/
void
mono_metadata_free_method_signature (MonoMethodSignature *sig)
{
int i;
- mono_metadata_free_type (sig->ret);
- for (i = 0; i < sig->param_count; ++i)
- mono_metadata_free_type (sig->params [i]);
-
- g_free (sig);
+ if (sig->ret)
+ mono_metadata_free_type (sig->ret);
+ for (i = 0; i < sig->param_count; ++i) {
+ if (sig->params [i])
+ mono_metadata_free_type (sig->params [i]);
+ }
}
+/*
+ * mono_metadata_lookup_generic_inst:
+ *
+ * Check whether the newly created generic instantiation @ginst already exists
+ * in the cache and return the cached value in this case. Otherwise insert
+ * it into the cache.
+ *
+ * Use this method each time you create a new `MonoGenericInst' to ensure
+ * proper caching. Only use the returned value as the argument passed to this
+ * method may be freed.
+ *
+ */
MonoGenericInst *
mono_metadata_lookup_generic_inst (MonoGenericInst *ginst)
{
return ginst;
}
+/*
+ * mono_metadata_lookup_generic_class:
+ *
+ * Check whether the newly created generic class @gclass already exists
+ * in the cache and return the cached value in this case. Otherwise insert
+ * it into the cache and return NULL.
+ *
+ * Returns: the previosly cached generic class or NULL if it has been newly
+ * inserted into the cache.
+ *
+ */
MonoGenericClass *
mono_metadata_lookup_generic_class (MonoGenericClass *gclass)
{
return NULL;
}
+/*
+ * mono_metadata_inflate_generic_inst:
+ *
+ * Instantiate the generic instance @ginst with the context @context.
+ *
+ */
MonoGenericInst *
mono_metadata_inflate_generic_inst (MonoGenericInst *ginst, MonoGenericContext *context)
{
MonoGenericInst *nginst;
int i;
+ if (!ginst->is_open)
+ return ginst;
+
nginst = g_new0 (MonoGenericInst, 1);
nginst->type_argc = ginst->type_argc;
nginst->type_argv = g_new0 (MonoType*, nginst->type_argc);
}
MonoGenericInst *
-mono_metadata_parse_generic_inst (MonoImage *m, MonoGenericContext *generic_context,
+mono_metadata_parse_generic_inst (MonoImage *m, MonoGenericContainer *container,
int count, const char *ptr, const char **rptr)
{
MonoGenericInst *ginst;
ginst->is_reference = 1;
for (i = 0; i < ginst->type_argc; i++) {
- MonoType *t = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_TYPE, 0, ptr, &ptr);
+ MonoType *t = mono_metadata_parse_type_full (m, container, MONO_PARSE_TYPE, 0, ptr, &ptr);
+ if (!t) {
+ g_free (ginst->type_argv);
+ g_free (ginst);
+ return NULL;
+ }
ginst->type_argv [i] = t;
if (!ginst->is_open)
ginst->is_open = mono_class_is_open_constructed_type (t);
return mono_metadata_lookup_generic_inst (ginst);
}
-static void
-do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericContext *generic_context,
+static gboolean
+do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericContainer *container,
const char *ptr, const char **rptr)
{
- MonoGenericClass *gclass = g_new0 (MonoGenericClass, 1);
- MonoGenericClass *cached;
+ MonoInflatedGenericClass *igclass;
+ MonoGenericClass *gclass, *cached;
MonoClass *gklass;
MonoType *gtype;
int count;
+ igclass = g_new0 (MonoInflatedGenericClass, 1);
+ gclass = &igclass->generic_class;
+ gclass->is_inflated = TRUE;
+
type->data.generic_class = gclass;
gclass->context = g_new0 (MonoGenericContext, 1);
gclass->context->gclass = gclass;
- gclass->klass = g_new0 (MonoClass, 1);
-
- gtype = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_TYPE, 0, ptr, &ptr);
- gclass->container_class = gklass = mono_class_from_mono_type (gtype);
-
- g_assert ((gclass->context->container = gklass->generic_container) != NULL);
- count = mono_metadata_decode_value (ptr, &ptr);
-
/*
* Create the klass before parsing the type arguments.
* This is required to support "recursive" definitions.
* See mcs/tests/gen-23.cs for an example.
*/
+ igclass->klass = g_new0 (MonoClass, 1);
- mono_class_create_generic (gclass);
+ gtype = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, ptr, &ptr);
+ if (gtype == NULL)
+ return FALSE;
+ gclass->container_class = gklass = mono_class_from_mono_type (gtype);
- gclass->inst = mono_metadata_parse_generic_inst (m, generic_context, count, ptr, &ptr);
+ g_assert (gklass->generic_container);
+ gclass->context->container = gklass->generic_container;
+
+ count = mono_metadata_decode_value (ptr, &ptr);
+
+ gclass->inst = mono_metadata_parse_generic_inst (m, container, count, ptr, &ptr);
if (rptr)
*rptr = ptr;
+ /* If we failed to parse, return, the error has been flagged. */
+ if (gclass->inst == NULL)
+ return FALSE;
+
/*
* 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
cached = g_hash_table_lookup (generic_class_cache, gclass);
if (cached) {
- g_free (gclass->klass);
+ g_free (igclass->klass);
g_free (gclass);
type->data.generic_class = cached;
- return;
+ return TRUE;
} else {
g_hash_table_insert (generic_class_cache, gclass, gclass);
sizeof (MonoGenericContext) +
gclass->inst->type_argc * sizeof (MonoType);
}
+ return TRUE;
+}
+
+/*
+ * select_container:
+ * @gc: The generic container to normalize
+ * @type: The kind of generic parameters the resulting generic-container should contain
+ */
+
+static MonoGenericContainer *
+select_container (MonoGenericContainer *gc, MonoTypeEnum type)
+{
+ gboolean is_var = (type == MONO_TYPE_VAR);
+ if (!gc)
+ return NULL;
+
+ g_assert (is_var || type == MONO_TYPE_MVAR);
+
+ if (is_var) {
+ if (gc->is_method || gc->parent)
+ /*
+ * The current MonoGenericContainer is a generic method -> its `parent'
+ * points to the containing class'es container.
+ */
+ return gc->parent;
+ }
+
+ return gc;
}
/*
- * do_mono_metadata_parse_generic_param:
+ * mono_metadata_parse_generic_param:
* @generic_container: Our MonoClass's or MonoMethodNormal's MonoGenericContainer;
* see mono_metadata_parse_type_full() for details.
* Internal routine to parse a generic type parameter.
*/
static MonoGenericParam *
-mono_metadata_parse_generic_param (MonoImage *m, MonoGenericContext *generic_context,
- gboolean is_mvar, const char *ptr, const char **rptr)
+mono_metadata_parse_generic_param (MonoImage *m, MonoGenericContainer *generic_container,
+ MonoTypeEnum type, const char *ptr, const char **rptr)
{
- MonoGenericContainer *generic_container;
- int index;
-
- index = mono_metadata_decode_value (ptr, &ptr);
+ int index = mono_metadata_decode_value (ptr, &ptr);
if (rptr)
*rptr = ptr;
- g_assert (generic_context);
- if (generic_context->gmethod)
- generic_container = generic_context->gmethod->container;
- else if (generic_context->gclass)
- generic_container = generic_context->gclass->container_class->generic_container;
- else
- generic_container = generic_context->container;
+ generic_container = select_container (generic_container, type);
+ if (!generic_container) {
+ /* Create dummy MonoGenericParam */
+ MonoGenericParam *param = g_new0 (MonoGenericParam, 1);
+ param->name = g_strdup_printf ("%d", index);
+ param->num = index;
- if (!is_mvar) {
- g_assert (generic_container);
- if (generic_container->parent) {
- /*
- * The current MonoGenericContainer is a generic method -> its `parent'
- * points to the containing class'es container.
- */
- generic_container = generic_container->parent;
- }
- g_assert (generic_container && !generic_container->is_method);
- g_assert (index < generic_container->type_argc);
-
- return &generic_container->type_params [index];
- } else {
- g_assert (generic_container && (generic_container->is_method || generic_container->is_signature));
- g_assert (index < generic_container->type_argc);
-
- return &generic_container->type_params [index];
+ return param;
}
+
+ g_assert (index < generic_container->type_argc);
+ return &generic_container->type_params [index];
}
/*
* do_mono_metadata_parse_type:
* @type: MonoType to be filled in with the return value
- * @
+ * @m: image context
+ * @generic_context: generics_context
+ * @ptr: pointer to the encoded type
+ * @rptr: pointer where the end of the encoded type is saved
+ *
* Internal routine used to "fill" the contents of @type from an
* allocated pointer. This is done this way to avoid doing too
* many mini-allocations (particularly for the MonoFieldType which
* mono_metadata_parse_field_type
*
* This extracts a Type as specified in Partition II (22.2.12)
+ *
+ * Returns: FALSE if the type could not be loaded
*/
-static void
-do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContext *generic_context,
+static gboolean
+do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container,
const char *ptr, const char **rptr)
{
+ gboolean ok = TRUE;
type->type = mono_metadata_decode_value (ptr, &ptr);
switch (type->type){
guint32 token;
token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr);
type->data.klass = mono_class_get (m, token);
+ if (!type->data.klass)
+ return FALSE;
break;
}
case MONO_TYPE_SZARRAY: {
- MonoType *etype = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
+ MonoType *etype = mono_metadata_parse_type_full (m, container, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
+ if (!etype)
+ return FALSE;
type->data.klass = mono_class_from_mono_type (etype);
mono_metadata_free_type (etype);
break;
}
case MONO_TYPE_PTR:
- type->data.type = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
+ type->data.type = mono_metadata_parse_type_full (m, container, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
+ if (!type->data.type)
+ return FALSE;
break;
case MONO_TYPE_FNPTR:
- type->data.method = mono_metadata_parse_method_signature_full (m, generic_context, 0, ptr, &ptr);
+ type->data.method = mono_metadata_parse_method_signature_full (m, container, 0, ptr, &ptr);
break;
case MONO_TYPE_ARRAY:
- type->data.array = mono_metadata_parse_array_full (m, generic_context, ptr, &ptr);
+ type->data.array = mono_metadata_parse_array_full (m, container, ptr, &ptr);
break;
-
case MONO_TYPE_MVAR:
- type->data.generic_param = mono_metadata_parse_generic_param (m, generic_context, TRUE, ptr, &ptr);
- break;
-
case MONO_TYPE_VAR:
- type->data.generic_param = mono_metadata_parse_generic_param (m, generic_context, FALSE, ptr, &ptr);
+ type->data.generic_param = mono_metadata_parse_generic_param (m, container, type->type, ptr, &ptr);
break;
-
case MONO_TYPE_GENERICINST:
- do_mono_metadata_parse_generic_class (type, m, generic_context, ptr, &ptr);
+ ok = do_mono_metadata_parse_generic_class (type, m, container, ptr, &ptr);
break;
-
default:
g_error ("type 0x%02x not handled in do_mono_metadata_parse_type", type->type);
}
if (rptr)
*rptr = ptr;
+ return ok;
}
/*
* mono_metadata_free_type:
* @type: type to free
*
- * Free the memory allocated for type @type.
+ * Free the memory allocated for type @type which is assumed to be created by
+ * mono_metadata_parse_type ().
*/
void
mono_metadata_free_type (MonoType *type)
mono_metadata_free_array (type->data.array);
break;
}
- g_free (type);
+
+ /* Allocated from a mempool, no need to free it */
}
#if 0
int i;
mh->num_clauses = is_fat ? sect_data_len / 24: sect_data_len / 12;
/* we could just store a pointer if we don't need to byteswap */
- mh->clauses = g_new0 (MonoExceptionClause, mh->num_clauses);
+ mh->clauses = mono_mempool_alloc0 (m->mempool, sizeof (MonoExceptionClause) * mh->num_clauses);
for (i = 0; i < mh->num_clauses; ++i) {
MonoExceptionClause *ec = &mh->clauses [i];
guint32 tof_value;
if (is_fat) {
ec->flags = read32 (p);
- p += 4;
- ec->try_offset = read32 (p);
- p += 4;
- ec->try_len = read32 (p);
- p += 4;
- ec->handler_offset = read32 (p);
- p += 4;
- ec->handler_len = read32 (p);
- p += 4;
- tof_value = read32 (p);
- p += 4;
+ ec->try_offset = read32 (p + 4);
+ ec->try_len = read32 (p + 8);
+ ec->handler_offset = read32 (p + 12);
+ ec->handler_len = read32 (p + 16);
+ tof_value = read32 (p + 20);
+ p += 24;
} else {
ec->flags = read16 (p);
- p += 2;
- ec->try_offset = read16 (p);
- p += 2;
- ec->try_len = *p;
- ++p;
- ec->handler_offset = read16 (p);
- p += 2;
- ec->handler_len = *p;
- ++p;
- tof_value = read32 (p);
- p += 4;
+ ec->try_offset = read16 (p + 2);
+ ec->try_len = *(p + 4);
+ ec->handler_offset = read16 (p + 5);
+ ec->handler_len = *(p + 7);
+ tof_value = read32 (p + 8);
+ p += 12;
}
if (ec->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
ec->data.filter_offset = tof_value;
}
/*
- * mono_metadata_parse_mh:
+ * mono_metadata_parse_mh_full:
* @m: metadata context
+ * @generic_context: generics context
* @ptr: pointer to the method header.
*
* Decode the method header at @ptr, including pointer to the IL code,
* info about local variables and optional exception tables.
+ * This is a Mono runtime internal function.
*
- * Returns: a MonoMethodHeader.
+ * LOCKING: Assumes the loader lock is held.
+ *
+ * Returns: a MonoMethodHeader allocated from the image mempool.
*/
MonoMethodHeader *
-mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContext *generic_context, const char *ptr)
+mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, const char *ptr)
{
MonoMethodHeader *mh;
unsigned char flags = *(const unsigned char *) ptr;
g_return_val_if_fail (ptr != NULL, NULL);
- switch (format){
+ mono_loader_lock ();
+ switch (format) {
case METHOD_HEADER_TINY_FORMAT:
- mh = g_new0 (MonoMethodHeader, 1);
+ mh = mono_mempool_alloc0 (m->mempool, sizeof (MonoMethodHeader));
ptr++;
mh->max_stack = 8;
local_var_sig_tok = 0;
mh->code_size = flags >> 2;
mh->code = ptr;
+ mono_loader_unlock ();
return mh;
case METHOD_HEADER_TINY_FORMAT1:
- mh = g_new0 (MonoMethodHeader, 1);
+ mh = mono_mempool_alloc0 (m->mempool, sizeof (MonoMethodHeader));
ptr++;
mh->max_stack = 8;
local_var_sig_tok = 0;
*/
mh->code_size = flags >> 2;
mh->code = ptr;
+ mono_loader_unlock ();
return mh;
case METHOD_HEADER_FAT_FORMAT:
fat_flags = read16 (ptr);
* There are more sections
*/
ptr = code + code_size;
-
break;
-
default:
+ mono_loader_unlock ();
return NULL;
}
g_warning ("wrong signature for locals blob");
locals_ptr++;
len = mono_metadata_decode_value (locals_ptr, &locals_ptr);
- mh = g_malloc0 (sizeof (MonoMethodHeader) + (len - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
+ mh = mono_mempool_alloc0 (m->mempool, sizeof (MonoMethodHeader) + (len - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
mh->num_locals = len;
- for (i = 0; i < len; ++i)
+ for (i = 0; i < len; ++i) {
mh->locals [i] = mono_metadata_parse_type_full (
- m, generic_context, MONO_PARSE_LOCAL, 0, locals_ptr, &locals_ptr);
+ m, container, MONO_PARSE_LOCAL, 0, locals_ptr, &locals_ptr);
+ if (!mh->locals [i]) {
+ mono_loader_unlock ();
+ return NULL;
+ }
+ }
} else {
- mh = g_new0 (MonoMethodHeader, 1);
+ mh = mono_mempool_alloc0 (m->mempool, sizeof (MonoMethodHeader));
}
mh->code = code;
mh->code_size = code_size;
mh->init_locals = init_locals;
if (fat_flags & METHOD_HEADER_MORE_SECTS)
parse_section_data (m, mh, (const unsigned char*)ptr);
+ mono_loader_unlock ();
return mh;
}
+/*
+ * mono_metadata_parse_mh:
+ * @generic_context: generics context
+ * @ptr: pointer to the method header.
+ *
+ * Decode the method header at @ptr, including pointer to the IL code,
+ * info about local variables and optional exception tables.
+ * This is a Mono runtime internal function.
+ *
+ * Returns: a MonoMethodHeader.
+ */
MonoMethodHeader *
mono_metadata_parse_mh (MonoImage *m, const char *ptr)
{
- return mono_metadata_parse_mh_full (m, NULL, ptr);
+ MonoMethodHeader *res;
+
+ mono_loader_lock ();
+
+ res = mono_metadata_parse_mh_full (m, NULL, ptr);
+
+ mono_loader_unlock ();
+
+ return res;
}
/*
* @mh: a method header
*
* Free the memory allocated for the method header.
+ * This is a Mono runtime internal function.
*/
void
mono_metadata_free_mh (MonoMethodHeader *mh)
{
- int i;
- for (i = 0; i < mh->num_locals; ++i)
- mono_metadata_free_type (mh->locals[i]);
- g_free (mh->clauses);
- g_free (mh);
+ /* Allocated from the mempool */
+}
+
+/*
+ * mono_method_header_get_code:
+ * @header: a MonoMethodHeader pointer
+ * @code_size: memory location for returning the code size
+ * @max_stack: memory location for returning the max stack
+ *
+ * Method header accessor to retreive info about the IL code properties:
+ * a pointer to the IL code itself, the size of the code and the max number
+ * of stack slots used by the code.
+ *
+ * Returns: pointer to the IL code represented by the method header.
+ */
+const unsigned char*
+mono_method_header_get_code (MonoMethodHeader *header, guint32* code_size, guint32* max_stack)
+{
+ if (code_size)
+ *code_size = header->code_size;
+ if (max_stack)
+ *max_stack = header->max_stack;
+ return header->code;
+}
+
+/*
+ * mono_method_header_get_locals:
+ * @header: a MonoMethodHeader pointer
+ * @num_locals: memory location for returning the number of local variables
+ * @init_locals: memory location for returning the init_locals flag
+ *
+ * Method header accessor to retreive info about the local variables:
+ * an array of local types, the number of locals and whether the locals
+ * are supposed to be initialized to 0 on method entry
+ *
+ * Returns: pointer to an array of types of the local variables
+ */
+MonoType**
+mono_method_header_get_locals (MonoMethodHeader *header, guint32* num_locals, gboolean *init_locals)
+{
+ if (num_locals)
+ *num_locals = header->num_locals;
+ if (init_locals)
+ *init_locals = header->init_locals;
+ return header->locals;
+}
+
+/*
+ * mono_method_header_get_num_clauses:
+ * @header: a MonoMethodHeader pointer
+ *
+ * Method header accessor to retreive the number of exception clauses.
+ *
+ * Returns: the number of exception clauses present
+ */
+int
+mono_method_header_get_num_clauses (MonoMethodHeader *header)
+{
+ return header->num_clauses;
+}
+
+/*
+ * mono_method_header_get_clauses:
+ * @header: a MonoMethodHeader pointer
+ * @method: MonoMethod the header belongs to
+ * @iter: pointer to a iterator
+ * @clause: pointer to a MonoExceptionClause structure which will be filled with the info
+ *
+ * Get the info about the exception clauses in the method. Set *iter to NULL to
+ * initiate the iteration, then call the method repeatedly until it returns FALSE.
+ * At each iteration, the structure pointed to by clause if filled with the
+ * exception clause information.
+ *
+ * Returns: TRUE if clause was filled with info, FALSE if there are no more exception
+ * clauses.
+ */
+int
+mono_method_header_get_clauses (MonoMethodHeader *header, MonoMethod *method, gpointer *iter, MonoExceptionClause *clause)
+{
+ MonoExceptionClause *sc;
+ /* later we'll be able to use this interface to parse the clause info on demand,
+ * without allocating anything.
+ */
+ if (!iter || !header->num_clauses)
+ return FALSE;
+ if (!*iter) {
+ *iter = sc = header->clauses;
+ *clause = *sc;
+ return TRUE;
+ }
+ sc = *iter;
+ sc++;
+ if (sc < header->clauses + header->num_clauses) {
+ *iter = sc;
+ *clause = *sc;
+ return TRUE;
+ }
+ return FALSE;
}
/**
switch (table){
case 0: /* TypeDef */
return MONO_TOKEN_TYPE_DEF | idx;
-
case 1: /* TypeRef */
return MONO_TOKEN_TYPE_REF | idx;
-
case 2: /* TypeSpec */
return MONO_TOKEN_TYPE_SPEC | idx;
-
default:
g_assert_not_reached ();
}
return 1;
}
+/**
+ * search_ptr_table:
+ *
+ * Return the 1-based row index in TABLE, which must be one of the *Ptr tables,
+ * which contains IDX.
+ */
+static guint32
+search_ptr_table (MonoImage *image, int table, int idx)
+{
+ MonoTableInfo *ptrdef = &image->tables [table];
+ int i;
+
+ /* Use a linear search to find our index in the table */
+ for (i = 0; i < ptrdef->rows; i ++)
+ /* All the Ptr tables have the same structure */
+ if (mono_metadata_decode_row_col (ptrdef, i, 0) == idx)
+ break;
+
+ if (i < ptrdef->rows)
+ return i + 1;
+ else
+ return idx;
+}
+
/**
* mono_metadata_typedef_from_field:
* @meta: metadata context
loc.col_idx = MONO_TYPEDEF_FIELD_LIST;
loc.t = tdef;
+ if (meta->uncompressed_metadata)
+ loc.idx = search_ptr_table (meta, MONO_TABLE_FIELD_POINTER, loc.idx);
+
if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
g_assert_not_reached ();
loc.col_idx = MONO_TYPEDEF_METHOD_LIST;
loc.t = tdef;
+ if (meta->uncompressed_metadata)
+ loc.idx = search_ptr_table (meta, MONO_TABLE_METHOD_POINTER, loc.idx);
+
if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
g_assert_not_reached ();
}
/*
- * mono_metadata_interfaces_from_typedef:
+ * mono_metadata_interfaces_from_typedef_full:
* @meta: metadata context
* @index: typedef token
*
- * Returns: and array of interfaces that the @index typedef token implements.
- * The number of elemnts in the array is returned in @count.
+ * The array of interfaces that the @index typedef token implements is returned in
+ * @interfaces. The number of elemnts in the array is returned in @count.
+ *
+ * LOCKING: Assumes the loader lock is held.
+ *
+ * Returns: TRUE on success, FALSE on failure.
*/
-MonoClass**
-mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, guint *count, MonoGenericContext *context)
+gboolean
+mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, MonoClass ***interfaces, guint *count, MonoGenericContext *context)
{
MonoTableInfo *tdef = &meta->tables [MONO_TABLE_INTERFACEIMPL];
locator_t loc;
- guint32 start, i;
+ guint32 start, pos;
guint32 cols [MONO_INTERFACEIMPL_SIZE];
MonoClass **result;
-
+
+ *interfaces = NULL;
*count = 0;
if (!tdef->base)
- return NULL;
+ return TRUE;
loc.idx = mono_metadata_token_index (index);
loc.col_idx = MONO_INTERFACEIMPL_CLASS;
loc.t = tdef;
if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
- return NULL;
+ return TRUE;
start = loc.result;
/*
else
break;
}
- result = NULL;
- i = 0;
- while (start < tdef->rows) {
- mono_metadata_decode_row (tdef, start, cols, MONO_INTERFACEIMPL_SIZE);
+ pos = start;
+ while (pos < tdef->rows) {
+ mono_metadata_decode_row (tdef, pos, cols, MONO_INTERFACEIMPL_SIZE);
+ if (cols [MONO_INTERFACEIMPL_CLASS] != loc.idx)
+ break;
+ ++pos;
+ }
+
+ mono_loader_lock ();
+ result = mono_mempool_alloc0 (meta->mempool, sizeof (MonoClass*) * (pos - start));
+ mono_loader_unlock ();
+
+ pos = start;
+ while (pos < tdef->rows) {
+ MonoClass *iface;
+
+ mono_metadata_decode_row (tdef, pos, cols, MONO_INTERFACEIMPL_SIZE);
if (cols [MONO_INTERFACEIMPL_CLASS] != loc.idx)
break;
- result = g_renew (MonoClass*, result, i + 1);
- result [i] = mono_class_get_full (
+ iface = mono_class_get_full (
meta, mono_metadata_token_from_dor (cols [MONO_INTERFACEIMPL_INTERFACE]), context);
- *count = ++i;
- ++start;
+ if (iface == NULL)
+ return FALSE;
+ result [pos - start] = iface;
+ ++pos;
}
- return result;
+ *count = pos - start;
+ *interfaces = result;
+ return TRUE;
}
MonoClass**
mono_metadata_interfaces_from_typedef (MonoImage *meta, guint32 index, guint *count)
{
- return mono_metadata_interfaces_from_typedef_full (meta, index, count, NULL);
+ MonoClass **interfaces;
+ gboolean rv;
+
+ mono_loader_lock ();
+ rv = mono_metadata_interfaces_from_typedef_full (meta, index, &interfaces, count, NULL);
+ mono_loader_unlock ();
+ if (rv)
+ return interfaces;
+ else
+ return NULL;
}
/*
loc.col_idx = MONO_CUSTOM_ATTR_PARENT;
loc.t = tdef;
+ /* FIXME: Index translation */
+
if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
return 0;
* type in memory
*/
int
-mono_type_size (MonoType *t, gint *align)
+mono_type_size (MonoType *t, int *align)
{
if (!t) {
*align = 1;
case MONO_TYPE_TYPEDBYREF:
return mono_class_value_size (mono_defaults.typed_reference_class, align);
case MONO_TYPE_GENERICINST: {
- MonoGenericClass *gclass = t->data.generic_class;
+ MonoInflatedGenericClass *gclass;
+ MonoClass *container_class;
- g_assert (!gclass->inst->is_open && !gclass->klass->generic_container);
+ gclass = mono_get_inflated_generic_class (t->data.generic_class);
+ // g_assert (!gclass->generic_class.inst->is_open);
+ // g_assert (!gclass->klass->generic_container);
- if (gclass->container_class->valuetype) {
- if (gclass->container_class->enumtype)
- return mono_type_size (gclass->container_class->enum_basetype, align);
+ container_class = gclass->generic_class.container_class;
+
+ if (container_class->valuetype) {
+ if (container_class->enumtype)
+ return mono_type_size (container_class->enum_basetype, align);
else
return mono_class_value_size (gclass->klass, align);
} else {
}
case MONO_TYPE_VAR:
case MONO_TYPE_MVAR:
+ /* FIXME: Martin, this is wrong. */
*align = __alignof__(gpointer);
return sizeof (gpointer);
default:
* type on the runtime stack
*/
int
-mono_type_stack_size (MonoType *t, gint *align)
+mono_type_stack_size (MonoType *t, int *align)
{
- int tmp;
+ guint32 tmp;
g_assert (t != NULL);
}
}
case MONO_TYPE_GENERICINST: {
- MonoGenericClass *gclass = t->data.generic_class;
+ MonoInflatedGenericClass *gclass;
+ MonoClass *container_class;
+
+ gclass = mono_get_inflated_generic_class (t->data.generic_class);
+ container_class = gclass->generic_class.container_class;
- g_assert (!gclass->inst->is_open && !gclass->klass->generic_container);
+ g_assert (!gclass->generic_class.inst->is_open);
+ g_assert (!gclass->klass->generic_container);
- if (gclass->container_class->valuetype) {
- if (gclass->container_class->enumtype)
- return mono_type_stack_size (gclass->container_class->enum_basetype, align);
+ if (container_class->valuetype) {
+ if (container_class->enumtype)
+ return mono_type_stack_size (container_class->enum_basetype, align);
else {
guint32 size = mono_class_value_size (gclass->klass, align);
return 0;
}
+gboolean
+mono_type_generic_inst_is_valuetype (MonoType *type)
+{
+ g_assert (type->type == MONO_TYPE_GENERICINST);
+ return type->data.generic_class->container_class->valuetype;
+}
+
gboolean
mono_metadata_generic_class_is_valuetype (MonoGenericClass *gclass)
{
gboolean
mono_metadata_generic_method_equal (MonoGenericMethod *g1, MonoGenericMethod *g2)
{
- return (g1->container == g2->container) && (g1->inst == g2->inst);
+ return (g1->container == g2->container) && (g1->generic_class == g2->generic_class) &&
+ (g1->inst == g2->inst);
}
if (p1->num != p2->num)
return FALSE;
- g_assert (p1->owner && p2->owner);
if (p1->owner == p2->owner)
return TRUE;
return _mono_metadata_generic_class_equal (c1->generic_class, c2->generic_class, signature_only);
if ((c1->byval_arg.type == MONO_TYPE_VAR) && (c2->byval_arg.type == MONO_TYPE_VAR))
return mono_metadata_generic_param_equal (
- c1->byval_arg.data.generic_param, c2->byval_arg.data.generic_param, FALSE);
+ c1->byval_arg.data.generic_param, c2->byval_arg.data.generic_param, signature_only);
if ((c1->byval_arg.type == MONO_TYPE_MVAR) && (c2->byval_arg.type == MONO_TYPE_MVAR))
return mono_metadata_generic_param_equal (
c1->byval_arg.data.generic_param, c2->byval_arg.data.generic_param, signature_only);
+ if (signature_only &&
+ (c1->byval_arg.type == MONO_TYPE_SZARRAY) && (c2->byval_arg.type == MONO_TYPE_SZARRAY))
+ return mono_metadata_class_equal (c1->byval_arg.data.klass, c2->byval_arg.data.klass, signature_only);
return FALSE;
}
+static gboolean
+mono_metadata_fnptr_equal (MonoMethodSignature *s1, MonoMethodSignature *s2, gboolean signature_only)
+{
+ gpointer iter1 = 0, iter2 = 0;
+
+ if (s1 == s2)
+ return TRUE;
+ if (s1->call_convention != s2->call_convention)
+ return FALSE;
+ if (s1->sentinelpos != s2->sentinelpos)
+ return FALSE;
+ if (s1->hasthis != s2->hasthis)
+ return FALSE;
+ if (s1->explicit_this != s2->explicit_this)
+ return FALSE;
+ if (! do_mono_metadata_type_equal (s1->ret, s2->ret, signature_only))
+ return FALSE;
+ if (s1->param_count != s2->param_count)
+ return FALSE;
+
+ while (TRUE) {
+ MonoType *t1 = mono_signature_get_params (s1, &iter1);
+ MonoType *t2 = mono_signature_get_params (s2, &iter2);
+
+ if (t1 == NULL || t2 == NULL)
+ return (t1 == t2);
+ if (! do_mono_metadata_type_equal (t1, t2, signature_only))
+ return FALSE;
+ }
+}
+
/*
* mono_metadata_type_equal:
* @t1: a type
static gboolean
do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only)
{
- if (t1->type != t2->type ||
- t1->byref != t2->byref)
+ if (t1->type != t2->type || t1->byref != t2->byref)
return FALSE;
switch (t1->type) {
t1->data.generic_class, t2->data.generic_class, signature_only);
case MONO_TYPE_VAR:
return mono_metadata_generic_param_equal (
- t1->data.generic_param, t2->data.generic_param, FALSE);
+ t1->data.generic_param, t2->data.generic_param, signature_only);
case MONO_TYPE_MVAR:
return mono_metadata_generic_param_equal (
t1->data.generic_param, t2->data.generic_param, signature_only);
+ case MONO_TYPE_FNPTR:
+ return mono_metadata_fnptr_equal (t1->data.method, t2->data.method, signature_only);
default:
g_error ("implement type compare for %0x!", t1->type);
return FALSE;
{
int i;
- if (sig1->hasthis != sig2->hasthis ||
- sig1->param_count != sig2->param_count)
+ if (sig1->hasthis != sig2->hasthis || sig1->param_count != sig2->param_count)
return FALSE;
/*
return TRUE;
}
+/**
+ * mono_metadata_type_dup_mp:
+ * @image: image type is defined in
+ * @original: type to duplicate
+ *
+ * Returns: copy of type allocated from mempool.
+ */
+MonoType *
+mono_metadata_type_dup_mp (MonoImage *image, const MonoType *original)
+{
+ MonoType *r = NULL;
+ mono_loader_lock ();
+ r = mono_mempool_alloc0 (image->mempool, sizeof(MonoType));
+ mono_loader_unlock ();
+ *r = *original;
+ /* FIXME: we don't handle these yet because they need to duplicate memory
+ * but the current routines used are not using the mempools
+ */
+ if (original->type == MONO_TYPE_PTR ||
+ original->type == MONO_TYPE_ARRAY ||
+ original->type == MONO_TYPE_FNPTR)
+ g_assert_not_reached ();
+ return r;
+}
+
guint
mono_signature_hash (MonoMethodSignature *sig)
{
guint i, res = sig->ret->type;
for (i = 0; i < sig->param_count; i++)
- res = (res << 5) - res + sig->params[i]->type;
+ res = (res << 5) - res + mono_type_hash (sig->params[i]);
return res;
}
locator_t loc;
loc.idx = index + 1;
+ if (meta->uncompressed_metadata)
+ loc.idx = search_ptr_table (meta, MONO_TABLE_FIELD_POINTER, loc.idx);
+
if (offset) {
tdef = &meta->tables [MONO_TABLE_FIELDLAYOUT];
loc.col_idx = MONO_CONSTANT_PARENT;
loc.t = tdef;
+ /* FIXME: Index translation */
+
if ((hint > 0) && (hint < tdef->rows) && (mono_metadata_decode_row_col (tdef, hint - 1, MONO_CONSTANT_PARENT) == index))
return hint;
if (!msemt->base)
return 0;
+ if (meta->uncompressed_metadata)
+ index = search_ptr_table (meta, MONO_TABLE_EVENT_POINTER, index + 1) - 1;
+
loc.t = msemt;
loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION;
loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT; /* Method association coded index */
if (!msemt->base)
return 0;
+ if (meta->uncompressed_metadata)
+ index = search_ptr_table (meta, MONO_TABLE_PROPERTY_POINTER, index + 1) - 1;
+
loc.t = msemt;
loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION;
loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY; /* Method association coded index */
if (!tdef->base)
return 0;
+ /* No index translation seems to be needed */
+
loc.t = tdef;
loc.col_idx = MONO_IMPLMAP_MEMBER;
loc.idx = ((method_idx + 1) << MONO_MEMBERFORWD_BITS) | MONO_MEMBERFORWD_METHODDEF;
* token.
*/
MonoType *
-mono_type_create_from_typespec_full (MonoImage *image, MonoGenericContext *generic_context, guint32 type_spec)
+mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
{
guint32 idx = mono_metadata_token_index (type_spec);
MonoTableInfo *t;
- guint32 cols [MONO_TYPESPEC_SIZE];
+ guint32 cols [MONO_TYPESPEC_SIZE];
const char *ptr;
guint32 len;
MonoType *type;
mono_loader_lock ();
- if ((type = g_hash_table_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec)))) {
+ type = g_hash_table_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec));
+ if (type) {
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);
g_hash_table_insert (image->typespec_cache, GUINT_TO_POINTER (type_spec), type);
if (*ptr == MONO_TYPE_BYREF) {
- type->byref = 1;
+ type->byref = 1;
ptr++;
}
- do_mono_metadata_parse_type (type, image, generic_context, ptr, &ptr);
+ if (!do_mono_metadata_parse_type (type, image, NULL, ptr, &ptr)) {
+ g_hash_table_remove (image->typespec_cache, GUINT_TO_POINTER (type_spec));
+ g_free (type);
+ mono_loader_unlock ();
+ return NULL;
+ }
mono_loader_unlock ();
return type;
}
-MonoType *
-mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
-{
- return mono_type_create_from_typespec_full (image, NULL, type_spec);
-}
-
MonoMarshalSpec *
mono_metadata_parse_marshal_spec (MonoImage *image, const char *ptr)
{
res->data.custom_data.cookie = g_strndup (ptr, len);
}
+ if (res->native == MONO_NATIVE_SAFEARRAY) {
+ res->data.safearray_data.elem_type = 0;
+ res->data.safearray_data.num_elem = 0;
+ if (ptr - start <= len)
+ res->data.safearray_data.elem_type = *ptr++;
+ if (ptr - start <= len)
+ res->data.safearray_data.num_elem = *ptr++;
+ }
return res;
}
if (mspec) {
switch (mspec->native) {
case MONO_NATIVE_BYVALARRAY:
- *conv = MONO_MARSHAL_CONV_ARRAY_BYVALARRAY;
+ if ((type->data.klass->element_class == mono_defaults.char_class) && !unicode)
+ *conv = MONO_MARSHAL_CONV_ARRAY_BYVALCHARARRAY;
+ else
+ *conv = MONO_MARSHAL_CONV_ARRAY_BYVALARRAY;
return MONO_NATIVE_BYVALARRAY;
case MONO_NATIVE_SAFEARRAY:
*conv = MONO_MARSHAL_CONV_ARRAY_SAVEARRAY;
*conv = MONO_MARSHAL_CONV_DEL_FTN;
return MONO_NATIVE_FUNC;
}
- else
- /* Fall through */
- ;
+ /* Fall through */
default:
g_error ("cant marshal object as native type %02x", mspec->native);
}
loc.col_idx = MONO_FIELD_MARSHAL_PARENT;
loc.idx = ((idx + 1) << MONO_HAS_FIELD_MARSHAL_BITS) | (is_field? MONO_HAS_FIELD_MARSHAL_FIELDSREF: MONO_HAS_FIELD_MARSHAL_PARAMDEF);
+ /* FIXME: Index translation */
+
if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
return NULL;
}
static MonoMethod*
-method_from_method_def_or_ref (MonoImage *m, guint32 tok)
+method_from_method_def_or_ref (MonoImage *m, guint32 tok, MonoGenericContext *context)
{
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);
+ return mono_get_method_full (m, MONO_TOKEN_METHOD_DEF | idx, NULL, context);
case MONO_METHODDEFORREF_METHODREF:
- return mono_get_method (m, MONO_TOKEN_MEMBER_REF | idx, NULL);
+ return mono_get_method_full (m, MONO_TOKEN_MEMBER_REF | idx, NULL, context);
}
g_assert_not_reached ();
return NULL;
}
-MonoMethod**
-mono_class_get_overrides (MonoImage *image, guint32 type_token, gint32 *num_overrides)
+/*
+ * mono_class_get_overrides_full:
+ *
+ * Return the method overrides belonging to class @type_token in @overrides, and
+ * the number of overrides in @num_overrides.
+ *
+ * Returns: TRUE on success, FALSE on failure.
+ */
+gboolean
+mono_class_get_overrides_full (MonoImage *image, guint32 type_token, MonoMethod ***overrides, gint32 *num_overrides,
+ MonoGenericContext *generic_context)
{
locator_t loc;
MonoTableInfo *tdef = &image->tables [MONO_TABLE_METHODIMPL];
gint32 i, num;
guint32 cols [MONO_METHODIMPL_SIZE];
MonoMethod **result;
-
+ gint32 ok = TRUE;
+
+ *overrides = NULL;
if (num_overrides)
*num_overrides = 0;
if (!tdef->base)
- return NULL;
+ return TRUE;
loc.t = tdef;
loc.col_idx = MONO_METHODIMPL_CLASS;
loc.idx = mono_metadata_token_index (type_token);
if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
- return NULL;
+ return TRUE;
start = loc.result;
end = start + 1;
num = end - start;
result = g_new (MonoMethod*, num * 2);
for (i = 0; i < num; ++i) {
+ MonoMethod *method;
+
mono_metadata_decode_row (tdef, start + i, cols, MONO_METHODIMPL_SIZE);
- result [i * 2] = method_from_method_def_or_ref (image, cols [MONO_METHODIMPL_DECLARATION]);
- result [i * 2 + 1] = method_from_method_def_or_ref (image, cols [MONO_METHODIMPL_BODY]);
+ method = method_from_method_def_or_ref (
+ image, cols [MONO_METHODIMPL_DECLARATION], generic_context);
+ if (method == NULL)
+ ok = FALSE;
+ result [i * 2] = method;
+ method = method_from_method_def_or_ref (
+ image, cols [MONO_METHODIMPL_BODY], generic_context);
+ if (method == NULL)
+ ok = FALSE;
+ result [i * 2 + 1] = method;
}
+ *overrides = result;
if (num_overrides)
*num_overrides = num;
- return result;
+ return ok;
}
/**
guid[10], guid[11], guid[12], guid[13], guid[14], guid[15]);
}
-static MonoClass**
-get_constraints (MonoImage *image, int owner, MonoGenericContext *context)
+static gboolean
+get_constraints (MonoImage *image, int owner, MonoClass ***constraints, MonoGenericContainer *container)
{
MonoTableInfo *tdef = &image->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
guint32 cols [MONO_GENPARCONSTRAINT_SIZE];
guint32 i, token, found;
MonoClass *klass, **res;
GList *cons = NULL, *tmp;
-
+ MonoGenericContext *context = &container->context;
+
+ /* FIXME: !container->klass => this is probably monodis */
+ g_assert (!container->klass || context->gclass || context->gmethod);
+ *constraints = NULL;
found = 0;
for (i = 0; i < tdef->rows; ++i) {
mono_metadata_decode_row (tdef, i, cols, MONO_GENPARCONSTRAINT_SIZE);
}
}
if (!found)
- return NULL;
+ return TRUE;
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;
+ *constraints = res;
+ return TRUE;
}
-gboolean
-mono_metadata_has_generic_params (MonoImage *image, guint32 token)
+/*
+ * mono_metadata_get_generic_param_row:
+ *
+ * @image:
+ * @token: TypeOrMethodDef token, owner for GenericParam
+ * @owner: coded token, set on return
+ *
+ * Returns: 1-based row-id in the GenericParam table whose
+ * owner is @token. 0 if not found.
+ */
+guint32
+mono_metadata_get_generic_param_row (MonoImage *image, guint32 token, guint32 *owner)
{
MonoTableInfo *tdef = &image->tables [MONO_TABLE_GENERICPARAM];
guint32 cols [MONO_GENERICPARAM_SIZE];
- guint32 i, owner = 0;
+ guint32 i;
+
+ g_assert (owner);
+ if (!tdef->base)
+ return 0;
if (mono_metadata_token_table (token) == MONO_TABLE_TYPEDEF)
- owner = MONO_TYPEORMETHOD_TYPE;
+ *owner = MONO_TYPEORMETHOD_TYPE;
else if (mono_metadata_token_table (token) == MONO_TABLE_METHOD)
- owner = MONO_TYPEORMETHOD_METHOD;
+ *owner = MONO_TYPEORMETHOD_METHOD;
else {
- g_error ("wrong token %x to load_generics_params", token);
- return FALSE;
+ g_error ("wrong token %x to get_generic_param_row", token);
+ return 0;
}
- owner |= mono_metadata_token_index (token) << MONO_TYPEORMETHOD_BITS;
- if (!tdef->base)
- return FALSE;
+ *owner |= mono_metadata_token_index (token) << MONO_TYPEORMETHOD_BITS;
for (i = 0; i < tdef->rows; ++i) {
mono_metadata_decode_row (tdef, i, cols, MONO_GENERICPARAM_SIZE);
- if (cols [MONO_GENERICPARAM_OWNER] == owner)
- break;
+ if (cols [MONO_GENERICPARAM_OWNER] == *owner)
+ return i + 1;
}
- if (i >= tdef->rows)
- return FALSE;
- return TRUE;
+ return 0;
+}
+
+gboolean
+mono_metadata_has_generic_params (MonoImage *image, guint32 token)
+{
+ guint32 owner;
+ return mono_metadata_get_generic_param_row (image, token, &owner);
+}
+
+/*
+ * mono_metadata_load_generic_param_constraints:
+ *
+ * Load the generic parameter constraints for the newly created generic type or method
+ * represented by @token and @container. The @container is the new container which has
+ * been returned by a call to mono_metadata_load_generic_params() with this @token.
+ */
+void
+mono_metadata_load_generic_param_constraints (MonoImage *image, guint32 token,
+ MonoGenericContainer *container)
+{
+ guint32 start_row, i, owner;
+ if (! (start_row = mono_metadata_get_generic_param_row (image, token, &owner)))
+ return;
+ for (i = 0; i < container->type_argc; i++)
+ get_constraints (image, start_row + i, &container->type_params [i].constraints, container);
}
+/*
+ * mono_metadata_load_generic_params:
+ *
+ * Load the type parameters from the type or method definition @token.
+ *
+ * Use this method after parsing a type or method definition to figure out whether it's a generic
+ * type / method. When parsing a method definition, @parent_container points to the generic container
+ * of the current class, if any.
+ *
+ * Note: This method does not load the constraints: for typedefs, this has to be done after fully
+ * creating the type.
+ *
+ * Returns: NULL if @token is not a generic type or method definition or the new generic container.
+ *
+ */
MonoGenericContainer *
mono_metadata_load_generic_params (MonoImage *image, guint32 token, MonoGenericContainer *parent_container)
{
MonoTableInfo *tdef = &image->tables [MONO_TABLE_GENERICPARAM];
guint32 cols [MONO_GENERICPARAM_SIZE];
- guint32 i, owner = 0, last_num, n;
+ guint32 i, owner = 0, n;
MonoGenericContainer *container;
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);
- return NULL;
- }
- owner |= mono_metadata_token_index (token) << MONO_TYPEORMETHOD_BITS;
- 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 = i;
- if (i >= tdef->rows)
+ if (!(i = mono_metadata_get_generic_param_row (image, token, &owner)))
return NULL;
+ mono_metadata_decode_row (tdef, i - 1, cols, MONO_GENERICPARAM_SIZE);
params = NULL;
n = 0;
container = g_new0 (MonoGenericContainer, 1);
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]);
- if (++i >= tdef->rows)
+ params [n - 1].constraints = NULL;
+ if (++i > tdef->rows)
break;
- mono_metadata_decode_row (tdef, i, cols, MONO_GENERICPARAM_SIZE);
+ mono_metadata_decode_row (tdef, i - 1, cols, MONO_GENERICPARAM_SIZE);
} while (cols [MONO_GENERICPARAM_OWNER] == owner);
container->type_argc = n;
container->context.container = container;
- for (i = 0; i < n; i++)
- params [i].constraints = get_constraints (image, last_num + i + 1, &container->context);
-
return container;
}
return type->data.array;
}
+/* For MONO_TYPE_PTR */
+MonoType*
+mono_type_get_ptr_type (MonoType *type)
+{
+ return type->data.type;
+}
+
MonoClass*
mono_type_get_modifiers (MonoType *type, gboolean *is_required, gpointer *iter)
{