* x86/tramp.c: handle boolean as a return value.
* x96/x86-codegen.c: x86_widen_memindex() added.
Wed Nov 14 19:23:00 CET 2001 Paolo Molaro <lupus@ximian.com>
* interp.c: move the stack frame dumping code to a function so it can
be called from the debugger. Fix virtual method lookup for interfaces.
Throw exceptions instead of aborting in more places.
Print also the message in an exception. Updates for field renames in
corlib.
Wed Nov 14 19:26:06 CET 2001 Paolo Molaro <lupus@ximian.com>
* class.h, class.c: add a max_interface_id to MonoClass.
* icall.c: rename my_mono_new_object() to my_mono_new_mono_type()
since it's used to do that. Added mono_type_type_from_obj().
Make GetType() return NULL instead of segfaulting if the type was not
found. Handle simple arrays in assQualifiedName.
* object.h: add a struct to represent an Exception.
* reflection.c: output call convention in method signature.
Add code to support P/Invoke methods and fixed offsets for fields.
svn path=/trunk/mono/; revision=1352
+
+Wed Nov 14 19:21:26 CET 2001 Paolo Molaro <lupus@ximian.com>
+
+ * x86/tramp.c: handle boolean as a return value.
+ * x96/x86-codegen.c: x86_widen_memindex() added.
+
2001-11-07 Miguel de Icaza <miguel@ximian.com>
* x86/tramp.c: Include stdlib to kill warning.
x86_lea_mem (p, X86_EDX, mem_addr);
/* test widen */
+ x86_widen_memindex (p, X86_EDX, X86_ECX, 0, X86_EBX, 2, 1, 0);
x86_cdq (p);
x86_wait (p);
switch (sig->ret->type) {
case MONO_TYPE_VOID:
break;
+ case MONO_TYPE_BOOLEAN:
+ x86_mov_reg_membase (p, X86_EAX, X86_EAX, 0, 1);
+ break;
case MONO_TYPE_I4:
case MONO_TYPE_U4:
case MONO_TYPE_I:
/* Copyright (C) 2000 Intel Corporation. All rights reserved.
Copyright (C) 2001 Ximian, Inc.
//
-// $Header: /home/miguel/third-conversion/public/mono/mono/arch/x86/x86-codegen.h,v 1.15 2001/11/09 13:40:43 dietmar Exp $
+// $Header: /home/miguel/third-conversion/public/mono/mono/arch/x86/x86-codegen.h,v 1.16 2001/11/14 15:18:55 lupus Exp $
*/
#ifndef X86_H
x86_membase_emit ((inst), (dreg), (basereg), (disp)); \
} while (0)
+#define x86_widen_memindex(inst,dreg,basereg,disp,indexreg,shift,is_signed,is_half) \
+ do { \
+ unsigned char op = 0xb6; \
+ *(inst)++ = (unsigned char)0x0f; \
+ if ((is_signed)) op += 0x08; \
+ if ((is_half)) op += 0x01; \
+ *(inst)++ = op; \
+ x86_memindex_emit ((inst), (dreg), (basereg), (disp), (indexreg), (shift)); \
+ } while (0)
+
#define x86_cdq(inst) do { *(inst)++ = (unsigned char)0x99; } while (0)
#define x86_wait(inst) do { *(inst)++ = (unsigned char)0x9b; } while (0)
+
+Wed Nov 14 19:23:00 CET 2001 Paolo Molaro <lupus@ximian.com>
+
+ * interp.c: move the stack frame dumping code to a function so it can
+ be called from the debugger. Fix virtual method lookup for interfaces.
+ Throw exceptions instead of aborting in more places.
+ Print also the message in an exception. Updates for field renames in
+ corlib.
+
2001-11-09 Dick Porter <dick@ximian.com>
* Makefile.am (mint_LDADD): Don't need THREAD_LIBS any more
if (!target_offset) {
MonoClassField *field;
- field = mono_class_get_field_from_name (mono_defaults.delegate_class, "target");
+ field = mono_class_get_field_from_name (mono_defaults.delegate_class, "m_target");
target_offset = field->offset;
field = mono_class_get_field_from_name (mono_defaults.delegate_class, "method_ptr");
method_offset = field->offset;
}
}
+static void
+dump_frame (MonoInvocation *inv)
+{
+ int i;
+ for (i = 0; inv; inv = inv->parent, ++i) {
+ MonoClass *k = inv->method->klass;
+ MonoMethodHeader *hd = ((MonoMethodNormal *)inv->method)->header;
+ g_print ("#%d: 0x%05x in %s.%s::%s (", i, inv->ip - hd->code,
+ k->name_space, k->name, inv->method->name);
+ dump_stack (inv->stack_args, inv->stack_args + inv->method->signature->param_count);
+ g_print (")\n");
+ }
+}
+
#define DEBUG_INTERP 1
#if DEBUG_INTERP
#define THROW_EX(exception,ex_ip) \
do {\
frame->ip = (ex_ip); \
- frame->ex = (exception); \
+ frame->ex = (MonoException*)(exception); \
goto handle_exception; \
} while (0)
if (frame->method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
if (!frame->method->addr) {
- frame->ex = get_exception_missing_method ();
+ frame->ex = (MonoException*)get_exception_missing_method ();
DEBUG_LEAVE ();
return;
}
if (frame->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
if (!frame->method->addr) {
- frame->ex = get_exception_missing_method ();
+ frame->ex = (MonoException*)get_exception_missing_method ();
DEBUG_LEAVE ();
return;
}
oclass = o->klass;
if (c->flags & TYPE_ATTRIBUTE_INTERFACE) {
- if ((c->interface_id < oclass->interface_count) &&
+ if ((c->interface_id <= oclass->max_interface_id) &&
oclass->interface_offsets [c->interface_id])
found = TRUE;
- g_error ("fixme: dont know if this works");
} else {
if ((oclass->baseval - c->baseval) <= c->diffval) {
sp [-1].data.vt.klass = c;
c = mono_class_get (image, token);
o = sp [-1].data.p;
+ if (!o)
+ THROW_EX (get_exception_null_reference(), ip - 1);
- g_assert (o->klass->type_token == c->type_token);
+ if (o->klass->type_token != c->type_token)
+ THROW_EX (get_exception_invalid_cast (), ip - 1);
sp [-1].type = VAL_MP;
sp [-1].data.p = (char *)o + sizeof (MonoObject);
MonoInvocation *inv;
MonoMethodHeader *hd;
MonoExceptionClause *clause;
+ char *message;
+ MonoObject *ex_obj;
for (inv = frame; inv; inv = inv->parent) {
hd = ((MonoMethodNormal*)inv->method)->header;
clause = &hd->clauses [i];
if (clause->flags <= 1 && OFFSET_IN_CLAUSE (clause, ip_offset)) {
if (!clause->flags) {
- if (mono_object_isinst (frame->ex, mono_class_get (inv->method->klass->image, clause->token_or_filter))) {
+ if (mono_object_isinst ((MonoObject*)frame->ex, mono_class_get (inv->method->klass->image, clause->token_or_filter))) {
/*
* OK, we found an handler, now we need to execute the finally
* and fault blocks before branching to the handler code.
/*
* If we get here, no handler was found: print a stack trace.
*/
- g_print ("Unhandled exception %s.%s.\n", frame->ex->klass->name_space, frame->ex->klass->name);
- for (inv = frame, i = 0; inv; inv = inv->parent, ++i) {
- MonoClass *k = inv->method->klass;
- MonoMethodHeader *hd = ((MonoMethodNormal *)inv->method)->header;
- g_print ("#%d: 0x%05x in %s.%s::%s (", i, inv->ip - hd->code,
- k->name_space, k->name, inv->method->name);
- dump_stack (inv->stack_args, inv->stack_args + inv->method->signature->param_count);
- g_print (")\n");
- }
+ ex_obj = (MonoObject*)frame->ex;
+ message = frame->ex->message? mono_string_to_utf8 (frame->ex->message): NULL;
+ g_print ("Unhandled exception %s.%s %s.\n", ex_obj->klass->name_space, ex_obj->klass->name,
+ message?message:"");
+ g_free (message);
+ dump_frame (frame);
exit (1);
}
handle_finally:
static FieldDesc
typebuilder_fields[] = {
- {"name", G_STRUCT_OFFSET (MonoReflectionTypeBuilder, name)},
+ {"tname", G_STRUCT_OFFSET (MonoReflectionTypeBuilder, name)},
{"nspace", G_STRUCT_OFFSET (MonoReflectionTypeBuilder, nspace)},
{"parent", G_STRUCT_OFFSET (MonoReflectionTypeBuilder, parent)},
{"interfaces", G_STRUCT_OFFSET (MonoReflectionTypeBuilder, interfaces)},
stackval *stack;
/* exception info */
const unsigned char *ip;
- MonoObject *ex;
+ MonoException *ex;
MonoExceptionClause *ex_handler;
};
+Wed Nov 14 19:26:06 CET 2001 Paolo Molaro <lupus@ximian.com>
+
+ * class.h, class.c: add a max_interface_id to MonoClass.
+ * icall.c: rename my_mono_new_object() to my_mono_new_mono_type()
+ since it's used to do that. Added mono_type_type_from_obj().
+ Make GetType() return NULL instead of segfaulting if the type was not
+ found. Handle simple arrays in assQualifiedName.
+ * object.h: add a struct to represent an Exception.
+ * reflection.c: output call convention in method signature.
+ Add code to support P/Invoke methods and fixed offsets for fields.
+
Mon Nov 12 12:41:32 CET 2001 Paolo Molaro <lupus@ximian.com>
* decimal.c, decimal.h: mono_double2decimal() get the sign bit from
max_iid = ic->interface_id;
}
}
-
+
+ class->max_interface_id = max_iid;
/* compute vtable offset for interfaces */
class->interface_offsets = g_malloc (sizeof (gpointer) * (max_iid + 1));
MonoMethod *im = ic->methods [l];
MonoClass *k1;
+ g_assert (io <= class->vtable_size);
+
if (tmp_vtable [io + l] || vtable [io + l])
continue;
const char *name_space;
guint interface_id; /* unique inderface id (for interfaces) */
+ guint max_interface_id;
gpointer *interface_offsets;
guint interface_count;
MonoClass **interfaces;
}
static MonoReflectionType *
-my_mono_new_object (MonoClass *klass, gpointer data)
+my_mono_new_mono_type (MonoType *type)
{
- MonoReflectionType *res = (MonoReflectionType *)mono_object_new (klass);
-
- res->type = (MonoType *)data;
+ MonoReflectionType *res = (MonoReflectionType *)mono_object_new (mono_defaults.monotype_class);
+ res->type = type;
return res;
}
+static void
+mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
+{
+ mtype->type = &obj->klass->byval_arg;
+}
+
static gint32
ves_icall_get_data_chunk (MonoReflectionAssemblyBuilder *assb, gint32 type, MonoArray *buf)
{
}
static MonoReflectionType*
-ves_icall_type_from_handle (gpointer handle)
+ves_icall_type_from_handle (MonoType *handle)
{
- return my_mono_new_object (mono_defaults.monotype_class, handle);
+ return my_mono_new_mono_type (handle);
}
static gpointer
g_strfreev (parts);
klass = mono_class_from_name (assembly->assembly->image, namespace, name);
- if (!klass->metadata_inited)
- mono_class_metadata_init (klass);
-
g_free (name);
g_free (namespace);
+ if (!klass)
+ return NULL;
+ if (!klass->metadata_inited)
+ mono_class_metadata_init (klass);
- return my_mono_new_object (mono_defaults.monotype_class, &klass->byval_arg);
+ return my_mono_new_mono_type (&klass->byval_arg);
}
static MonoString *
{
/* FIXME : real rules are more complicated (internal classes,
reference types, array types, etc. */
-
-
MonoString *res;
gchar *fullname;
MonoClass *klass;
-
- klass = object->type->data.klass;
+ char *append = NULL;
+
+ switch (object->type->type) {
+ case MONO_TYPE_SZARRAY:
+ klass = object->type->data.type->data.klass;
+ append = "[]";
+ break;
+ default:
+ klass = object->type->data.klass;
+ break;
+ }
fullname = g_strconcat (klass->name_space, ".",
klass->name, ",",
- klass->image->assembly_name);
- res = mono_string_new (fullname);
+ klass->image->assembly_name, append, NULL);
+ res = mono_string_new (fullname);
g_free (fullname);
return res;
"System.Reflection.Assembly::LoadFrom", ves_icall_System_Reflection_Assembly_LoadFrom,
"System.Reflection.Assembly::GetType", ves_icall_System_Reflection_Assembly_GetType,
+ /*
+ * System.MonoType.
+ */
"System.MonoType::assQualifiedName", ves_icall_System_MonoType_assQualifiedName,
+ "System.MonoType::type_from_obj", mono_type_type_from_obj,
"System.PAL.OpSys::GetCurrentDirectory", ves_icall_System_PAL_GetCurrentDirectory,
/*
size = obj->klass->instance_size;
o = mono_object_allocate (size);
+ /* FIXME: handle arrays... */
memcpy (o, obj, size);
* they need to be kept in sync.
*/
o = mono_object_allocate (sizeof (MonoArray) + byte_len);
+ if (!o)
+ G_BREAKPOINT ();
o->klass = array_class;
mono_threads_synchronisation_init (&o->synchronisation);
gint32 length;
} MonoString;
+typedef struct {
+ MonoObject object;
+ MonoObject *inner_ex;
+ MonoString *message;
+} MonoException;
+
#define mono_array_length(array) ((array)->bounds->length)
#define mono_array_addr(array,type,index) ( ((char*)(array)->vector) + sizeof (type) * (index) )
#define mono_array_addr_with_size(array,size,index) ( ((char*)(array)->vector) + (size) * (index) )
char *b = blob_size;
p = buf = g_malloc (size);
- *p = 0;
+ /* LAMESPEC: all the call conv spec is foobared */
+ *p = mb->call_conv & 0x60; /* has-this, explicit-this */
+ if (mb->call_conv & 2)
+ *p |= 0x5; /* vararg */
if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
*p |= 0x20; /* hasthis */
- /*
- * FIXME: set also call convention and explict_this if needed.
- */
p++;
mono_metadata_encode_value (nparams, p, &p);
encode_type (mb->rtype->type, p, &p);
return assembly->text_rva + idx + CLI_H_SIZE;
}
+static guint32
+find_index_in_table (MonoDynamicAssembly *assembly, int table_idx, int col, guint32 index)
+{
+ int i;
+ MonoDynamicTable *table;
+ guint32 *values;
+
+ table = &assembly->tables [table_idx];
+
+ g_assert (col < table->columns);
+
+ values = table->values + table->columns;
+ for (i = 1; i <= table->rows; ++i) {
+ if (values [col] == index)
+ return i;
+ }
+ return 0;
+}
+
static void
mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
{
values [MONO_METHOD_SIGNATURE] = method_encode_signature (assembly, mb);
values [MONO_METHOD_PARAMLIST] = 0; /* FIXME: add support later */
values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
+
+ if (mb->dll) { /* It's a P/Invoke method */
+ guint32 moduleref;
+ table = &assembly->tables [MONO_TABLE_IMPLMAP];
+ table->rows ++;
+ alloc_table (table, table->rows);
+ values = table->values + table->rows * MONO_IMPLMAP_SIZE;
+ values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | mb->charset;
+ values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
+ name = mono_string_to_utf8 (mb->dllentry);
+ values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
+ g_free (name);
+ name = mono_string_to_utf8 (mb->dll);
+ moduleref = string_heap_insert (&assembly->sheap, name);
+ g_free (name);
+ if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
+ table = &assembly->tables [MONO_TABLE_MODULEREF];
+ table->rows ++;
+ alloc_table (table, table->rows);
+ table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
+ values [MONO_IMPLMAP_SCOPE] = table->rows;
+ }
+ }
}
static guint32
g_free (name);
values [MONO_FIELD_FLAGS] = fb->attrs;
values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
+
+ if (fb->offset != -1) {
+ table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
+ table->rows ++;
+ alloc_table (table, table->rows);
+ values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
+ values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
+ values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
+ }
}
static guint32
}
static guint32
-mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoClass *klass)
+mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
{
MonoDynamicTable *table;
guint32 *values;
guint32 token;
+ MonoClass *klass;
if (!assembly->typeref)
assembly->typeref = g_hash_table_new (g_direct_hash, g_direct_equal);
- token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, klass));
+ token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
if (token)
return token;
+ klass = type->data.klass;
if (klass->image != mono_defaults.corlib)
g_error ("multiple assemblyref not yet supported");
values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
token = 1 | (table->next_idx << 2); /* typeref */
- g_hash_table_insert (assembly->typeref, klass, GUINT_TO_POINTER(token));
+ g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
table->next_idx ++;
return token;
}
tb->table_idx = table->next_idx ++;
values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
values [MONO_TYPEDEF_FLAGS] = tb->attrs;
- /* FIXME: use tb->base later */
- values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_defaults.object_class);
+ values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
n = mono_string_to_utf8 (tb->name);
values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
g_free (n);
MonoArray *code;
MonoReflectionILGen *ilgen;
MonoObject *type;
+ MonoArray *pinfo;
+ MonoString *dll;
+ MonoString *dllentry;
+ guint32 charset;
+ guint32 native_cc;
+ guint32 call_conv;
} MonoReflectionMethodBuilder;
typedef struct {
gint32 table_idx;
} MonoReflectionPropertyBuilder;
-typedef struct {
- MonoReflectionType type;
- MonoString *name;
- MonoString *nspace;
- MonoReflectionType *parent;
- MonoArray *interfaces;
- MonoArray *methods;
- MonoArray *properties;
- MonoArray *fields;
- guint32 attrs;
- guint32 table_idx;
-} MonoReflectionTypeBuilder;
-
typedef struct {
MonoObject obj;
MonoImage *image;
guint32 table_idx;
} MonoReflectionModuleBuilder;
+typedef struct {
+ MonoReflectionType type;
+ MonoString *name;
+ MonoString *nspace;
+ MonoReflectionType *parent;
+ MonoArray *interfaces;
+ MonoArray *methods;
+ MonoArray *properties;
+ MonoArray *fields;
+ guint32 attrs;
+ guint32 table_idx;
+ MonoReflectionModuleBuilder *module;
+} MonoReflectionTypeBuilder;
+
int mono_image_get_header (MonoReflectionAssemblyBuilder *assembly, char *buffer, int maxsize);
#endif /* __METADATA_REFLECTION_H__ */
TESTSRC= \
array-init.cs \
+ arraylist.cs \
field-layout.cs \
+ hash-table.cs \
test-ops.cs \
obj.cs \
+ string.cs \
+ stringbuilder.cs \
switch.cs \
outparm.cs \
delegate.cs \
--- /dev/null
+using System.Collections;
+
+namespace Test {
+ public class Test {
+ public static int Main() {
+ ArrayList a = new ArrayList (10);
+ int i = 0;
+ a.Add (0);
+ a.Add (1);
+ a.Add (2);
+ a.Add (3);
+ foreach (int elem in a) {
+ if (elem != i++)
+ return i;
+ }
+ return 0;
+ }
+ }
+}
--- /dev/null
+using System.Collections;
+
+namespace Test {
+ public class Test {
+ public static int Main () {
+ string[] names = {
+ "one", "two", "three", "four"
+ };
+ Hashtable hash = new Hashtable ();
+
+ for (int i=0; i < names.Length; ++i) {
+ hash.Add (names [i], i);
+ }
+ if ((int)hash ["one"] != 0)
+ return 1;
+ if ((int)hash ["two"] != 1)
+ return 2;
+ if ((int)hash ["three"] != 2)
+ return 3;
+ if ((int)hash ["four"] != 3)
+ return 4;
+ if (hash.Contains("urka"))
+ return 5;
+ return 0;
+ }
+ }
+}
--- /dev/null
+using System;
+
+public class TestString {
+
+ public static int Main() {
+ string a = "ddd";
+ string b = "ddd";
+ string c = "ddda";
+ if (a != b)
+ return 1;
+ if (c != String.Concat(b , "a"))
+ return 2;
+ if (!System.Object.ReferenceEquals(a, b))
+ return 3;
+ if (System.Object.ReferenceEquals(c, String.Concat(b, "a")))
+ return 4;
+ return 0;
+ }
+}
--- /dev/null
+using System.Text;
+
+namespace test {
+ public class Test {
+ public static int Main() {
+ StringBuilder b = new StringBuilder ();
+ /*b.Append ('A');
+ b.Append ('b');
+ b.Append ('r');*/
+ b.Append ("Abr");
+ if (b.ToString() != "Abr") {
+ System.Console.WriteLine ("Got: " + b.ToString());
+ return 1;
+ }
+ b.Append ('a');
+ b.Append ("cadabra");
+ if (b.ToString() != "Abracadabra") {
+ System.Console.WriteLine ("Got: " + b.ToString());
+ return 2;
+ }
+ return 0;
+
+ }
+ }
+}