Просмотр исходного кода

2001-07-23 Miguel de Icaza <[email protected]>

	* interp.c (newobj): Added function to handle newobj opcode.

2001-07-23  Miguel de Icaza  <[email protected]>

	* object.h, object.c, class.h, class.c: Implemented the beginning
	of the object system. x

2001-07-23  Miguel de Icaza  <[email protected]>

	* metadata.c (mono_metadata_parse_field_type): Implement.
	(do_mono_metadata_parse_type): Split engine from
	mono_metadata_parse_type, so that we can create smaller structures
	for things that just have one pointer to the MonoType (look at
	the MonoFieldType)

svn path=/trunk/mono/; revision=312
Miguel de Icaza 24 лет назад
Родитель
Сommit
3cbb51830a

+ 8 - 4
mono/cli/Makefile.am

@@ -2,10 +2,14 @@ lib_LIBRARIES = libmonocli.a
 
 INCLUDES = $(GLIB_CFLAGS) -I$(top_srcdir)
 
-libmonocli_a_SOURCES = \
-	loader.c
+libmonocli_a_SOURCES = 		\
+	class.c			\
+	loader.c		\
+	object.c
 
 libmonocliincludedir = $(includir)/mono/cli
 
-libmonocliinclude_HEADERS = \
-	cli.h
+libmonocliinclude_HEADERS = 	\
+	cli.h			\
+	object.h		\
+	types.h

+ 304 - 0
mono/cli/class.c

@@ -0,0 +1,304 @@
+/*
+ * class.c: Class management for the Mono runtime
+ *
+ * Author:
+ *   Miguel de Icaza ([email protected])
+ *
+ * (C) 2001 Ximian, Inc.
+ *
+ * Possible Optimizations:
+ *     in mono_class_create, do not allocate the class right away,
+ *     but wait until you know the size of the FieldMap, so that
+ *     the class embeds directly the FieldMap after the vtable.
+ *
+ * 
+ */
+#include <config.h>
+#include <glib.h>
+#include <stdio.h>
+#include <mono/metadata/image.h>
+#include <mono/metadata/cil-coff.h>
+#include <mono/metadata/metadata.h>
+#include <mono/metadata/tabledefs.h>
+#include <mono/metadata/tokentype.h>
+#include <mono/cli/class.h>
+#include <mono/cli/types.h>
+#include <mono/cli/object.h>
+
+static GHashTable *class_hash;
+
+#define CSIZE(x) (sizeof (x) / 4)
+
+/*
+ * mono_field_type_size:
+ * @t: the type to return the size of
+ *
+ * Returns: the number of bytes required to hold an instance of this
+ * type in memory
+ */
+int
+mono_field_type_size (MonoFieldType *ft)
+{
+	MonoType *t = &ft->type;
+
+	switch (t->type){
+	case ELEMENT_TYPE_BOOLEAN:
+		return sizeof (m_boolean);
+		
+	case ELEMENT_TYPE_CHAR:
+		return sizeof (m_char);
+		
+	case ELEMENT_TYPE_I1:
+	case ELEMENT_TYPE_U1:
+		return 1;
+		
+	case ELEMENT_TYPE_I2:
+	case ELEMENT_TYPE_U2:
+		return 2;
+		
+	case ELEMENT_TYPE_I4:
+	case ELEMENT_TYPE_U4:
+	case ELEMENT_TYPE_R4:
+		return 4;
+		
+	case ELEMENT_TYPE_I8:
+	case ELEMENT_TYPE_U8:
+	case ELEMENT_TYPE_R8:
+		return 8;
+		
+	case ELEMENT_TYPE_I:
+		return sizeof (m_i);
+		
+	case ELEMENT_TYPE_U:
+		return sizeof (m_u);
+		
+	case ELEMENT_TYPE_STRING:
+		return sizeof (m_string);
+		
+	case ELEMENT_TYPE_OBJECT:
+		return sizeof (m_object);
+		
+	case ELEMENT_TYPE_VALUETYPE:
+		g_error ("FIXME: Add computation of size for ELEMENT_TYPE_VALUETYPE");
+		
+	case ELEMENT_TYPE_CLASS:
+		g_error ("FIXME: Add computation of size for ELEMENT_TYPE_CLASS");
+		break;
+		
+	case ELEMENT_TYPE_SZARRAY:
+		g_error ("FIXME: Add computation of size for ELEMENT_TYPE_SZARRAY");
+		break;
+		
+	case ELEMENT_TYPE_PTR:
+		g_error ("FIXME: Add computation of size for ELEMENT_TYPE_PTR");
+		break;
+		
+	case ELEMENT_TYPE_FNPTR:
+		g_error ("FIXME: Add computation of size for ELEMENT_TYPE_FNPTR");
+		break;
+		
+	case ELEMENT_TYPE_ARRAY:
+		g_error ("FIXME: Add computation of size for ELEMENT_TYPE_ARRAY");
+		break;
+	default:
+		g_error ("type 0x%02x unknown", t->type);
+	}
+	return 0;
+}
+
+/** 
+ * class_compute_field_layout:
+ * @m: pointer to the metadata.
+ * @class: The class to initialize
+ *
+ * Initializes the class->fields.
+ *
+ * Currently we only support AUTO_LAYOUT, and do not even try to do
+ * a good job at it.  This is temporary to get the code for Paolo.
+ */
+static void
+class_compute_field_layout (metadata_t *m, MonoClass *class)
+{
+	const int top = class->field.count;
+	guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
+	metadata_tableinfo_t *t = &m->tables [META_TABLE_FIELD];
+	int instance_size = sizeof (MonoObject);
+	int i;
+	
+	/*
+	 * Fetch all the field information.
+	 */
+	for (i = 0; i < top; i++){
+		const char *sig;
+		guint32 cols [3];
+		int idx = class->field.first + i;
+		
+		mono_metadata_decode_row (t, idx, cols, CSIZE (cols));
+		sig = mono_metadata_blob_heap (m, cols [2]);
+		
+		class->fields [i].type = mono_metadata_parse_field_type (
+			m, sig, &sig);
+		class->fields [i].flags = cols [0];
+	}
+
+	/*
+	 * Compute field layout and total size.
+	 */
+	switch (layout){
+	case TYPE_ATTRIBUTE_AUTO_LAYOUT:
+		for (i = 0; i < top; i++){
+			int size;
+			
+			class->fields [i].offset = instance_size;
+			
+			size = mono_field_type_size (class->fields [i].type);
+			size += (size % 4);
+			instance_size += size;
+		}
+		break;
+		
+	case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
+		for (i = 0; i < top; i++){
+			int size;
+			
+			class->fields [i].offset = instance_size;
+			
+			size = mono_field_type_size (class->fields [i].type);
+			size += (size % 4);
+			instance_size += size;
+		}
+		break;
+		
+	case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
+		g_error ("TODO: Explicit layout not supported yet");
+	}
+}
+
+/**
+ * @image: context where the image is created
+ * @tidx:  index of the type to create
+ */
+static MonoClass *
+mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
+{
+	cli_image_info_t *iinfo = image->image_info;
+	metadata_t *m = &iinfo->cli_metadata;
+	metadata_tableinfo_t *tt = &m->tables [META_TABLE_TYPEDEF];
+	MonoClass *class;
+	guint32 cols [6];
+	guint tidx = type_token & 0xffffff;
+	
+	class = g_new0 (MonoClass, 1);
+	class->image = image;
+	class->type_token = tidx;
+
+	mono_metadata_decode_row (tt, tidx, cols, CSIZE (cols));
+
+	class->flags = cols [0];
+	
+	/*
+	 * Compute the field and method lists
+	 */
+	class->field.first  = cols [4] - 1;
+	class->method.first = cols [5] - 1;
+
+	if (tt->rows > tidx + 1){
+		guint32 cols_next [6];
+		
+		mono_metadata_decode_row (tt, tidx + 1, cols_next, CSIZE (cols_next));
+		class->field.last  = cols_next [4] - 1;
+		class->method.last = cols_next [5] - 1;
+	} else {
+		class->field.last  = m->tables [META_TABLE_FIELD].rows;
+		class->method.last = m->tables [META_TABLE_METHOD].rows;
+	}
+
+	if (cols [4] && cols [4] <= m->tables [META_TABLE_FIELD].rows)
+		class->field.count = class->field.last - class->field.first;
+	else
+		class->field.count = 0;
+
+	if (cols [5] <= m->tables [META_TABLE_METHOD].rows)
+		class->method.count = class->method.last - class->method.first;
+	else
+		class->method.count = 0;
+
+	/*
+	 * Computes the size used by the fields, and their locations
+	 */
+	if (class->field.count > 0){
+		class->fields = g_new (MonoClassFields, class->field.count);
+		class_compute_field_layout (m, class);
+	}
+
+	return class;
+}
+
+/**
+ * mono_class_get:
+ * @image: the image where the class resides
+ * @type_token: the token for the class
+ *
+ * Returns: the MonoClass that represents @type_token in @image
+ */
+MonoClass *
+mono_class_get (MonoImage *image, guint32 type_token)
+{
+	MonoClass *class, hash_lookup;
+
+	hash_lookup.image = image;
+	hash_lookup.type_token = type_token;
+	
+	class = g_hash_table_lookup (class_hash, &hash_lookup);
+
+	if (class)
+		return class;
+
+	switch (type_token & 0xff000000){
+	case TOKEN_TYPE_TYPE_DEF:
+		class = mono_class_create_from_typedef (image, type_token);
+		break;
+		
+	case TOKEN_TYPE_TYPE_REF:
+		g_error ("Can not handle class creation of TypeRefs yet");
+		
+	default:
+		g_assert_not_reached ();
+	}
+	
+	g_hash_table_insert (class_hash, class, class);
+
+	return class;
+}
+
+static guint
+mono_class_hash (gconstpointer p)
+{
+	MonoClass *c = (MonoClass *) p;
+
+	return (((guint32)(c->image)) ^ c->type_token);
+}
+
+static gint
+mono_class_equal (gconstpointer ap, gconstpointer bp)
+{
+	MonoClass *a = (MonoClass *) ap;
+	MonoClass *b = (MonoClass *) bp;
+
+	if ((a->image == b->image) && (a->type_token == b->type_token))
+		return TRUE;
+
+	return FALSE;
+}
+
+/**
+ * mono_class_init:
+ *
+ * Initializes the runtime class system
+ */
+void
+mono_class_init (void)
+{
+	class_hash = g_hash_table_new (
+		mono_class_hash, mono_class_equal);
+}

+ 43 - 0
mono/cli/class.h

@@ -0,0 +1,43 @@
+#ifndef _MONO_CLI_CLASS_H_
+#define _MONO_CLI_CLASS_H_
+
+#include <mono/metadata/metadata.h>
+#include <mono/metadata/image.h>
+
+typedef struct {
+	MonoFieldType *type;
+	int            offset;
+	guint32        flags;
+} MonoClassFields;
+	
+typedef struct {
+	MonoImage *image;
+	guint32    type_token;
+
+	/*
+	 * Computed object instance size, total.
+	 */
+	int        instance_size;
+
+
+	/*
+	 * From the TypeDef table
+	 */
+	guint32    flags;
+	struct {
+		guint32 first, last;
+		int count;
+	} field, method;
+
+	/*
+	 * Field information: Type and location from object base
+	 */
+	MonoClassFields *fields;
+} MonoClass;
+
+MonoClass *mono_class_get       (MonoImage *image, guint32 type_token);
+void       mono_class_init      (void);
+
+int        mono_field_type_size (MonoFieldType *ft);
+
+#endif /* _MONO_CLI_CLASS_H_ */

+ 3 - 0
mono/cli/cli.h

@@ -14,6 +14,9 @@ MonoMethod        *mono_get_method    (MonoImage *image, guint32 token);
 void               mono_free_method   (MonoMethod *method);
 
 #include <mono/metadata/image.h>
+
 MonoImage         *mono_load_image    (const char *fname, enum MonoImageOpenStatus *status);
 
+#include <mono/cli/object.h>
+
 #endif

+ 43 - 1
mono/cli/object.c

@@ -7,8 +7,42 @@
  * (C) 2001 Ximian, Inc.
  */
 #include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
 #include <mono/cli/object.h>
 
+/**
+ * mono_object_allocate:
+ * @size: number of bytes to allocate
+ *
+ * This is a very simplistic routine until we have our GC-aware
+ * memory allocator. 
+ *
+ * Returns: an allocated object of size @size, or NULL on failure.
+ */
+static void *
+mono_object_allocate (size_t size)
+{
+	void *o = calloc (1, size);
+
+	return o;
+}
+
+/**
+ * mono_object_free:
+ *
+ * Frees the memory used by the object.  Debugging purposes
+ * only, as we will have our GC system.
+ */
+void
+mono_object_free (MonoObject *o)
+{
+	MonoClass *c = o->klass;
+	
+	memset (o, 0, c->instance_size);
+	free (o);
+}
+
 /**
  * mono_object_new:
  * @image: Context where the type_token is hosted
@@ -17,7 +51,15 @@
  * Returns: A newly created object whose definition is
  * looked up using @type_token in the @image image
  */
-void *
+MonoObject *
 mono_object_new (MonoImage *image, guint32 type_token)
 {
+	MonoClass *c = mono_class_get (image, type_token);
+	MonoObject *o;
+	
+	o = mono_object_allocate (c->instance_size);
+	o->klass = c;
+
+	return o;
 }
+

+ 4 - 3
mono/cli/object.h

@@ -1,13 +1,14 @@
 #ifndef _MONO_CLI_OBJECT_H_
 #define _MONO_CLI_OBJECT_H_
 
-typedef struct {
-} MonoClass;
+#include <mono/cli/class.h>
 
 typedef struct {
 	MonoClass *klass;
 } MonoObject;
 
-void *mono_object_new (MonoImage *image, guint32 type_token);
+MonoObject *mono_object_new  (MonoImage *image, guint32 type_token);
+void        mono_object_free (MonoObject *o);
 		      
 #endif
+

+ 28 - 0
mono/cli/types.h

@@ -0,0 +1,28 @@
+#ifndef _MONO_CLI_TYPES_H_
+#define _MONO_CLI_TYPES_H_
+
+/*
+ * 32 bit computer definitions.
+ */
+
+typedef char           m_boolean;
+typedef short          m_char;
+typedef char           m_i1;
+typedef unsigned char  m_u1;
+typedef short          m_i2;
+typedef unsigned short m_u2;
+typedef int            m_i4;
+typedef unsigned int   m_u4;
+typedef long           m_i8;
+typedef unsigned long  m_u8;
+typedef float          m_r4;
+typedef double         m_r8;
+typedef int            m_i;
+typedef unsigned int   m_u;
+typedef void *         m_string;
+typedef void *         m_object;
+typedef void *         m_class;
+typedef void *         m_ptr;
+typedef void *         m_fnptr;
+
+#endif

+ 72 - 4
mono/interpreter/interp.c

@@ -4,8 +4,9 @@
  *
  * interp.c: Interpreter for CIL byte codes
  *
- * Author:
+ * Authors:
  *   Paolo Molaro ([email protected])
+ *   Miguel de Icaza ([email protected])
  *
  * (C) 2001 Ximian, Inc.
  */
@@ -30,7 +31,7 @@
 #include <mono/metadata/endian.h>
 #include <mono/metadata/tabledefs.h>
 #include <mono/metadata/blob.h>
-
+#include <mono/metadata/tokentype.h>
 #include <mono/cli/cli.h>
 
 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
@@ -107,6 +108,8 @@ static int count = 0;
 #define SUB_SWITCH case 0xFE:
 #endif
 
+#define CSIZE(x) (sizeof (x) / 4)
+
 static void
 ves_real_abort (int line, MonoImage *image, MonoMethod *mh,
 		const unsigned char *ip, stackval *stack, stackval *sp)
@@ -124,9 +127,65 @@ ves_real_abort (int line, MonoImage *image, MonoMethod *mh,
 		printf ("\t[%d] %d 0x%08x %0.5f\n", sp-stack, sp[-1].type, sp[-1].data.i, sp[-1].data.f);
 	exit (1);
 }
-
 #define ves_abort() ves_real_abort(__LINE__, image, mh, ip, stack, sp)
 
+/*
+ * newobj:
+ * @image: image where the object is being referenced
+ * @token: method token to invoke
+ *
+ * This routine creates a new object based on the class where the
+ * constructor lives.x
+ */
+static MonoObject *
+newobj (MonoImage *image, guint32 token)
+{
+	cli_image_info_t *iinfo = image->image_info;
+	metadata_t *m = &iinfo->cli_metadata;
+	
+	switch (mono_metadata_token_code (token)){
+	case TOKEN_TYPE_METHOD_DEF:
+		g_error ("TOKEN_TYPE_METHOD_DEF not supported in newobj yet");
+		break;
+		
+	case TOKEN_TYPE_MEMBER_REF: {
+		guint32 member_cols [3];
+		guint32 mpr_token, table, idx;
+		
+		mono_metadata_decode_row (
+			&m->tables [META_TABLE_MEMBERREF],
+			mono_metadata_token_index (token) - 1,
+			member_cols, CSIZE (member_cols));
+		mpr_token = member_cols [0];
+		table = mpr_token & 7;
+		idx = mpr_token >> 3;
+		
+		switch (table){
+		case 0: /* TypeDef */
+			return mono_object_new (image, TOKEN_TYPE_TYPE_DEF | idx);
+			
+		case 1: /* TypeRef */
+			return mono_object_new (image, TOKEN_TYPE_TYPE_REF | idx);
+			
+		case 2: /* ModuleRef */
+			g_error ("Unhandled: ModuleRef");
+			
+		case 3: /* MethodDef */
+			g_error ("Unhandled: MethodDef");
+			
+		case 4: /* TypeSpec */
+			g_error ("Unhandled: TypeSepc");
+		}
+		break;
+	}
+	}
+
+	/*
+	 * Failure
+	 */
+	return NULL;
+}
+
 /*
  * Need to optimize ALU ops when natural int == int32 
  *
@@ -698,7 +757,16 @@ ves_exec_method (MonoImage *image, MonoMethod *mh, stackval *args)
 		CASE (CEE_CPOBJ) ves_abort(); BREAK;
 		CASE (CEE_LDOBJ) ves_abort(); BREAK;
 		CASE (CEE_LDSTR) ves_abort(); BREAK;
-		CASE (CEE_NEWOBJ) ves_abort(); BREAK;
+
+		CASE (CEE_NEWOBJ) {
+			MonoObject *o;
+			guint32 token = read32 (ip);
+			
+			o = newobj (image, token);
+			ip += 4;
+			BREAK;
+		}
+		
 		CASE (CEE_CASTCLASS) ves_abort(); BREAK;
 		CASE (CEE_ISINST) ves_abort(); BREAK;
 		CASE (CEE_CONV_R_UN) ves_abort(); BREAK;

+ 8 - 0
mono/metadata/ChangeLog

@@ -1,3 +1,11 @@
+2001-07-23  Miguel de Icaza  <[email protected]>
+
+	* metadata.c (mono_metadata_parse_field_type): Implement. 
+	(do_mono_metadata_parse_type): Split engine from
+	mono_metadata_parse_type, so that we can create smaller structures
+	for things that just have one pointer to the MonoType (look at
+	the MonoFieldType)
+
 2001-07-20  Miguel de Icaza  <[email protected]>
 
 	* metadata.c (mono_metadata_parse_mh): Correct the implementation,

+ 51 - 0
mono/metadata/blob.h

@@ -0,0 +1,51 @@
+/*
+ * blob.h: Definitions used to pull information out of the Blob
+ *
+ */
+#ifndef _MONO_METADATA_BLOB_H_
+#define _MONO_METADATA_BLOB_H_
+
+#define SIGNATURE_HAS_THIS      0x20
+#define SIGNATURE_EXPLICIT_THIS 0x40
+#define SIGNATURE_VARARG        0x05
+
+/*
+ * Encoding for type signatures used in the Metadata
+ */
+typedef enum {
+	ELEMENT_TYPE_END        = 0x00,       /* End of List */
+	ELEMENT_TYPE_VOID       = 0x01,
+	ELEMENT_TYPE_BOOLEAN    = 0x02,
+	ELEMENT_TYPE_CHAR       = 0x03,
+	ELEMENT_TYPE_I1         = 0x04,
+	ELEMENT_TYPE_U1         = 0x05,
+	ELEMENT_TYPE_I2         = 0x06,
+	ELEMENT_TYPE_U2         = 0x07,
+	ELEMENT_TYPE_I4         = 0x08,
+	ELEMENT_TYPE_U4         = 0x09,
+	ELEMENT_TYPE_I8         = 0x0a,
+	ELEMENT_TYPE_U8         = 0x0b,
+	ELEMENT_TYPE_R4         = 0x0c,
+	ELEMENT_TYPE_R8         = 0x0d,
+	ELEMENT_TYPE_STRING     = 0x0e,
+	ELEMENT_TYPE_PTR        = 0x0f,       /* arg: <type> token */
+	ELEMENT_TYPE_BYREF      = 0x10,       /* arg: <type> token */
+	ELEMENT_TYPE_VALUETYPE  = 0x11,       /* arg: <type> token */
+	ELEMENT_TYPE_CLASS      = 0x12,       /* arg: <type> token */
+	ELEMENT_TYPE_ARRAY      = 0x14,       /* type, rank, boundsCount, bound1, loCount, lo1 */
+	ELEMENT_TYPE_TYPEDBYREF = 0x15,
+	ELEMENT_TYPE_I          = 0x18,
+	ELEMENT_TYPE_U          = 0x19,
+	ELEMENT_TYPE_FNPTR      = 0x1b,	      /* arg: full method signature */
+	ELEMENT_TYPE_OBJECT     = 0x1c,
+	ELEMENT_TYPE_SZARRAY    = 0x1d,       /* 0-based one-dim-array */
+	ELEMENT_TYPE_CMOD_REQD  = 0x1f,       /* arg: typedef or typeref token */
+	ELEMENT_TYPE_CMOD_OPT   = 0x20,       /* optional arg: typedef or typref token */
+	ELEMENT_TYPE_INTERNAL   = 0x21,       /* CLR internal type */
+
+	ELEMENT_TYPE_MODIFIER   = 0x40,       /* Or with the following types */
+	ELEMENT_TYPE_SENTINEL   = 0x41,       /* Sentinel for varargs method signature */
+	ELEMENT_TYPE_PINNED     = 0x45,       /* Local var that points to pinned object */
+} ElementTypeEnum;
+
+#endif

+ 304 - 0
mono/metadata/class.c

@@ -0,0 +1,304 @@
+/*
+ * class.c: Class management for the Mono runtime
+ *
+ * Author:
+ *   Miguel de Icaza ([email protected])
+ *
+ * (C) 2001 Ximian, Inc.
+ *
+ * Possible Optimizations:
+ *     in mono_class_create, do not allocate the class right away,
+ *     but wait until you know the size of the FieldMap, so that
+ *     the class embeds directly the FieldMap after the vtable.
+ *
+ * 
+ */
+#include <config.h>
+#include <glib.h>
+#include <stdio.h>
+#include <mono/metadata/image.h>
+#include <mono/metadata/cil-coff.h>
+#include <mono/metadata/metadata.h>
+#include <mono/metadata/tabledefs.h>
+#include <mono/metadata/tokentype.h>
+#include <mono/cli/class.h>
+#include <mono/cli/types.h>
+#include <mono/cli/object.h>
+
+static GHashTable *class_hash;
+
+#define CSIZE(x) (sizeof (x) / 4)
+
+/*
+ * mono_field_type_size:
+ * @t: the type to return the size of
+ *
+ * Returns: the number of bytes required to hold an instance of this
+ * type in memory
+ */
+int
+mono_field_type_size (MonoFieldType *ft)
+{
+	MonoType *t = &ft->type;
+
+	switch (t->type){
+	case ELEMENT_TYPE_BOOLEAN:
+		return sizeof (m_boolean);
+		
+	case ELEMENT_TYPE_CHAR:
+		return sizeof (m_char);
+		
+	case ELEMENT_TYPE_I1:
+	case ELEMENT_TYPE_U1:
+		return 1;
+		
+	case ELEMENT_TYPE_I2:
+	case ELEMENT_TYPE_U2:
+		return 2;
+		
+	case ELEMENT_TYPE_I4:
+	case ELEMENT_TYPE_U4:
+	case ELEMENT_TYPE_R4:
+		return 4;
+		
+	case ELEMENT_TYPE_I8:
+	case ELEMENT_TYPE_U8:
+	case ELEMENT_TYPE_R8:
+		return 8;
+		
+	case ELEMENT_TYPE_I:
+		return sizeof (m_i);
+		
+	case ELEMENT_TYPE_U:
+		return sizeof (m_u);
+		
+	case ELEMENT_TYPE_STRING:
+		return sizeof (m_string);
+		
+	case ELEMENT_TYPE_OBJECT:
+		return sizeof (m_object);
+		
+	case ELEMENT_TYPE_VALUETYPE:
+		g_error ("FIXME: Add computation of size for ELEMENT_TYPE_VALUETYPE");
+		
+	case ELEMENT_TYPE_CLASS:
+		g_error ("FIXME: Add computation of size for ELEMENT_TYPE_CLASS");
+		break;
+		
+	case ELEMENT_TYPE_SZARRAY:
+		g_error ("FIXME: Add computation of size for ELEMENT_TYPE_SZARRAY");
+		break;
+		
+	case ELEMENT_TYPE_PTR:
+		g_error ("FIXME: Add computation of size for ELEMENT_TYPE_PTR");
+		break;
+		
+	case ELEMENT_TYPE_FNPTR:
+		g_error ("FIXME: Add computation of size for ELEMENT_TYPE_FNPTR");
+		break;
+		
+	case ELEMENT_TYPE_ARRAY:
+		g_error ("FIXME: Add computation of size for ELEMENT_TYPE_ARRAY");
+		break;
+	default:
+		g_error ("type 0x%02x unknown", t->type);
+	}
+	return 0;
+}
+
+/** 
+ * class_compute_field_layout:
+ * @m: pointer to the metadata.
+ * @class: The class to initialize
+ *
+ * Initializes the class->fields.
+ *
+ * Currently we only support AUTO_LAYOUT, and do not even try to do
+ * a good job at it.  This is temporary to get the code for Paolo.
+ */
+static void
+class_compute_field_layout (metadata_t *m, MonoClass *class)
+{
+	const int top = class->field.count;
+	guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
+	metadata_tableinfo_t *t = &m->tables [META_TABLE_FIELD];
+	int instance_size = sizeof (MonoObject);
+	int i;
+	
+	/*
+	 * Fetch all the field information.
+	 */
+	for (i = 0; i < top; i++){
+		const char *sig;
+		guint32 cols [3];
+		int idx = class->field.first + i;
+		
+		mono_metadata_decode_row (t, idx, cols, CSIZE (cols));
+		sig = mono_metadata_blob_heap (m, cols [2]);
+		
+		class->fields [i].type = mono_metadata_parse_field_type (
+			m, sig, &sig);
+		class->fields [i].flags = cols [0];
+	}
+
+	/*
+	 * Compute field layout and total size.
+	 */
+	switch (layout){
+	case TYPE_ATTRIBUTE_AUTO_LAYOUT:
+		for (i = 0; i < top; i++){
+			int size;
+			
+			class->fields [i].offset = instance_size;
+			
+			size = mono_field_type_size (class->fields [i].type);
+			size += (size % 4);
+			instance_size += size;
+		}
+		break;
+		
+	case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
+		for (i = 0; i < top; i++){
+			int size;
+			
+			class->fields [i].offset = instance_size;
+			
+			size = mono_field_type_size (class->fields [i].type);
+			size += (size % 4);
+			instance_size += size;
+		}
+		break;
+		
+	case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
+		g_error ("TODO: Explicit layout not supported yet");
+	}
+}
+
+/**
+ * @image: context where the image is created
+ * @tidx:  index of the type to create
+ */
+static MonoClass *
+mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
+{
+	cli_image_info_t *iinfo = image->image_info;
+	metadata_t *m = &iinfo->cli_metadata;
+	metadata_tableinfo_t *tt = &m->tables [META_TABLE_TYPEDEF];
+	MonoClass *class;
+	guint32 cols [6];
+	guint tidx = type_token & 0xffffff;
+	
+	class = g_new0 (MonoClass, 1);
+	class->image = image;
+	class->type_token = tidx;
+
+	mono_metadata_decode_row (tt, tidx, cols, CSIZE (cols));
+
+	class->flags = cols [0];
+	
+	/*
+	 * Compute the field and method lists
+	 */
+	class->field.first  = cols [4] - 1;
+	class->method.first = cols [5] - 1;
+
+	if (tt->rows > tidx + 1){
+		guint32 cols_next [6];
+		
+		mono_metadata_decode_row (tt, tidx + 1, cols_next, CSIZE (cols_next));
+		class->field.last  = cols_next [4] - 1;
+		class->method.last = cols_next [5] - 1;
+	} else {
+		class->field.last  = m->tables [META_TABLE_FIELD].rows;
+		class->method.last = m->tables [META_TABLE_METHOD].rows;
+	}
+
+	if (cols [4] && cols [4] <= m->tables [META_TABLE_FIELD].rows)
+		class->field.count = class->field.last - class->field.first;
+	else
+		class->field.count = 0;
+
+	if (cols [5] <= m->tables [META_TABLE_METHOD].rows)
+		class->method.count = class->method.last - class->method.first;
+	else
+		class->method.count = 0;
+
+	/*
+	 * Computes the size used by the fields, and their locations
+	 */
+	if (class->field.count > 0){
+		class->fields = g_new (MonoClassFields, class->field.count);
+		class_compute_field_layout (m, class);
+	}
+
+	return class;
+}
+
+/**
+ * mono_class_get:
+ * @image: the image where the class resides
+ * @type_token: the token for the class
+ *
+ * Returns: the MonoClass that represents @type_token in @image
+ */
+MonoClass *
+mono_class_get (MonoImage *image, guint32 type_token)
+{
+	MonoClass *class, hash_lookup;
+
+	hash_lookup.image = image;
+	hash_lookup.type_token = type_token;
+	
+	class = g_hash_table_lookup (class_hash, &hash_lookup);
+
+	if (class)
+		return class;
+
+	switch (type_token & 0xff000000){
+	case TOKEN_TYPE_TYPE_DEF:
+		class = mono_class_create_from_typedef (image, type_token);
+		break;
+		
+	case TOKEN_TYPE_TYPE_REF:
+		g_error ("Can not handle class creation of TypeRefs yet");
+		
+	default:
+		g_assert_not_reached ();
+	}
+	
+	g_hash_table_insert (class_hash, class, class);
+
+	return class;
+}
+
+static guint
+mono_class_hash (gconstpointer p)
+{
+	MonoClass *c = (MonoClass *) p;
+
+	return (((guint32)(c->image)) ^ c->type_token);
+}
+
+static gint
+mono_class_equal (gconstpointer ap, gconstpointer bp)
+{
+	MonoClass *a = (MonoClass *) ap;
+	MonoClass *b = (MonoClass *) bp;
+
+	if ((a->image == b->image) && (a->type_token == b->type_token))
+		return TRUE;
+
+	return FALSE;
+}
+
+/**
+ * mono_class_init:
+ *
+ * Initializes the runtime class system
+ */
+void
+mono_class_init (void)
+{
+	class_hash = g_hash_table_new (
+		mono_class_hash, mono_class_equal);
+}

+ 43 - 0
mono/metadata/class.h

@@ -0,0 +1,43 @@
+#ifndef _MONO_CLI_CLASS_H_
+#define _MONO_CLI_CLASS_H_
+
+#include <mono/metadata/metadata.h>
+#include <mono/metadata/image.h>
+
+typedef struct {
+	MonoFieldType *type;
+	int            offset;
+	guint32        flags;
+} MonoClassFields;
+	
+typedef struct {
+	MonoImage *image;
+	guint32    type_token;
+
+	/*
+	 * Computed object instance size, total.
+	 */
+	int        instance_size;
+
+
+	/*
+	 * From the TypeDef table
+	 */
+	guint32    flags;
+	struct {
+		guint32 first, last;
+		int count;
+	} field, method;
+
+	/*
+	 * Field information: Type and location from object base
+	 */
+	MonoClassFields *fields;
+} MonoClass;
+
+MonoClass *mono_class_get       (MonoImage *image, guint32 type_token);
+void       mono_class_init      (void);
+
+int        mono_field_type_size (MonoFieldType *ft);
+
+#endif /* _MONO_CLI_CLASS_H_ */

+ 65 - 5
mono/metadata/metadata.c

@@ -1046,12 +1046,23 @@ mono_metadata_free_method_signature (MonoMethodSignature *method)
 	g_free (method);
 }
 
-/* II 22.2.12 */
-MonoType *
-mono_metadata_parse_type (metadata_t *m, const char *ptr, const char **rptr)
+/* 
+ * do_mono_metadata_parse_type:
+ * @type: MonoType to be filled in with the return value
+ * @
+ * 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
+ * most of the time is just a MonoType, but sometimes might be augmented).
+ *
+ * This routine is used by mono_metadata_parse_type and
+ * mono_metadata_parse_field_type
+ *
+ * This extracts a Type as specified in Partition II (22.2.12) 
+ */
+static void
+do_mono_metadata_parse_type (MonoType *type, metadata_t *m, const char *ptr, const char **rptr)
 {
-	/* should probably be allocated in a memchunk */
-	MonoType *type = g_new0(MonoType, 1);
 	int val;
 	
 	ptr = mono_metadata_decode_value (ptr, &val);
@@ -1093,6 +1104,7 @@ mono_metadata_parse_type (metadata_t *m, const char *ptr, const char **rptr)
 			type->data.mtype = mtype = g_malloc0(sizeof(MonoModifiedType)+(count-1)*sizeof(MonoCustomMod));
 			mtype->num_modifiers = count;
 			count = 0;
+			
 			/* save them this time */
 			while (mono_metadata_parse_custom_mod (m, &(mtype->modifiers[count]), ptr, &ptr))
 				count++;
@@ -1125,6 +1137,25 @@ mono_metadata_parse_type (metadata_t *m, const char *ptr, const char **rptr)
 	
 	if (rptr)
 		*rptr = ptr;
+}
+
+/**
+ * mono_metadata_parse_type:
+ * @m: metadata context to scan
+ * @ptr: pointer to encoded Type stream.
+ * @rptr: the new position in the stream after parsing the type
+ *
+ * Returns: A MonoType structure that has the parsed information
+ * from the type stored at @ptr in the metadata table @m.
+ */
+MonoType *
+mono_metadata_parse_type (metadata_t *m, const char *ptr, const char **rptr)
+{
+	/* should probably be allocated in a memchunk */
+	MonoType *type = g_new0(MonoType, 1);
+
+	do_mono_metadata_parse_type (type, m, ptr, rptr);
+
 	return type;
 }
 
@@ -1297,3 +1328,32 @@ mono_metadata_free_mh (MonoMetaMethodHeader *mh)
 	g_free (mh);
 }
 
+/**
+ * mono_metadata_parse_field_type:
+ * @m: metadata context to extract information from
+ * @ptr: pointer to the field signature
+ *
+ * Parses the field signature, and returns the type information for it. 
+ *
+ * Returns: The MonoFieldType that was extracted from @ptr.
+ */
+MonoFieldType *
+mono_metadata_parse_field_type (metadata_t *m, const char *ptr, const char **rptr)
+{
+	MonoFieldType *ft;
+	int len;
+	
+	ft = g_new (MonoFieldType, 1);
+	ptr = mono_metadata_decode_value (ptr, &len);
+
+	/* FIELD signature == 0x06 */
+	g_assert (*ptr == 0x06);
+	ptr++;
+	len--;
+
+	mono_metadata_parse_custom_mod (m, &ft->custom_mod, ptr, &ptr);
+	do_mono_metadata_parse_type (&ft->type, m, ptr, rptr);
+
+	return ft;
+}
+

+ 33 - 22
mono/metadata/metadata.h

@@ -217,6 +217,7 @@ typedef struct {
 } MonoMetaExceptionHandler;
 
 typedef struct _MonoType MonoType;
+typedef struct _MonoFieldType MonoFieldType;
 typedef struct _MonoArray MonoArray;
 typedef struct _MonoMethodSignature MonoMethodSignature;
 
@@ -254,6 +255,14 @@ struct _MonoType {
 	} data;
 };
 
+/*
+ * A Field Type is a Type that might have an optional Custom Modifier.
+ */
+struct _MonoFieldType {
+	MonoType type;
+	MonoCustomMod custom_mod;
+};
+
 typedef struct {
 	/* maybe use a union here: saves 4 bytes */
 	MonoType *type; /* NULL for VOID */
@@ -290,30 +299,32 @@ typedef struct {
 	GList      *exception_handler_list;
 } MonoMetaMethodHeader;
 
-typedef struct {
-	
-} MonoTypedef;
-
 guint32     mono_metadata_parse_typedef_or_ref (metadata_t      *m,
                                                 const char      *ptr,
                                                 const char     **rptr);
-int         mono_metadata_parse_custom_mod     (metadata_t      *m,
-                                                MonoCustomMod   *dest,
-                                                const char      *ptr,
-                                                const char     **rptr);
-MonoArray  *mono_metadata_parse_array          (metadata_t      *m,
-                                                const char      *ptr,
-                                                const char     **rptr);
-void        mono_metadata_free_array           (MonoArray       *array);
-MonoParam  *mono_metadata_parse_param          (metadata_t      *m,
-                                                int              rettype,
-                                                const char      *ptr,
-                                                const char     **rptr);
-void        mono_metadata_free_param           (MonoParam       *param);
-MonoType   *mono_metadata_parse_type           (metadata_t      *m,
-                                                const char      *ptr,
-                                                const char     **rptr);
-void        mono_metadata_free_type            (MonoType        *type);
+int            mono_metadata_parse_custom_mod  (metadata_t      *m,
+						MonoCustomMod   *dest,
+						const char      *ptr,
+						const char     **rptr);
+MonoArray     *mono_metadata_parse_array       (metadata_t      *m,
+						const char      *ptr,
+						const char     **rptr);
+void           mono_metadata_free_array        (MonoArray       *array);
+MonoParam     *mono_metadata_parse_param       (metadata_t      *m,
+						int              rettype,
+						const char      *ptr,
+						const char     **rptr);
+void           mono_metadata_free_param        (MonoParam       *param);
+MonoType      *mono_metadata_parse_type        (metadata_t      *m,
+               					const char      *ptr,
+               					const char     **rptr);
+void           mono_metadata_free_type         (MonoType        *type);
+
+MonoFieldType *mono_metadata_parse_field_type  (metadata_t      *m,
+						const char      *ptr,
+						const char      **rptr);
+void           mono_metadata_free_field_type   (MonoFieldType   *field_type);
+							
 
 MonoMethodSignature  *mono_metadata_parse_method_signature (metadata_t            *m,
                                                             int                    def,
@@ -334,7 +345,7 @@ void                  mono_metadata_free_mh  (MonoMetaMethodHeader *mh);
  */
 #define mono_metadata_token_table(token) ((token) >> 24)
 
-/*
+ /*
  * Returns the index that a token refers to
  */
 #define mono_metadata_token_index(token) ((token & 0xffffff))

+ 43 - 1
mono/metadata/object.c

@@ -7,8 +7,42 @@
  * (C) 2001 Ximian, Inc.
  */
 #include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
 #include <mono/cli/object.h>
 
+/**
+ * mono_object_allocate:
+ * @size: number of bytes to allocate
+ *
+ * This is a very simplistic routine until we have our GC-aware
+ * memory allocator. 
+ *
+ * Returns: an allocated object of size @size, or NULL on failure.
+ */
+static void *
+mono_object_allocate (size_t size)
+{
+	void *o = calloc (1, size);
+
+	return o;
+}
+
+/**
+ * mono_object_free:
+ *
+ * Frees the memory used by the object.  Debugging purposes
+ * only, as we will have our GC system.
+ */
+void
+mono_object_free (MonoObject *o)
+{
+	MonoClass *c = o->klass;
+	
+	memset (o, 0, c->instance_size);
+	free (o);
+}
+
 /**
  * mono_object_new:
  * @image: Context where the type_token is hosted
@@ -17,7 +51,15 @@
  * Returns: A newly created object whose definition is
  * looked up using @type_token in the @image image
  */
-void *
+MonoObject *
 mono_object_new (MonoImage *image, guint32 type_token)
 {
+	MonoClass *c = mono_class_get (image, type_token);
+	MonoObject *o;
+	
+	o = mono_object_allocate (c->instance_size);
+	o->klass = c;
+
+	return o;
 }
+

+ 4 - 3
mono/metadata/object.h

@@ -1,13 +1,14 @@
 #ifndef _MONO_CLI_OBJECT_H_
 #define _MONO_CLI_OBJECT_H_
 
-typedef struct {
-} MonoClass;
+#include <mono/cli/class.h>
 
 typedef struct {
 	MonoClass *klass;
 } MonoObject;
 
-void *mono_object_new (MonoImage *image, guint32 type_token);
+MonoObject *mono_object_new  (MonoImage *image, guint32 type_token);
+void        mono_object_free (MonoObject *o);
 		      
 #endif
+

+ 55 - 0
mono/metadata/typedef.c

@@ -0,0 +1,55 @@
+/*
+ * typedef.c: Handling of TypeDefs. 
+ *
+ * Author:
+ *   Miguel de Icaza ([email protected])
+ *
+ * (C) 2001 Ximian, Inc.
+ */
+#include <config.h>
+#include <mono/metadata/typedef.h>
+
+/**
+ * mono_typedef_decode:
+ * @image: image to decode from
+ * @tidx: typedef number
+ *
+ * Decodes the TypeDef whose index is @tidx in @image
+ */
+void
+mono_typedef_decode (MonoImage *image, guint32 tidx, MonoTypedef *ret)
+{
+	cli_image_info_t *iinfo = image->image_info;
+	metadata_t *m = &iinfo->cli_metadata;
+	metadata_tableinfo_t *tt = m->tables [META_TABLE_TYPEDEF];
+	int next_is_valid;
+	guint32 cols_next [6];
+	guint last;
+	
+	g_assert (typedef_token < tt->rows);
+	
+	mono_metadata_decode_row (tt, typedef_idx, &ret->cols, CSIZE (ret->cols));
+
+	/*
+	 * Get the field and method range
+	 */
+	ret->field.first = ret->cols [4] - 1;
+	ret->method.first = ret->cols [5] - 1;
+	
+	if (tt->rows > typedef_idx + 1){
+		mono_metadata_decode_row (tt, typedef_idx + 1, cols_next, CSIZE (cols_next));
+		ret->field.last = cols_next [4] - 1;
+		ret->method.last = cols_next [5] - 1;
+	} else {
+		ret->field.last = m->tables [META_TABLE_FIELD].rows;
+		ret->field.method = m->tables [META_TABLE_METHOD].rows;
+	}
+
+	/*
+	 * Get the method range
+	 */
+	ref
+	
+}
+
+