Преглед изворни кода

2001-08-09 Dietmar Maurer <[email protected]>

	* implemented arrays, but you will need a modified version of
	Array.cs to get arrays working (will commit soon)

	* interp.c (ves_icall_array_Set): impl.
	(ves_icall_array_Get): impl.
	(ves_icall_array_ctor): impl.
	(ves_icall_System_Array_GetRank): impl.
	(ves_icall_System_Array_GetLength): impl.
	(ves_icall_System_Array_GetLowerBound): impl.
	(mono_lookup_internal_call): impl.

	* object.c (mono_new_szarray): impl.

	* loader.c (mono_typedef_from_name): return the token, not the index
	(mono_get_corlib): impl.
	(mono_get_array_class_info): impl.
	(method_from_memberref): add array support
	(mono_get_method): support INTERNAL_CALL

	* class.c (mono_class_create_from_typedef): Array support,
	code cleanup, store the token_type, not the token index, added
	flag for value types.
	(mono_type_to_tydedef): impl.
	(mono_class_create_from_typespec): impl.
	(mono_array_class_get): impl.
	(mono_class_get): support TYPE_SPEC token.

svn path=/trunk/mono/; revision=452
Dietmar Maurer пре 24 година
родитељ
комит
db2912b8f4

+ 4 - 0
ChangeLog

@@ -1,3 +1,7 @@
+2001-08-09  Dietmar Maurer  <[email protected]>
+
+	* mono/tests/array.cs: more array tests
+
 2001-08-06  Dietmar Maurer  <[email protected]>
 
 	* mono/tests/pinvoke.cs: we can now print strings ;-)

+ 18 - 0
mono/cli/ChangeLog

@@ -1,3 +1,21 @@
+2001-08-09  Dietmar Maurer  <[email protected]>
+
+	* object.c (mono_new_szarray): impl.
+
+	* loader.c (mono_typedef_from_name): return the token, not the index
+	(mono_get_corlib): impl.
+	(mono_get_array_class_info): impl.
+	(method_from_memberref): add array support
+	(mono_get_method): support INTERNAL_CALL
+
+	* class.c (mono_class_create_from_typedef): Array support,
+	code cleanup, store the token_type, not the token index, added
+	flag for value types.
+	(mono_type_to_tydedef): impl.
+	(mono_class_create_from_typespec): impl.
+	(mono_array_class_get): impl.
+	(mono_class_get): support TYPE_SPEC token.
+
 2001-08-06  Dietmar Maurer  <[email protected]>
 
 	* cli.h: renamed MonoMethodManaged to MonoMethodNormal

+ 218 - 56
mono/cli/class.c

@@ -21,12 +21,46 @@
 #include <mono/metadata/metadata.h>
 #include <mono/metadata/tabledefs.h>
 #include <mono/metadata/tokentype.h>
+#include <mono/cli/cli.h>
 #include <mono/cli/class.h>
 #include <mono/cli/types.h>
 #include <mono/cli/object.h>
 
 #define CSIZE(x) (sizeof (x) / 4)
 
+static void
+typedef_from_typeref (MonoImage *image, guint32 type_token, MonoImage **rimage, guint32 *index)
+{
+	guint32 cols[MONO_TYPEDEF_SIZE];
+	MonoMetadata *m = &image->metadata;
+	MonoTableInfo  *t = &m->tables[MONO_TABLE_TYPEREF];
+	guint32 idx, i;
+	const char *name, *nspace;
+	
+	mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, 3);
+	g_assert ((cols [0] & 0x3) == 2);
+	idx = cols [0] >> 2;
+	name = mono_metadata_string_heap (m, cols [1]);
+	nspace = mono_metadata_string_heap (m, cols [2]);
+	/* load referenced assembly */
+	image = image->references [idx-1]->image;
+	m = &image->metadata;
+	t = &m->tables [MONO_TABLE_TYPEDEF];
+	/* dumb search for now */
+	for (i=0; i < t->rows; ++i) {
+		mono_metadata_decode_row (t, i, cols, MONO_TYPEDEF_SIZE);
+
+		if (!strcmp (name, mono_metadata_string_heap (m, cols [1])) &&
+		    !strcmp (nspace, mono_metadata_string_heap (m, cols [2]))) {
+			*rimage = image;
+			*index =  MONO_TOKEN_TYPE_DEF | (i + 1);
+			return;
+		}
+	}
+	g_assert_not_reached ();
+	
+}
+
 /** 
  * class_compute_field_layout:
  * @m: pointer to the metadata.
@@ -116,7 +150,7 @@ class_compute_field_layout (MonoMetadata *m, MonoClass *class)
 
 /**
  * @image: context where the image is created
- * @tidx:  index of the type to create
+ * @type_token:  typedef token
  */
 static MonoClass *
 mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
@@ -126,37 +160,34 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
 	MonoClass stack_class;
 	MonoClass *class = &stack_class;
 	guint32 cols [MONO_TYPEDEF_SIZE], parent_token;
-	guint tidx = type_token & 0xffffff;
+	guint tidx = mono_metadata_token_index (type_token);
 	const char *name, *nspace;
      
+	g_assert (mono_metadata_token_table (type_token) == MONO_TABLE_TYPEDEF);
+
 	memset (class, 0, sizeof (MonoClass));
 
 	mono_metadata_decode_row (tt, tidx-1, cols, CSIZE (cols));
 	name = mono_metadata_string_heap (m, cols[1]);
 	nspace = mono_metadata_string_heap (m, cols[2]);
 	/*g_print ("Init class %s\n", name);*/
-
-	/*
-	 * If root of the hierarchy
-	 */
-	if (!strcmp (name, "Object") && !strcmp (nspace, "System")) {
+ 
+	/* if root of the hierarchy */
+	if (!strcmp (nspace, "System") && !strcmp (name, "Object")) {
 		class->instance_size = sizeof (MonoObject);
 		class->parent = NULL;
 	} else {
 		parent_token = mono_metadata_token_from_dor (cols [3]);
 		class->parent = mono_class_get (image, parent_token);
 		class->instance_size = class->parent->instance_size;
+		class->valuetype = class->parent->valuetype;
 	}
+	if (!strcmp (nspace, "System") && !strcmp (name, "ValueType"))
+		class->valuetype = 1;
 
-	/* reserve space to store vector pointer in arrays */
-	if (!strcmp (name, "Object") && !strcmp (nspace, "Array")) {
-		class->instance_size += sizeof (gpointer);
-		g_assert (class->instance_size != sizeof (MonoArrayObject));
-	}
-
-	
+	g_assert (class->instance_size);
 	class->image = image;
-	class->type_token = tidx;
+	class->type_token = type_token;
 	class->flags = cols [0];
 	class->class_size = sizeof (MonoClass);
 	
@@ -196,11 +227,171 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
 		class_compute_field_layout (m, class);
 	}
 
+	/* reserve space to store vector pointer in arrays */
+	if (!strcmp (nspace, "System") && !strcmp (name, "Array")) {
+		class->instance_size += 2 * sizeof (gpointer);
+		g_assert (class->field.count == 0);
+		g_assert (class->instance_size == sizeof (MonoArrayObject));
+	}
+
 	class = g_malloc0 (class->class_size);
 	*class = stack_class;
 	return class;
 }
 
+static guint32
+mono_type_to_tydedef (MonoImage *image, MonoType *type, MonoImage **rimage)
+{
+	MonoImage *corlib, *res;
+	guint32 etype;
+
+	res = corlib = mono_get_corlib ();
+
+	switch (type->type) {
+	case MONO_TYPE_BOOLEAN:
+		etype = mono_typedef_from_name (corlib, "Boolean", "System", NULL);
+		break;
+	case MONO_TYPE_CHAR:
+		etype = mono_typedef_from_name (corlib, "Char", "System", NULL); 
+		break;
+	case MONO_TYPE_I1:
+		etype = mono_typedef_from_name (corlib, "Byte", "System", NULL); 
+		break;
+	case MONO_TYPE_I2:
+		etype = mono_typedef_from_name (corlib, "Int16", "System", NULL); 
+		break;
+	case MONO_TYPE_U2:
+		etype = mono_typedef_from_name (corlib, "UInt16", "System", NULL); 
+		break;
+	case MONO_TYPE_I4:
+		etype = mono_typedef_from_name (corlib, "Int32", "System", NULL); 
+		break;
+	case MONO_TYPE_U4:
+		etype = mono_typedef_from_name (corlib, "UInt32", "System", NULL); 
+		break;
+	case MONO_TYPE_I8:
+		etype = mono_typedef_from_name (corlib, "Int64", "System", NULL); 
+		break;
+	case MONO_TYPE_U8:
+		etype = mono_typedef_from_name (corlib, "UInt64", "System", NULL); 
+		break;
+	case MONO_TYPE_R8:
+		etype = mono_typedef_from_name (corlib, "Double", "System", NULL); 
+		break;
+	case MONO_TYPE_STRING:
+		etype = mono_typedef_from_name (corlib, "String", "System", NULL); 
+		break;
+	case MONO_TYPE_CLASS:
+		etype = type->data.token;
+		res = image;
+		break;
+	default:
+		g_warning ("implement me %08x\n", type->type);
+		g_assert_not_reached ();
+	}
+	
+	*rimage = res;
+	return etype;
+}
+
+/**
+ * @image: context where the image is created
+ * @type_spec:  typespec token
+ * @at: an optional pointer to return the array type
+ */
+static MonoClass *
+mono_class_create_from_typespec (MonoImage *image, guint32 type_spec)
+{
+	MonoMetadata *m = &image->metadata;
+	guint32 idx = mono_metadata_token_index (type_spec);
+	MonoTableInfo *t;
+	guint32 cols [MONO_TYPESPEC_SIZE];       
+	const char *ptr;
+	guint32 len, etype;
+	MonoType *type;
+	MonoClass *class;
+	MonoImage *rimage;
+
+	t = &m->tables [MONO_TABLE_TYPESPEC];
+	
+	mono_metadata_decode_row (t, idx-1, cols, MONO_TYPESPEC_SIZE);
+	ptr = mono_metadata_blob_heap (m, cols [MONO_TYPESPEC_SIGNATURE]);
+	len = mono_metadata_decode_value (ptr, &ptr);
+	type = mono_metadata_parse_type (m, ptr, &ptr);
+
+	switch (type->type) {
+	case MONO_TYPE_ARRAY:
+		etype = mono_type_to_tydedef (image, type->data.array->type, &rimage);
+		class = mono_array_class_get (rimage, etype, type->data.array->rank);
+		break;
+	case MONO_TYPE_SZARRAY:
+		g_assert (!type->custom_mod);
+		etype = mono_type_to_tydedef (image, type->data.type, &rimage);
+		class = mono_array_class_get (rimage, etype, 1);
+		break;
+	default:
+		g_assert_not_reached ();		
+	}
+
+	mono_metadata_free_type (type);
+	
+	return class;
+}
+
+MonoClass *
+mono_array_class_get (MonoImage *image, guint32 etype, guint32 rank)
+{
+	MonoClass *class, *eclass;
+	static MonoClass *parent = NULL;
+	MonoArrayClass *aclass;
+	guint32 esize, key;
+
+	g_assert (rank <= 255);
+
+	if (!parent) {
+		guint32 arr_token;
+		MonoImage *corlib;
+
+		mono_get_array_class_info (&arr_token, &corlib);
+		parent = mono_class_get (corlib, arr_token);
+		g_assert (parent != NULL);
+	}
+
+	eclass = mono_class_get (image, etype);
+	g_assert (eclass != NULL);
+
+	image = eclass->image;
+
+	esize = eclass->instance_size;
+
+	g_assert (!eclass->type_token ||
+		  mono_metadata_token_table (eclass->type_token) == MONO_TABLE_TYPEDEF);
+	
+	key = ((rank & 0xff) << 24) | (eclass->type_token & 0xffffff);
+	if ((class = g_hash_table_lookup (image->array_cache, GUINT_TO_POINTER (key))))
+		return class;
+	
+	if (eclass->valuetype)
+		esize -= sizeof (MonoObject);
+
+	aclass = g_new0 (MonoArrayClass, 1);
+	class = (MonoClass *)aclass;
+       
+	class->image = image;
+	class->type_token = 0;
+	class->flags = TYPE_ATTRIBUTE_CLASS;
+	class->parent = parent;
+	class->instance_size = class->parent->instance_size;
+	class->class_size = sizeof (MonoArrayClass);
+	
+	aclass->rank = rank;
+	aclass->etype_token = eclass->type_token;
+	aclass->esize = esize;
+
+	g_hash_table_insert (image->array_cache, GUINT_TO_POINTER (key), class);
+	return class;
+}
+
 /*
  * Auxiliary routine to mono_class_get_field
  *
@@ -243,43 +434,11 @@ mono_class_get_field (MonoClass *class, guint32 field_token)
 	return mono_class_get_field_idx (class, idx - 1);
 }
 
-void
-typedef_from_typeref (MonoImage *image, guint32 type_token, MonoImage **rimage, guint32 *index)
-{
-	guint32 cols[MONO_TYPEDEF_SIZE];
-	MonoMetadata *m = &image->metadata;
-	MonoTableInfo  *t = &m->tables[MONO_TABLE_TYPEREF];
-	guint32 idx, i;
-	const char *name, *nspace;
-	
-	mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, 3);
-	g_assert ((cols [0] & 0x3) == 2);
-	idx = cols [0] >> 2;
-	name = mono_metadata_string_heap (m, cols [1]);
-	nspace = mono_metadata_string_heap (m, cols [2]);
-	/* load referenced assembly */
-	image = image->references [idx-1]->image;
-	m = &image->metadata;
-	t = &m->tables [MONO_TABLE_TYPEDEF];
-	/* dumb search for now */
-	for (i=0; i < t->rows; ++i) {
-		mono_metadata_decode_row (t, i, cols, MONO_TYPEDEF_SIZE);
-
-		if (!strcmp (name, mono_metadata_string_heap (m, cols [1])) &&
-		    !strcmp (nspace, mono_metadata_string_heap (m, cols [2]))) {
-			*rimage = image;
-			*index = i + 1;
-			return;
-		}
-	}
-	g_assert_not_reached ();
-	
-}
-
 /**
  * mono_class_get:
  * @image: the image where the class resides
  * @type_token: the token for the class
+ * @at: an optional pointer to return the array element type
  *
  * Returns: the MonoClass that represents @type_token in @image
  */
@@ -288,23 +447,26 @@ mono_class_get (MonoImage *image, guint32 type_token)
 {
 	MonoClass *class;
        
-	if ((type_token & 0xff000000) == MONO_TOKEN_TYPE_DEF 
-					&& (class = g_hash_table_lookup (image->class_cache, GUINT_TO_POINTER (type_token))))
-			return class;
-
 	switch (type_token & 0xff000000){
 	case MONO_TOKEN_TYPE_DEF:
+		if ((class = g_hash_table_lookup (image->class_cache, 
+						  GUINT_TO_POINTER (type_token))))
+			return class;
+
 		class = mono_class_create_from_typedef (image, type_token);
 		break;
 		
 	case MONO_TOKEN_TYPE_REF: {
 		typedef_from_typeref (image, type_token, &image, &type_token);
-		class = mono_class_create_from_typedef (image, type_token);
-		break;
+		return mono_class_get (image, type_token);
 	}
 	case MONO_TOKEN_TYPE_SPEC:
-		g_error ("Can not handle class creation of TypeSpecs yet");
-		
+		if ((class = g_hash_table_lookup (image->class_cache, 
+						  GUINT_TO_POINTER (type_token))))
+			return class;
+
+		class = mono_class_create_from_typespec (image, type_token);
+		break;
 	default:
 		g_assert_not_reached ();
 	}

+ 17 - 2
mono/cli/class.h

@@ -4,6 +4,8 @@
 #include <mono/metadata/metadata.h>
 #include <mono/metadata/image.h>
 
+#define MONO_CLASS_IS_ARRAY(c) (c->type_token == 0)
+
 typedef struct {
 	MonoFieldType *type;
 	int            offset;
@@ -17,6 +19,7 @@ struct _MonoClass {
 	guint32    type_token;
 
 	guint inited : 1;
+	guint valuetype : 1;
 
 	MonoClass *parent;
 	
@@ -44,8 +47,20 @@ struct _MonoClass {
 	 */
 };
 
-MonoClass *mono_class_get       (MonoImage *image, guint32 type_token);
+typedef struct {
+	MonoClass class;
+	guint32 rank;        /* array dimension */
+	guint32 etype_token; /* element type token */
+	guint32 esize;       /* element size */	
+} MonoArrayClass;
+
+MonoClass *
+mono_class_get       (MonoImage *image, guint32 type_token);
+
+MonoClass *
+mono_array_class_get (MonoImage *image, guint32 etype, guint32 rank);
 
-MonoClassField *mono_class_get_field (MonoClass *class, guint32 field_token);
+MonoClassField *
+mono_class_get_field (MonoClass *class, guint32 field_token);
 
 #endif /* _MONO_CLI_CLASS_H_ */

+ 19 - 7
mono/cli/cli.h

@@ -28,17 +28,29 @@ typedef struct {
 } MonoMethodPInvoke;
 
 
-MonoMethod        *mono_get_method      (MonoImage *image, guint32 token);
-void               mono_free_method     (MonoMethod *method);
+MonoMethod *
+mono_get_method            (MonoImage *image, guint32 token);
 
-guint32            mono_typedef_from_name (MonoImage *image, const char *name, 
-					   const char *nspace, guint32 *mlist);
+void               
+mono_free_method           (MonoMethod *method);
 
-guint32            mono_get_string_class_info (guint *ttoken, MonoImage **cl);
+guint32            
+mono_typedef_from_name     (MonoImage *image, const char *name, 
+			    const char *nspace, guint32 *mlist);
 
+MonoImage *
+mono_get_corlib            (void);
 
-MonoImage         *mono_load_image    (const char *fname, enum MonoImageOpenStatus *status);
+guint32            
+mono_get_string_class_info (guint *ttoken, MonoImage **cl);
 
-gpointer           mono_lookup_internal_call (const char *name);
+void              
+mono_get_array_class_info  (guint *ttoken, MonoImage **cl);
+
+MonoImage *
+mono_load_image            (const char *fname, enum MonoImageOpenStatus *status);
+
+gpointer
+mono_lookup_internal_call  (const char *name);
 
 #endif

+ 123 - 21
mono/cli/loader.c

@@ -65,13 +65,57 @@ mono_typedef_from_name (MonoImage *image, const char *name,
 				&& strcmp (nspace, mono_metadata_string_heap (m, cols [MONO_TYPEDEF_NAMESPACE])) == 0) {
 			if (mlist)
 				*mlist = cols [MONO_TYPEDEF_METHOD_LIST];
-			return i + 1;
+			return MONO_TOKEN_TYPE_DEF | (i + 1);
 		}
 	}
 	g_assert_not_reached ();
 	return 0;
 }
 
+MonoImage *
+mono_get_corlib ()
+{
+	static MonoImage *corlib = NULL;
+	MonoAssembly *ass;
+	enum MonoImageOpenStatus status = MONO_IMAGE_OK;
+
+	if (!corlib) {
+		ass = mono_assembly_open (CORLIB_NAME, NULL, &status);
+		g_assert (status == MONO_IMAGE_OK);
+		g_assert (ass != NULL);
+		g_assert (ass->image != NULL);
+		
+		corlib = ass->image;
+	}
+
+	return corlib;
+}
+
+/**
+ * mono_get_array_class_info:
+ * @ttoken: pointer to location to store type definition token
+ * @cl: pointer where image will be stored
+ *
+ * This routine locates information about the System.Array class. A reference
+ * to the image containing the class is returned in @cl. The type definition 
+ * token is returned in @ttoken. 
+ */
+void
+mono_get_array_class_info (guint *ttoken, MonoImage **cl)
+{
+	static guint32 arr_token = 0;
+	static MonoImage *corlib;
+
+	if (!arr_token) {
+		corlib = mono_get_corlib ();		
+		arr_token = mono_typedef_from_name (corlib, "Array", "System", NULL);
+		g_assert (arr_token != 0);
+	}
+
+	*ttoken = arr_token;
+	*cl = corlib;
+}
+
 /**
  * mono_get_string_class_info:
  * @ttoken: pointer to location to store type definition token
@@ -88,8 +132,6 @@ guint32
 mono_get_string_class_info (guint *ttoken, MonoImage **cl)
 {
 	static guint32 ctor = 0, tt = 0;
-	enum MonoImageOpenStatus status = MONO_IMAGE_OK; 
-	MonoAssembly *ass;
 	static MonoImage *corlib;
 	MonoMetadata *m;
 	MonoTableInfo *t;
@@ -104,13 +146,8 @@ mono_get_string_class_info (guint *ttoken, MonoImage **cl)
 		return ctor;
 	}
 
-	ass = mono_assembly_open (CORLIB_NAME, NULL, &status);
-	g_assert (status == MONO_IMAGE_OK);
-	g_assert (ass != NULL);
+	*cl = corlib = mono_get_corlib ();		
 	
-	*cl = corlib = ass->image;
-	g_assert (corlib != NULL);
-       
 	m = &corlib->metadata;
 	t = &m->tables [MONO_TABLE_TYPEDEF];
 
@@ -165,8 +202,8 @@ mono_get_string_class_info (guint *ttoken, MonoImage **cl)
 	return ctor;
 }
 
-static void
-methoddef_from_memberref (MonoImage *image, guint32 index, MonoImage **rimage, guint32 *rindex)
+static MonoMethod *
+method_from_memberref (MonoImage *image, guint32 index)
 {
 	MonoMetadata *m = &image->metadata;
 	MonoTableInfo *tables = m->tables;
@@ -220,9 +257,7 @@ methoddef_from_memberref (MonoImage *image, guint32 index, MonoImage **rimage, g
 				if (strcmp (mname, mono_metadata_string_heap (m, cols [MONO_METHOD_NAME])) == 0 
 						&& sig_len == msig_len
 						&& strncmp (sig, msig, sig_len) == 0) {
-					*rimage = image;
-					*rindex = i + 1;
-					return;
+					return mono_get_method (image, MONO_TOKEN_METHOD_DEF | (i + 1));
 				}
 			}
 			g_assert_not_reached ();
@@ -232,9 +267,66 @@ methoddef_from_memberref (MonoImage *image, guint32 index, MonoImage **rimage, g
 		}
 		break;
 	}
+	case MEMBERREF_PARENT_TYPESPEC: {
+		MonoMethodSignature *ms;
+		guint32 bcols [MONO_TYPESPEC_SIZE];
+		const char *ptr;
+		guint32 len;
+		MonoType *type;
+		MonoMethod *result;
+
+		mono_metadata_decode_row (&tables [MONO_TABLE_TYPESPEC], nindex - 1, 
+					  bcols, MONO_TYPESPEC_SIZE);
+		ptr = mono_metadata_blob_heap (m, bcols [MONO_TYPESPEC_SIGNATURE]);
+		len = mono_metadata_decode_value (ptr, &ptr);	
+		type = mono_metadata_parse_type (m, ptr, &ptr);
+
+		if (type->type != MONO_TYPE_ARRAY)
+			g_assert_not_reached ();		
+
+		ms = mono_metadata_parse_method_signature (m, 0, sig, &sig);
+
+		result = (MonoMethod *)g_new0 (MonoMethod, 1);
+		result->image = image;
+		result->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
+		result->signature = ms;
+		
+		if (!strcmp (mname, ".ctor")) { 
+			g_assert (ms->hasthis);
+			if (type->data.array->rank == ms->param_count) {
+				result->addr = mono_lookup_internal_call ("__array_ctor");
+				return result;
+			} else if ((type->data.array->rank * 2) == ms->param_count) {
+				result->addr = mono_lookup_internal_call ("__array_bound_ctor");
+				return result;			
+			} else 
+				g_assert_not_reached ();
+		}
+
+		if (!strcmp (mname, "Set")) {
+			g_assert (ms->hasthis);
+			g_assert (type->data.array->rank + 1 == ms->param_count);
+
+			result->addr = mono_lookup_internal_call ("__array_Set");
+			return result;
+		}
+
+		if (!strcmp (mname, "Get")) {
+			g_assert (ms->hasthis);
+			g_assert (type->data.array->rank == ms->param_count);
+
+			result->addr = mono_lookup_internal_call ("__array_Get");
+			return result;
+		}
+
+		g_assert_not_reached ();
+		break;
+	}
 	default:
 		g_assert_not_reached ();
 	}
+
+	return NULL;
 }
 
 static ffi_type *
@@ -356,28 +448,36 @@ mono_get_method (MonoImage *image, guint32 token)
 	int table = mono_metadata_token_table (token);
 	int index = mono_metadata_token_index (token);
 	MonoTableInfo *tables = m->tables;
-	const char *loc, *name;
-	const char *sig = NULL;
+	const char *loc, *sig = NULL;
+	char *name;
 	int size;
 	guint32 cols[6];
 
 	if (table == MONO_TABLE_METHOD && (result = g_hash_table_lookup (image->method_cache, GINT_TO_POINTER (token))))
 			return result;
-	
+
 	if (table != MONO_TABLE_METHOD) {
 		g_assert (table == MONO_TABLE_MEMBERREF);
-		methoddef_from_memberref (image, index, &image, &token);
-		return mono_get_method (image, MONO_TOKEN_METHOD_DEF | token);
+		return method_from_memberref (image, index);
 	}
 
 	mono_metadata_decode_row (&tables [table], index - 1, cols, 6);
 
 	if (cols [1] & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
+		MonoTableInfo *t = &m->tables [MONO_TABLE_TYPEDEF];
 		MonoAssembly *corlib;
+		guint32 tdef;
+		guint32 tdcols [MONO_TYPEDEF_SIZE];
 
-		corlib = mono_assembly_open (CORLIB_NAME, NULL, NULL);
+		tdef = mono_metadata_typedef_from_method (m, index - 1) - 1;
+
+		mono_metadata_decode_row (t, tdef, tdcols, MONO_TYPEDEF_SIZE);
 
-		name = mono_metadata_string_heap (m, cols[3]);
+		name = g_strconcat (mono_metadata_string_heap (m, tdcols [MONO_TYPEDEF_NAMESPACE]), ".",
+				    mono_metadata_string_heap (m, tdcols [MONO_TYPEDEF_NAME]), "::", 
+				    mono_metadata_string_heap (m, cols [MONO_METHOD_NAME]), NULL);
+
+		corlib = mono_assembly_open (CORLIB_NAME, NULL, NULL);
 
 		/* all internal calls must be inside corlib */
 		g_assert (corlib->image == image);
@@ -386,6 +486,8 @@ mono_get_method (MonoImage *image, guint32 token)
 
 		result->addr = mono_lookup_internal_call (name);
 
+		g_free (name);
+
 		g_assert (result->addr != NULL);
 
 	} else if (cols [2] & METHOD_ATTRIBUTE_PINVOKE_IMPL) {

+ 38 - 2
mono/cli/object.c

@@ -9,6 +9,7 @@
 #include <config.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <mono/cli/cli.h>
 #include <mono/cli/object.h>
 
 /**
@@ -54,12 +55,47 @@ mono_object_free (MonoObject *o)
 MonoObject *
 mono_object_new (MonoImage *image, guint32 type_token)
 {
-	MonoClass *c = mono_class_get (image, type_token);
+	MonoClass *c;
 	MonoObject *o;
-	
+
+	c = mono_class_get (image, type_token);
 	o = mono_object_allocate (c->instance_size);
 	o->klass = c;
 
 	return o;
 }
 
+/*
+ * mono_new_szarray:
+ * @image: image where the object is being referenced
+ * @etype: element type token
+ * @n: number of array elements
+ *
+ * This routine creates a new szarray with @n elements of type @token
+ */
+MonoObject *
+mono_new_szarray (MonoImage *image, guint32 etype, guint32 n)
+{
+	MonoClass *c;
+	MonoObject *o;
+	MonoArrayObject *ao;
+	MonoArrayClass *ac;
+	guint32 esize;
+
+	c = mono_array_class_get (image, etype, 1);
+	g_assert (c != NULL);
+
+	o = mono_object_allocate (c->instance_size);
+	o->klass = c;
+
+	ao = (MonoArrayObject *)o;
+	ac = (MonoArrayClass *)c;
+
+	ao->bounds = g_malloc0 (sizeof (MonoArrayBounds));
+	ao->bounds [0].length = n;
+	ao->bounds [0].lower_bound = 0;
+
+	ao->vector = g_malloc0 (n * ac->esize);
+
+	return o;
+}

+ 15 - 6
mono/cli/object.h

@@ -7,22 +7,31 @@ typedef struct {
 	MonoClass *klass;
 } MonoObject;
 
+typedef struct {
+	guint32 length;
+	guint32 lower_bound;
+} MonoArrayBounds;
+
 typedef struct {
 	MonoObject obj;
-	gint32 lower_bound;
-	gint32 length;
-	gint32 rank;
 	gpointer vector;
+	MonoArrayBounds *bounds;
 } MonoArrayObject;
 
 typedef struct {
 	MonoObject obj;
-	gint32 length;
 	MonoArrayObject *c_str;
+	gint32 length;
 } MonoStringObject;
 
-MonoObject *mono_object_new  (MonoImage *image, guint32 type_token);
-void        mono_object_free (MonoObject *o);
+MonoObject *
+mono_object_new       (MonoImage *image, guint32 type_token);
+
+MonoObject *
+mono_new_szarray      (MonoImage *image, guint32 etype, guint32 n);
+
+void       
+mono_object_free      (MonoObject *o);
 		      
 #endif
 

+ 0 - 1
mono/dis/get.c

@@ -939,7 +939,6 @@ get_method (MonoMetadata *m, guint32 token)
 
 	switch (mono_metadata_token_code (token)){
 	case MONO_TOKEN_METHOD_DEF:
-
 		mono_metadata_decode_row (&m->tables [MONO_TABLE_METHOD], 
 					  idx - 1, method_cols, MONO_METHOD_SIZE);
 

+ 13 - 0
mono/interpreter/ChangeLog

@@ -1,3 +1,16 @@
+2001-08-09  Dietmar Maurer  <[email protected]>
+
+	* implemented arrays, but you will need a modified version of 
+	Array.cs to get arrays working (will commit soon)
+	
+	* interp.c (ves_icall_array_Set): impl.
+	(ves_icall_array_Get): impl.
+	(ves_icall_array_ctor): impl.
+	(ves_icall_System_Array_GetRank): impl.
+	(ves_icall_System_Array_GetLength): impl.
+	(ves_icall_System_Array_GetLowerBound): impl.
+	(mono_lookup_internal_call): impl.
+
 2001-08-06  Dietmar Maurer  <[email protected]>
 
 	* interp.c (ves_exec_method): impl. NEWARR

+ 199 - 74
mono/interpreter/interp.c

@@ -145,6 +145,9 @@ newobj (MonoImage *image, guint32 token)
 		table = mpr_token & 7;
 		idx = mpr_token >> 3;
 		
+		if (strcmp (mono_metadata_string_heap (m, member_cols[1]), ".ctor"))
+			g_error ("Unhandled: call to non constructor");
+
 		switch (table){
 		case 0: /* TypeDef */
 			result = mono_object_new (image, MONO_TOKEN_TYPE_DEF | idx);
@@ -158,8 +161,8 @@ newobj (MonoImage *image, guint32 token)
 		case 3: /* MethodDef */
 			g_error ("Unhandled: MethodDef");
 			
-		case 4: /* TypeSpec */
-			g_error ("Unhandled: TypeSepc");
+		case 4: /* TypeSpec */			
+			result = mono_object_new (image, MONO_TOKEN_TYPE_SPEC | idx);
 		}
 		break;
 	}
@@ -224,6 +227,7 @@ stackval_from_data (MonoType *type, const char *data, guint offset)
 	case MONO_TYPE_STRING:
 	case MONO_TYPE_SZARRAY:
 	case MONO_TYPE_CLASS:
+	case MONO_TYPE_ARRAY:
 		result.type = VAL_OBJ;
 		result.data.p = *(gpointer*)(data + offset);
 		break; 
@@ -262,6 +266,7 @@ stackval_to_data (MonoType *type, stackval *val, char *data, guint offset)
 	case MONO_TYPE_STRING:
 	case MONO_TYPE_SZARRAY:
 	case MONO_TYPE_CLASS:
+	case MONO_TYPE_ARRAY:
 		*(gpointer*)(data + offset) = val->data.p;
 		break;
 	default:
@@ -270,59 +275,6 @@ stackval_to_data (MonoType *type, stackval *val, char *data, guint offset)
 	}
 }
 
-/*
- * newarr:
- * @image: image where the object is being referenced
- * @token: type token
- * @n: number of array elements
- *
- * This routine creates a new array with @n elements of type @token
- */
-static MonoObject *
-newarr (MonoImage *image, guint32 token, guint32 n)
-{
-	MonoClass *tc;
-	MonoObject *o;
-	MonoArrayObject *ao;
-	static guint32 arr_token = 0;
-	static MonoImage *corlib = NULL;
-
-	tc = mono_class_get (image, token);
-	g_assert (tc != 0);
-
-	if (!arr_token) {
-		MonoAssembly *ass;
-		enum MonoImageOpenStatus status = MONO_IMAGE_OK; 
-
-		ass = mono_assembly_open (CORLIB_NAME, NULL, &status);
-		g_assert (status == MONO_IMAGE_OK);
-		g_assert (ass != NULL);
-
-		corlib = ass->image;
-		
-		arr_token = mono_typedef_from_name (corlib, "Array", "System",
-						    NULL);
-		g_assert (arr_token != 0);
-
-		arr_token =  MONO_TOKEN_TYPE_DEF | arr_token;
-	}
-
-        o = mono_object_new (corlib, arr_token);
-	g_assert (o != NULL);
-
-	g_assert (o->klass->field.count == 3);
-
-	ao = (MonoArrayObject *)o;
-
-	ao->lower_bound = 0;
-	ao->length = n;
-	ao->rank = 1;
-	ao->vector = g_malloc0 (n * (o->klass->instance_size - 
-				     sizeof (MonoObject)));
-
-	return o;
-}
-
 static char *
 mono_get_ansi_string (MonoObject *o)
 {
@@ -330,6 +282,8 @@ mono_get_ansi_string (MonoObject *o)
 	char *as, *vector;
 	int i;
 
+	g_assert (o != NULL);
+
 	if (!s->length)
 		return g_strdup ("");
 
@@ -350,12 +304,150 @@ mono_get_ansi_string (MonoObject *o)
 }
 
 static void 
-ves_icall_InternalGetValue (MonoMethod *mh, stackval *sp)
+ves_icall_array_Set (MonoMethod *mh, stackval *sp)
+{
+	MonoObject *o;
+	MonoArrayObject *ao;
+	MonoArrayClass *ac;
+	gint32 i, t, pos;
+	gpointer ea;
+
+	g_assert (sp [0].type == VAL_OBJ);
+
+	o = sp [0].data.p;
+	ao = (MonoArrayObject *)o;
+	ac = (MonoArrayClass *)o->klass;
+
+	g_assert (ac->rank >= 1);
+
+	pos = sp [1].data.i - ao->bounds [1].lower_bound;
+	for (i = 1; i < ac->rank; i++) {
+		if ((t = sp [i + 1].data.i - ao->bounds [i].lower_bound) >= ao->bounds [i].length) {
+			g_warning ("wrong array index");
+			g_assert_not_reached ();
+		}
+		pos = pos*ao->bounds [i].length + sp [i + 1].data.i - ao->bounds [i].lower_bound;
+	}
+
+	ea = ao->vector + (pos * ac->esize);
+	memcpy (ea, &sp [ac->rank + 1].data.p, ac->esize);
+}
+
+static void 
+ves_icall_array_Get (MonoMethod *mh, stackval *sp)
+{
+	MonoObject *o;
+	MonoArrayObject *ao;
+	MonoArrayClass *ac;
+	gint32 i, pos;
+	gpointer ea;
+
+	g_assert (sp [0].type == VAL_OBJ);
+
+	o = sp [0].data.p;
+	ao = (MonoArrayObject *)o;
+	ac = (MonoArrayClass *)o->klass;
+
+	g_assert (ac->rank >= 1);
+
+	pos = sp [1].data.i - ao->bounds [1].lower_bound;
+	for (i = 1; i < ac->rank; i++)
+		pos = pos*ao->bounds [i].length + sp [i + 1].data.i - ao->bounds [i].lower_bound;
+
+	ea = ao->vector + (pos * ac->esize);
+
+	sp [0].type = VAL_I32; /* fixme: not really true */
+	memcpy (&sp [0].data.p, ea, ac->esize);
+}
+
+static void 
+ves_icall_array_ctor (MonoMethod *mh, stackval *sp)
+{
+	MonoObject *o;
+	MonoArrayObject *ao;
+	MonoArrayClass *ac;
+	gint32 i, len;
+
+	g_assert (sp [0].type == VAL_OBJ);
+
+	o = sp [0].data.p;
+	ao = (MonoArrayObject *)o;
+	ac = (MonoArrayClass *)o->klass;
+
+	g_assert (ac->rank >= 1);
+
+	len = sp [1].data.i;
+	for (i = 1; i < ac->rank; i++)
+		len *= sp [i + 1].data.i;
+
+	ao->vector = g_malloc0 (len * ac->esize);
+	ao->bounds = g_malloc0 (ac->rank * sizeof (MonoArrayBounds));
+
+	for (i = 0; i < ac->rank; i++)
+		ao->bounds [i].length = sp [i + 1].data.i;
+}
+
+static void 
+ves_icall_array_bound_ctor (MonoMethod *mh, stackval *sp)
+{
+	MonoObject *o;
+	MonoArrayClass *ac;
+
+	g_assert (sp [0].type == VAL_OBJ);
+
+	o = sp [0].data.p;
+	ac = (MonoArrayClass *)o->klass;
+
+	g_warning ("experimental implementation");
+	g_assert_not_reached ();
+}
+
+static void 
+ves_icall_System_Array_InternalGetValue (MonoMethod *mh, stackval *sp)
 {
 	g_warning ("experimental implementation");
 	g_assert_not_reached ();
 }
 
+static void 
+ves_icall_System_Array_GetRank (MonoMethod *mh, stackval *sp)
+{
+	MonoObject *o;
+
+	g_assert (sp [0].type == VAL_OBJ);
+
+	o = sp [0].data.p;
+
+	sp [0].data.i = ((MonoArrayClass *)o->klass)->rank;
+	sp [0].type = VAL_I32;
+}
+
+static void 
+ves_icall_System_Array_GetLength (MonoMethod *mh, stackval *sp)
+{
+	MonoObject *o;
+
+	g_assert (sp [0].type == VAL_OBJ);
+
+	o = sp [0].data.p;
+
+	sp [0].data.i = ((MonoArrayObject *)o)->bounds [sp [1].data.i].length;
+	sp [0].type = VAL_I32;
+}
+
+static void 
+ves_icall_System_Array_GetLowerBound (MonoMethod *mh, stackval *sp)
+{
+	MonoObject *o;
+
+	g_assert (sp [0].type == VAL_OBJ);
+
+	o = sp [0].data.p;
+
+	sp [0].data.i = ((MonoArrayObject *)o)->bounds [sp [1].data.i].lower_bound;
+	sp [0].type = VAL_I32;
+}
+
 gpointer
 mono_lookup_internal_call (const char *name)
 {
@@ -365,8 +457,22 @@ mono_lookup_internal_call (const char *name)
 	if (!icall_hash) {
 		icall_hash = g_hash_table_new (g_str_hash , g_str_equal);
 		
-		g_hash_table_insert (icall_hash, "InternalGetValue", 
-				     &ves_icall_InternalGetValue);
+		g_hash_table_insert (icall_hash, "__array_Set", 
+				     &ves_icall_array_Set);
+		g_hash_table_insert (icall_hash, "__array_Get", 
+				     &ves_icall_array_Get);
+		g_hash_table_insert (icall_hash, "__array_ctor", 
+				     &ves_icall_array_ctor);
+		g_hash_table_insert (icall_hash, "__array_bound_ctor", 
+				     &ves_icall_array_bound_ctor);
+		g_hash_table_insert (icall_hash, "System.Array::InternalGetValue", 
+				     &ves_icall_System_Array_InternalGetValue);
+		g_hash_table_insert (icall_hash, "System.Array::GetRank", 
+				     &ves_icall_System_Array_GetRank);
+		g_hash_table_insert (icall_hash, "System.Array::GetLength", 
+				     &ves_icall_System_Array_GetLength);
+		g_hash_table_insert (icall_hash, "System.Array::GetLowerBound", 
+				     &ves_icall_System_Array_GetLowerBound);
 	}
 
 	if (!(res = g_hash_table_lookup (icall_hash, name))) {
@@ -417,7 +523,9 @@ ves_pinvoke_method (MonoMethod *mh, stackval *sp)
 			values[i] = &sp [i].data.f;
 			break;
 		case MONO_TYPE_STRING:
-			if (mh->flags & PINVOKE_ATTRIBUTE_CHAR_SET_ANSI) {
+			g_assert (sp [i].type == VAL_OBJ);
+
+			if (mh->flags & PINVOKE_ATTRIBUTE_CHAR_SET_ANSI && sp [i].data.p) {
 				tmp_string = alloca (sizeof (char *));
 				*tmp_string = mono_get_ansi_string (sp [i].data.p);
 				l = g_slist_prepend (l, *tmp_string);
@@ -1319,7 +1427,7 @@ ves_exec_method (MonoMethod *mh, stackval *args)
 
 			ctor = mono_get_string_class_info (&ttoken, &cl);
 			o = mono_object_new (cl, ttoken);
-		
+			
 			g_assert (o != NULL);
 
 			cmh = mono_get_method (cl, ctor);
@@ -1478,7 +1586,7 @@ ves_exec_method (MonoMethod *mh, stackval *args)
 
 			ip++;
 			token = read32 (ip);
-			o = newarr (mh->image, token, sp [-1].data.i);
+			o = mono_new_szarray (mh->image, token, sp [-1].data.i);
 			ip += 4;
 
 			sp [-1].type = VAL_OBJ;
@@ -1496,11 +1604,10 @@ ves_exec_method (MonoMethod *mh, stackval *args)
 			o = sp [-1].data.p;
 			g_assert (o != NULL);
 			
-			/* must be a szarray */
-			g_assert (o->vector != NULL);
+			g_assert (MONO_CLASS_IS_ARRAY (o->obj.klass));
 
 			sp [-1].type = VAL_I32;
-			sp [-1].data.i = o->length;
+			sp [-1].data.i = o->bounds [0].length;
 
 			BREAK;
 		}
@@ -1513,18 +1620,19 @@ ves_exec_method (MonoMethod *mh, stackval *args)
 		CASE (CEE_LDELEM_U4) /* fall through */
 		CASE (CEE_LDELEM_I)  /* fall through */
 		CASE (CEE_LDELEM_R4) /* fall through */
-		CASE (CEE_LDELEM_R8) {
+		CASE (CEE_LDELEM_R8) /* fall through */
+		CASE (CEE_LDELEM_REF) {
 			MonoArrayObject *o;
 
 			sp -= 2;
 
 			g_assert (sp [0].type == VAL_OBJ);
 			o = sp [0].data.p;
-			/* must be a szarray */
-			g_assert (o->vector != NULL);
 
+			g_assert (MONO_CLASS_IS_ARRAY (o->obj.klass));
+			
 			g_assert (sp [1].data.i >= 0);
-			g_assert (sp [1].data.i < o->length);
+			g_assert (sp [1].data.i < o->bounds [0].length);
 			
 			switch (*ip) {
 			case CEE_LDELEM_I1:
@@ -1563,6 +1671,10 @@ ves_exec_method (MonoMethod *mh, stackval *args)
 				sp [0].data.i = ((double *)o->vector)[sp [1].data.i]; 
 				sp [0].type = VAL_DOUBLE;
 				break;
+			case CEE_LDELEM_REF:
+				sp [0].data.p = ((gpointer *)o->vector)[sp [1].data.i]; 
+				sp [0].type = VAL_OBJ;
+				break;
 			default:
 				ves_abort();
 			}
@@ -1573,24 +1685,27 @@ ves_exec_method (MonoMethod *mh, stackval *args)
 			BREAK;
 		}
 		CASE (CEE_LDELEM_I8) ves_abort(); BREAK;
-		CASE (CEE_LDELEM_REF) ves_abort(); BREAK;
 		CASE (CEE_STELEM_I)  /* fall through */
 		CASE (CEE_STELEM_I1) /* fall through */ 
 		CASE (CEE_STELEM_I2) /* fall through */
 		CASE (CEE_STELEM_I4) /* fall through */
 		CASE (CEE_STELEM_R4) /* fall through */
-		CASE (CEE_STELEM_R8) {
+		CASE (CEE_STELEM_R8) /* fall through */
+		CASE (CEE_STELEM_REF) {
 			MonoArrayObject *o;
+			MonoArrayClass *ac;
+			MonoObject *v;
 
 			sp -= 3;
 
 			g_assert (sp [0].type == VAL_OBJ);
 			o = sp [0].data.p;
-			/* must be a szarray */
-			g_assert (o->vector != NULL);
 
+			g_assert (MONO_CLASS_IS_ARRAY (o->obj.klass));
+			ac = (MonoArrayClass *)o->obj.klass;
+		    
 			g_assert (sp [1].data.i >= 0);
-			g_assert (sp [1].data.i < o->length);
+			g_assert (sp [1].data.i < o->bounds [0].length);
 
 			switch (*ip) {
 			case CEE_STELEM_I:
@@ -1617,6 +1732,17 @@ ves_exec_method (MonoMethod *mh, stackval *args)
 				((double *)o->vector)[sp [1].data.i] = 
 					sp [2].data.f;
 				break;
+			case CEE_STELEM_REF:
+				g_assert (sp [2].type == VAL_OBJ);
+			
+				v = sp [2].data.p;
+
+				//fixme: what about type conversions ?
+				g_assert (v->klass->type_token == ac->etype_token);
+
+				((gpointer *)o->vector)[sp [1].data.i] = 
+					sp [2].data.p;
+				break;
 			default:
 				ves_abort();
 			}
@@ -1626,7 +1752,6 @@ ves_exec_method (MonoMethod *mh, stackval *args)
 			BREAK;
 		}
 		CASE (CEE_STELEM_I8)  ves_abort(); BREAK;
-		CASE (CEE_STELEM_REF) ves_abort(); BREAK;
 		CASE (CEE_UNUSED2) 
 		CASE (CEE_UNUSED3) 
 		CASE (CEE_UNUSED4) 

+ 4 - 0
mono/metadata/ChangeLog

@@ -1,3 +1,7 @@
+2001-08-09  Dietmar Maurer  <[email protected]>
+
+	* image.c (do_mono_image_open): added a cache for arrays.
+
 Sat Aug 4 12:46:02 CEST 2001 Paolo Molaro <[email protected]>
 
 	* metadata.h, metadata.c: add mono_metadata_decode_row_col () to

+ 218 - 56
mono/metadata/class.c

@@ -21,12 +21,46 @@
 #include <mono/metadata/metadata.h>
 #include <mono/metadata/tabledefs.h>
 #include <mono/metadata/tokentype.h>
+#include <mono/cli/cli.h>
 #include <mono/cli/class.h>
 #include <mono/cli/types.h>
 #include <mono/cli/object.h>
 
 #define CSIZE(x) (sizeof (x) / 4)
 
+static void
+typedef_from_typeref (MonoImage *image, guint32 type_token, MonoImage **rimage, guint32 *index)
+{
+	guint32 cols[MONO_TYPEDEF_SIZE];
+	MonoMetadata *m = &image->metadata;
+	MonoTableInfo  *t = &m->tables[MONO_TABLE_TYPEREF];
+	guint32 idx, i;
+	const char *name, *nspace;
+	
+	mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, 3);
+	g_assert ((cols [0] & 0x3) == 2);
+	idx = cols [0] >> 2;
+	name = mono_metadata_string_heap (m, cols [1]);
+	nspace = mono_metadata_string_heap (m, cols [2]);
+	/* load referenced assembly */
+	image = image->references [idx-1]->image;
+	m = &image->metadata;
+	t = &m->tables [MONO_TABLE_TYPEDEF];
+	/* dumb search for now */
+	for (i=0; i < t->rows; ++i) {
+		mono_metadata_decode_row (t, i, cols, MONO_TYPEDEF_SIZE);
+
+		if (!strcmp (name, mono_metadata_string_heap (m, cols [1])) &&
+		    !strcmp (nspace, mono_metadata_string_heap (m, cols [2]))) {
+			*rimage = image;
+			*index =  MONO_TOKEN_TYPE_DEF | (i + 1);
+			return;
+		}
+	}
+	g_assert_not_reached ();
+	
+}
+
 /** 
  * class_compute_field_layout:
  * @m: pointer to the metadata.
@@ -116,7 +150,7 @@ class_compute_field_layout (MonoMetadata *m, MonoClass *class)
 
 /**
  * @image: context where the image is created
- * @tidx:  index of the type to create
+ * @type_token:  typedef token
  */
 static MonoClass *
 mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
@@ -126,37 +160,34 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
 	MonoClass stack_class;
 	MonoClass *class = &stack_class;
 	guint32 cols [MONO_TYPEDEF_SIZE], parent_token;
-	guint tidx = type_token & 0xffffff;
+	guint tidx = mono_metadata_token_index (type_token);
 	const char *name, *nspace;
      
+	g_assert (mono_metadata_token_table (type_token) == MONO_TABLE_TYPEDEF);
+
 	memset (class, 0, sizeof (MonoClass));
 
 	mono_metadata_decode_row (tt, tidx-1, cols, CSIZE (cols));
 	name = mono_metadata_string_heap (m, cols[1]);
 	nspace = mono_metadata_string_heap (m, cols[2]);
 	/*g_print ("Init class %s\n", name);*/
-
-	/*
-	 * If root of the hierarchy
-	 */
-	if (!strcmp (name, "Object") && !strcmp (nspace, "System")) {
+ 
+	/* if root of the hierarchy */
+	if (!strcmp (nspace, "System") && !strcmp (name, "Object")) {
 		class->instance_size = sizeof (MonoObject);
 		class->parent = NULL;
 	} else {
 		parent_token = mono_metadata_token_from_dor (cols [3]);
 		class->parent = mono_class_get (image, parent_token);
 		class->instance_size = class->parent->instance_size;
+		class->valuetype = class->parent->valuetype;
 	}
+	if (!strcmp (nspace, "System") && !strcmp (name, "ValueType"))
+		class->valuetype = 1;
 
-	/* reserve space to store vector pointer in arrays */
-	if (!strcmp (name, "Object") && !strcmp (nspace, "Array")) {
-		class->instance_size += sizeof (gpointer);
-		g_assert (class->instance_size != sizeof (MonoArrayObject));
-	}
-
-	
+	g_assert (class->instance_size);
 	class->image = image;
-	class->type_token = tidx;
+	class->type_token = type_token;
 	class->flags = cols [0];
 	class->class_size = sizeof (MonoClass);
 	
@@ -196,11 +227,171 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
 		class_compute_field_layout (m, class);
 	}
 
+	/* reserve space to store vector pointer in arrays */
+	if (!strcmp (nspace, "System") && !strcmp (name, "Array")) {
+		class->instance_size += 2 * sizeof (gpointer);
+		g_assert (class->field.count == 0);
+		g_assert (class->instance_size == sizeof (MonoArrayObject));
+	}
+
 	class = g_malloc0 (class->class_size);
 	*class = stack_class;
 	return class;
 }
 
+static guint32
+mono_type_to_tydedef (MonoImage *image, MonoType *type, MonoImage **rimage)
+{
+	MonoImage *corlib, *res;
+	guint32 etype;
+
+	res = corlib = mono_get_corlib ();
+
+	switch (type->type) {
+	case MONO_TYPE_BOOLEAN:
+		etype = mono_typedef_from_name (corlib, "Boolean", "System", NULL);
+		break;
+	case MONO_TYPE_CHAR:
+		etype = mono_typedef_from_name (corlib, "Char", "System", NULL); 
+		break;
+	case MONO_TYPE_I1:
+		etype = mono_typedef_from_name (corlib, "Byte", "System", NULL); 
+		break;
+	case MONO_TYPE_I2:
+		etype = mono_typedef_from_name (corlib, "Int16", "System", NULL); 
+		break;
+	case MONO_TYPE_U2:
+		etype = mono_typedef_from_name (corlib, "UInt16", "System", NULL); 
+		break;
+	case MONO_TYPE_I4:
+		etype = mono_typedef_from_name (corlib, "Int32", "System", NULL); 
+		break;
+	case MONO_TYPE_U4:
+		etype = mono_typedef_from_name (corlib, "UInt32", "System", NULL); 
+		break;
+	case MONO_TYPE_I8:
+		etype = mono_typedef_from_name (corlib, "Int64", "System", NULL); 
+		break;
+	case MONO_TYPE_U8:
+		etype = mono_typedef_from_name (corlib, "UInt64", "System", NULL); 
+		break;
+	case MONO_TYPE_R8:
+		etype = mono_typedef_from_name (corlib, "Double", "System", NULL); 
+		break;
+	case MONO_TYPE_STRING:
+		etype = mono_typedef_from_name (corlib, "String", "System", NULL); 
+		break;
+	case MONO_TYPE_CLASS:
+		etype = type->data.token;
+		res = image;
+		break;
+	default:
+		g_warning ("implement me %08x\n", type->type);
+		g_assert_not_reached ();
+	}
+	
+	*rimage = res;
+	return etype;
+}
+
+/**
+ * @image: context where the image is created
+ * @type_spec:  typespec token
+ * @at: an optional pointer to return the array type
+ */
+static MonoClass *
+mono_class_create_from_typespec (MonoImage *image, guint32 type_spec)
+{
+	MonoMetadata *m = &image->metadata;
+	guint32 idx = mono_metadata_token_index (type_spec);
+	MonoTableInfo *t;
+	guint32 cols [MONO_TYPESPEC_SIZE];       
+	const char *ptr;
+	guint32 len, etype;
+	MonoType *type;
+	MonoClass *class;
+	MonoImage *rimage;
+
+	t = &m->tables [MONO_TABLE_TYPESPEC];
+	
+	mono_metadata_decode_row (t, idx-1, cols, MONO_TYPESPEC_SIZE);
+	ptr = mono_metadata_blob_heap (m, cols [MONO_TYPESPEC_SIGNATURE]);
+	len = mono_metadata_decode_value (ptr, &ptr);
+	type = mono_metadata_parse_type (m, ptr, &ptr);
+
+	switch (type->type) {
+	case MONO_TYPE_ARRAY:
+		etype = mono_type_to_tydedef (image, type->data.array->type, &rimage);
+		class = mono_array_class_get (rimage, etype, type->data.array->rank);
+		break;
+	case MONO_TYPE_SZARRAY:
+		g_assert (!type->custom_mod);
+		etype = mono_type_to_tydedef (image, type->data.type, &rimage);
+		class = mono_array_class_get (rimage, etype, 1);
+		break;
+	default:
+		g_assert_not_reached ();		
+	}
+
+	mono_metadata_free_type (type);
+	
+	return class;
+}
+
+MonoClass *
+mono_array_class_get (MonoImage *image, guint32 etype, guint32 rank)
+{
+	MonoClass *class, *eclass;
+	static MonoClass *parent = NULL;
+	MonoArrayClass *aclass;
+	guint32 esize, key;
+
+	g_assert (rank <= 255);
+
+	if (!parent) {
+		guint32 arr_token;
+		MonoImage *corlib;
+
+		mono_get_array_class_info (&arr_token, &corlib);
+		parent = mono_class_get (corlib, arr_token);
+		g_assert (parent != NULL);
+	}
+
+	eclass = mono_class_get (image, etype);
+	g_assert (eclass != NULL);
+
+	image = eclass->image;
+
+	esize = eclass->instance_size;
+
+	g_assert (!eclass->type_token ||
+		  mono_metadata_token_table (eclass->type_token) == MONO_TABLE_TYPEDEF);
+	
+	key = ((rank & 0xff) << 24) | (eclass->type_token & 0xffffff);
+	if ((class = g_hash_table_lookup (image->array_cache, GUINT_TO_POINTER (key))))
+		return class;
+	
+	if (eclass->valuetype)
+		esize -= sizeof (MonoObject);
+
+	aclass = g_new0 (MonoArrayClass, 1);
+	class = (MonoClass *)aclass;
+       
+	class->image = image;
+	class->type_token = 0;
+	class->flags = TYPE_ATTRIBUTE_CLASS;
+	class->parent = parent;
+	class->instance_size = class->parent->instance_size;
+	class->class_size = sizeof (MonoArrayClass);
+	
+	aclass->rank = rank;
+	aclass->etype_token = eclass->type_token;
+	aclass->esize = esize;
+
+	g_hash_table_insert (image->array_cache, GUINT_TO_POINTER (key), class);
+	return class;
+}
+
 /*
  * Auxiliary routine to mono_class_get_field
  *
@@ -243,43 +434,11 @@ mono_class_get_field (MonoClass *class, guint32 field_token)
 	return mono_class_get_field_idx (class, idx - 1);
 }
 
-void
-typedef_from_typeref (MonoImage *image, guint32 type_token, MonoImage **rimage, guint32 *index)
-{
-	guint32 cols[MONO_TYPEDEF_SIZE];
-	MonoMetadata *m = &image->metadata;
-	MonoTableInfo  *t = &m->tables[MONO_TABLE_TYPEREF];
-	guint32 idx, i;
-	const char *name, *nspace;
-	
-	mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, 3);
-	g_assert ((cols [0] & 0x3) == 2);
-	idx = cols [0] >> 2;
-	name = mono_metadata_string_heap (m, cols [1]);
-	nspace = mono_metadata_string_heap (m, cols [2]);
-	/* load referenced assembly */
-	image = image->references [idx-1]->image;
-	m = &image->metadata;
-	t = &m->tables [MONO_TABLE_TYPEDEF];
-	/* dumb search for now */
-	for (i=0; i < t->rows; ++i) {
-		mono_metadata_decode_row (t, i, cols, MONO_TYPEDEF_SIZE);
-
-		if (!strcmp (name, mono_metadata_string_heap (m, cols [1])) &&
-		    !strcmp (nspace, mono_metadata_string_heap (m, cols [2]))) {
-			*rimage = image;
-			*index = i + 1;
-			return;
-		}
-	}
-	g_assert_not_reached ();
-	
-}
-
 /**
  * mono_class_get:
  * @image: the image where the class resides
  * @type_token: the token for the class
+ * @at: an optional pointer to return the array element type
  *
  * Returns: the MonoClass that represents @type_token in @image
  */
@@ -288,23 +447,26 @@ mono_class_get (MonoImage *image, guint32 type_token)
 {
 	MonoClass *class;
        
-	if ((type_token & 0xff000000) == MONO_TOKEN_TYPE_DEF 
-					&& (class = g_hash_table_lookup (image->class_cache, GUINT_TO_POINTER (type_token))))
-			return class;
-
 	switch (type_token & 0xff000000){
 	case MONO_TOKEN_TYPE_DEF:
+		if ((class = g_hash_table_lookup (image->class_cache, 
+						  GUINT_TO_POINTER (type_token))))
+			return class;
+
 		class = mono_class_create_from_typedef (image, type_token);
 		break;
 		
 	case MONO_TOKEN_TYPE_REF: {
 		typedef_from_typeref (image, type_token, &image, &type_token);
-		class = mono_class_create_from_typedef (image, type_token);
-		break;
+		return mono_class_get (image, type_token);
 	}
 	case MONO_TOKEN_TYPE_SPEC:
-		g_error ("Can not handle class creation of TypeSpecs yet");
-		
+		if ((class = g_hash_table_lookup (image->class_cache, 
+						  GUINT_TO_POINTER (type_token))))
+			return class;
+
+		class = mono_class_create_from_typespec (image, type_token);
+		break;
 	default:
 		g_assert_not_reached ();
 	}

+ 17 - 2
mono/metadata/class.h

@@ -4,6 +4,8 @@
 #include <mono/metadata/metadata.h>
 #include <mono/metadata/image.h>
 
+#define MONO_CLASS_IS_ARRAY(c) (c->type_token == 0)
+
 typedef struct {
 	MonoFieldType *type;
 	int            offset;
@@ -17,6 +19,7 @@ struct _MonoClass {
 	guint32    type_token;
 
 	guint inited : 1;
+	guint valuetype : 1;
 
 	MonoClass *parent;
 	
@@ -44,8 +47,20 @@ struct _MonoClass {
 	 */
 };
 
-MonoClass *mono_class_get       (MonoImage *image, guint32 type_token);
+typedef struct {
+	MonoClass class;
+	guint32 rank;        /* array dimension */
+	guint32 etype_token; /* element type token */
+	guint32 esize;       /* element size */	
+} MonoArrayClass;
+
+MonoClass *
+mono_class_get       (MonoImage *image, guint32 type_token);
+
+MonoClass *
+mono_array_class_get (MonoImage *image, guint32 etype, guint32 rank);
 
-MonoClassField *mono_class_get_field (MonoClass *class, guint32 field_token);
+MonoClassField *
+mono_class_get_field (MonoClass *class, guint32 field_token);
 
 #endif /* _MONO_CLI_CLASS_H_ */

+ 1 - 0
mono/metadata/image.c

@@ -324,6 +324,7 @@ do_mono_image_open (const char *fname, enum MonoImageOpenStatus *status)
 
 	image->method_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
 	image->class_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
+	image->array_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
 
 	header = &iinfo->cli_header;
 		

+ 6 - 0
mono/metadata/image.h

@@ -32,6 +32,12 @@ struct _MonoImage {
 	GHashTable *method_cache;
 	GHashTable *class_cache;
 
+	/*
+	 * Indexed by ((rank << 24) | (typedef & 0xffffff)), which limits us to a
+	 * maximal rank of 255
+	 */
+	GHashTable *array_cache;
+
 	/*
 	 * user_info is a public field and is not touched by the
 	 * metadata engine

+ 123 - 21
mono/metadata/loader.c

@@ -65,13 +65,57 @@ mono_typedef_from_name (MonoImage *image, const char *name,
 				&& strcmp (nspace, mono_metadata_string_heap (m, cols [MONO_TYPEDEF_NAMESPACE])) == 0) {
 			if (mlist)
 				*mlist = cols [MONO_TYPEDEF_METHOD_LIST];
-			return i + 1;
+			return MONO_TOKEN_TYPE_DEF | (i + 1);
 		}
 	}
 	g_assert_not_reached ();
 	return 0;
 }
 
+MonoImage *
+mono_get_corlib ()
+{
+	static MonoImage *corlib = NULL;
+	MonoAssembly *ass;
+	enum MonoImageOpenStatus status = MONO_IMAGE_OK;
+
+	if (!corlib) {
+		ass = mono_assembly_open (CORLIB_NAME, NULL, &status);
+		g_assert (status == MONO_IMAGE_OK);
+		g_assert (ass != NULL);
+		g_assert (ass->image != NULL);
+		
+		corlib = ass->image;
+	}
+
+	return corlib;
+}
+
+/**
+ * mono_get_array_class_info:
+ * @ttoken: pointer to location to store type definition token
+ * @cl: pointer where image will be stored
+ *
+ * This routine locates information about the System.Array class. A reference
+ * to the image containing the class is returned in @cl. The type definition 
+ * token is returned in @ttoken. 
+ */
+void
+mono_get_array_class_info (guint *ttoken, MonoImage **cl)
+{
+	static guint32 arr_token = 0;
+	static MonoImage *corlib;
+
+	if (!arr_token) {
+		corlib = mono_get_corlib ();		
+		arr_token = mono_typedef_from_name (corlib, "Array", "System", NULL);
+		g_assert (arr_token != 0);
+	}
+
+	*ttoken = arr_token;
+	*cl = corlib;
+}
+
 /**
  * mono_get_string_class_info:
  * @ttoken: pointer to location to store type definition token
@@ -88,8 +132,6 @@ guint32
 mono_get_string_class_info (guint *ttoken, MonoImage **cl)
 {
 	static guint32 ctor = 0, tt = 0;
-	enum MonoImageOpenStatus status = MONO_IMAGE_OK; 
-	MonoAssembly *ass;
 	static MonoImage *corlib;
 	MonoMetadata *m;
 	MonoTableInfo *t;
@@ -104,13 +146,8 @@ mono_get_string_class_info (guint *ttoken, MonoImage **cl)
 		return ctor;
 	}
 
-	ass = mono_assembly_open (CORLIB_NAME, NULL, &status);
-	g_assert (status == MONO_IMAGE_OK);
-	g_assert (ass != NULL);
+	*cl = corlib = mono_get_corlib ();		
 	
-	*cl = corlib = ass->image;
-	g_assert (corlib != NULL);
-       
 	m = &corlib->metadata;
 	t = &m->tables [MONO_TABLE_TYPEDEF];
 
@@ -165,8 +202,8 @@ mono_get_string_class_info (guint *ttoken, MonoImage **cl)
 	return ctor;
 }
 
-static void
-methoddef_from_memberref (MonoImage *image, guint32 index, MonoImage **rimage, guint32 *rindex)
+static MonoMethod *
+method_from_memberref (MonoImage *image, guint32 index)
 {
 	MonoMetadata *m = &image->metadata;
 	MonoTableInfo *tables = m->tables;
@@ -220,9 +257,7 @@ methoddef_from_memberref (MonoImage *image, guint32 index, MonoImage **rimage, g
 				if (strcmp (mname, mono_metadata_string_heap (m, cols [MONO_METHOD_NAME])) == 0 
 						&& sig_len == msig_len
 						&& strncmp (sig, msig, sig_len) == 0) {
-					*rimage = image;
-					*rindex = i + 1;
-					return;
+					return mono_get_method (image, MONO_TOKEN_METHOD_DEF | (i + 1));
 				}
 			}
 			g_assert_not_reached ();
@@ -232,9 +267,66 @@ methoddef_from_memberref (MonoImage *image, guint32 index, MonoImage **rimage, g
 		}
 		break;
 	}
+	case MEMBERREF_PARENT_TYPESPEC: {
+		MonoMethodSignature *ms;
+		guint32 bcols [MONO_TYPESPEC_SIZE];
+		const char *ptr;
+		guint32 len;
+		MonoType *type;
+		MonoMethod *result;
+
+		mono_metadata_decode_row (&tables [MONO_TABLE_TYPESPEC], nindex - 1, 
+					  bcols, MONO_TYPESPEC_SIZE);
+		ptr = mono_metadata_blob_heap (m, bcols [MONO_TYPESPEC_SIGNATURE]);
+		len = mono_metadata_decode_value (ptr, &ptr);	
+		type = mono_metadata_parse_type (m, ptr, &ptr);
+
+		if (type->type != MONO_TYPE_ARRAY)
+			g_assert_not_reached ();		
+
+		ms = mono_metadata_parse_method_signature (m, 0, sig, &sig);
+
+		result = (MonoMethod *)g_new0 (MonoMethod, 1);
+		result->image = image;
+		result->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
+		result->signature = ms;
+		
+		if (!strcmp (mname, ".ctor")) { 
+			g_assert (ms->hasthis);
+			if (type->data.array->rank == ms->param_count) {
+				result->addr = mono_lookup_internal_call ("__array_ctor");
+				return result;
+			} else if ((type->data.array->rank * 2) == ms->param_count) {
+				result->addr = mono_lookup_internal_call ("__array_bound_ctor");
+				return result;			
+			} else 
+				g_assert_not_reached ();
+		}
+
+		if (!strcmp (mname, "Set")) {
+			g_assert (ms->hasthis);
+			g_assert (type->data.array->rank + 1 == ms->param_count);
+
+			result->addr = mono_lookup_internal_call ("__array_Set");
+			return result;
+		}
+
+		if (!strcmp (mname, "Get")) {
+			g_assert (ms->hasthis);
+			g_assert (type->data.array->rank == ms->param_count);
+
+			result->addr = mono_lookup_internal_call ("__array_Get");
+			return result;
+		}
+
+		g_assert_not_reached ();
+		break;
+	}
 	default:
 		g_assert_not_reached ();
 	}
+
+	return NULL;
 }
 
 static ffi_type *
@@ -356,28 +448,36 @@ mono_get_method (MonoImage *image, guint32 token)
 	int table = mono_metadata_token_table (token);
 	int index = mono_metadata_token_index (token);
 	MonoTableInfo *tables = m->tables;
-	const char *loc, *name;
-	const char *sig = NULL;
+	const char *loc, *sig = NULL;
+	char *name;
 	int size;
 	guint32 cols[6];
 
 	if (table == MONO_TABLE_METHOD && (result = g_hash_table_lookup (image->method_cache, GINT_TO_POINTER (token))))
 			return result;
-	
+
 	if (table != MONO_TABLE_METHOD) {
 		g_assert (table == MONO_TABLE_MEMBERREF);
-		methoddef_from_memberref (image, index, &image, &token);
-		return mono_get_method (image, MONO_TOKEN_METHOD_DEF | token);
+		return method_from_memberref (image, index);
 	}
 
 	mono_metadata_decode_row (&tables [table], index - 1, cols, 6);
 
 	if (cols [1] & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
+		MonoTableInfo *t = &m->tables [MONO_TABLE_TYPEDEF];
 		MonoAssembly *corlib;
+		guint32 tdef;
+		guint32 tdcols [MONO_TYPEDEF_SIZE];
 
-		corlib = mono_assembly_open (CORLIB_NAME, NULL, NULL);
+		tdef = mono_metadata_typedef_from_method (m, index - 1) - 1;
+
+		mono_metadata_decode_row (t, tdef, tdcols, MONO_TYPEDEF_SIZE);
 
-		name = mono_metadata_string_heap (m, cols[3]);
+		name = g_strconcat (mono_metadata_string_heap (m, tdcols [MONO_TYPEDEF_NAMESPACE]), ".",
+				    mono_metadata_string_heap (m, tdcols [MONO_TYPEDEF_NAME]), "::", 
+				    mono_metadata_string_heap (m, cols [MONO_METHOD_NAME]), NULL);
+
+		corlib = mono_assembly_open (CORLIB_NAME, NULL, NULL);
 
 		/* all internal calls must be inside corlib */
 		g_assert (corlib->image == image);
@@ -386,6 +486,8 @@ mono_get_method (MonoImage *image, guint32 token)
 
 		result->addr = mono_lookup_internal_call (name);
 
+		g_free (name);
+
 		g_assert (result->addr != NULL);
 
 	} else if (cols [2] & METHOD_ATTRIBUTE_PINVOKE_IMPL) {

+ 2 - 5
mono/metadata/metadata.c

@@ -907,7 +907,7 @@ mono_metadata_parse_typedef_or_ref (MonoMetadata *m, const char *ptr, const char
 	guint table;
 	token = mono_metadata_decode_value (ptr, &ptr);
 
-	switch (table & 0x03) {
+	switch (token & 0x03) {
 	case 0: table = MONO_TABLE_TYPEDEF; break;
 	case 1: table = MONO_TABLE_TYPEREF; break;
 	case 2: table = MONO_TABLE_TYPESPEC; break;
@@ -1658,12 +1658,9 @@ mono_type_size (MonoType *t, gint *align)
 	case MONO_TYPE_SZARRAY:
 	case MONO_TYPE_PTR:
 	case MONO_TYPE_FNPTR:
+	case MONO_TYPE_ARRAY:
 		*align = __alignof__(gpointer);
 		return sizeof (gpointer);
-		
-	case MONO_TYPE_ARRAY:
-		g_error ("FIXME: Add computation of size for MONO_TYPE_ARRAY");
-		break;
 	default:
 		g_error ("type 0x%02x unknown", t->type);
 	}

+ 1 - 1
mono/metadata/metadata.h

@@ -256,7 +256,7 @@ MonoType      *mono_metadata_parse_type        (MonoMetadata      *m,
                					const char     **rptr);
 void           mono_metadata_free_type         (MonoType        *type);
 int            mono_type_size                  (MonoType        *type, 
-				                                int             *alignment);
+						int             *alignment);
 
 MonoFieldType *mono_metadata_parse_field_type  (MonoMetadata      *m,
 						const char      *ptr,

+ 38 - 2
mono/metadata/object.c

@@ -9,6 +9,7 @@
 #include <config.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <mono/cli/cli.h>
 #include <mono/cli/object.h>
 
 /**
@@ -54,12 +55,47 @@ mono_object_free (MonoObject *o)
 MonoObject *
 mono_object_new (MonoImage *image, guint32 type_token)
 {
-	MonoClass *c = mono_class_get (image, type_token);
+	MonoClass *c;
 	MonoObject *o;
-	
+
+	c = mono_class_get (image, type_token);
 	o = mono_object_allocate (c->instance_size);
 	o->klass = c;
 
 	return o;
 }
 
+/*
+ * mono_new_szarray:
+ * @image: image where the object is being referenced
+ * @etype: element type token
+ * @n: number of array elements
+ *
+ * This routine creates a new szarray with @n elements of type @token
+ */
+MonoObject *
+mono_new_szarray (MonoImage *image, guint32 etype, guint32 n)
+{
+	MonoClass *c;
+	MonoObject *o;
+	MonoArrayObject *ao;
+	MonoArrayClass *ac;
+	guint32 esize;
+
+	c = mono_array_class_get (image, etype, 1);
+	g_assert (c != NULL);
+
+	o = mono_object_allocate (c->instance_size);
+	o->klass = c;
+
+	ao = (MonoArrayObject *)o;
+	ac = (MonoArrayClass *)c;
+
+	ao->bounds = g_malloc0 (sizeof (MonoArrayBounds));
+	ao->bounds [0].length = n;
+	ao->bounds [0].lower_bound = 0;
+
+	ao->vector = g_malloc0 (n * ac->esize);
+
+	return o;
+}

+ 15 - 6
mono/metadata/object.h

@@ -7,22 +7,31 @@ typedef struct {
 	MonoClass *klass;
 } MonoObject;
 
+typedef struct {
+	guint32 length;
+	guint32 lower_bound;
+} MonoArrayBounds;
+
 typedef struct {
 	MonoObject obj;
-	gint32 lower_bound;
-	gint32 length;
-	gint32 rank;
 	gpointer vector;
+	MonoArrayBounds *bounds;
 } MonoArrayObject;
 
 typedef struct {
 	MonoObject obj;
-	gint32 length;
 	MonoArrayObject *c_str;
+	gint32 length;
 } MonoStringObject;
 
-MonoObject *mono_object_new  (MonoImage *image, guint32 type_token);
-void        mono_object_free (MonoObject *o);
+MonoObject *
+mono_object_new       (MonoImage *image, guint32 type_token);
+
+MonoObject *
+mono_new_szarray      (MonoImage *image, guint32 etype, guint32 n);
+
+void       
+mono_object_free      (MonoObject *o);
 		      
 #endif
 

+ 71 - 4
mono/tests/array.cs

@@ -1,8 +1,66 @@
+using System;
+using System.Runtime.InteropServices;
+
 public class Test {
 
+	[DllImport("cygwin1.dll", EntryPoint="puts", CharSet=CharSet.Ansi)]
+	public static extern int puts (string name);
+
+	public static int jagged () {
+		int[][] j2 = new int [3][];
+
+		// does not work 
+		// j2 [0] = new int[] {1, 2, 3};
+		// j2 [1] = new int[] {1, 2, 3, 4, 5, 6};
+		// j2 [2] = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9};
+
+		j2 [0] = new int[3];
+		j2 [1] = new int[6];
+		j2 [2] = new int[9];
+
+		for (int i = 0; i < j2.Length; i++)
+			for (int j = 0; j < (i+1)*3; j++)
+				j2 [i][j] = j;
+
+		for (int i = 0; i < j2.Length; i++)
+			for (int j = 0; j < (i+1)*3; j++)
+				if (j2 [i][j] != j)
+					return 1;
+		return 0;
+	}
+
+	public static int stest () {
+		string[] sa = new string[32];
+
+		sa [0] = "This";
+		sa [2] = "is";
+		sa [10] = "a";
+		sa [20] = "stupid";
+		sa [21] = "Test";
+
+		for (int i = 0; i < sa.Length; i++)
+			if (sa [i] != null)
+				puts (sa [i]);
+		
+		return 0;
+	}
+	
+	public static int atest2 () {
+		int[,] ia = new int[32,32];
+
+		for (int i = 0; i <ia.GetLength (0); i++)
+			ia [i,i] = i*i;
+
+		for (int i = 0; i <ia.GetLength (0); i++)
+			if (ia [i,i] != i*i)
+				return 1;
+
+		return 0;
+	}
+	
 	public static int Main () {
 		int[] ia = new int[32];
-		
+
 		for (int i = 0; i <ia.Length; i++)
 			ia [i] = i*i;
 
@@ -12,9 +70,18 @@ public class Test {
 		
 		if (ia.Rank != 1)
 			return 1;
-
-		// test Clone
-
+		
+		if (atest2 () != 0)
+			return 1;
+		if (atest2 () != 0)
+			return 1;
+		
+		if (stest () != 0)
+			return 1;
+		
+		if (jagged () != 0)
+			return 1;
+		
 
 		if (ia.GetValue (2) == null)
 			return 1;