From: Dietmar Maurer Date: Tue, 16 Jul 2002 15:27:07 +0000 (-0000) Subject: 2002-07-16 Dietmar Maurer X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=da471d6ef844e368822ca40a720d9030c06d4934;p=mono.git 2002-07-16 Dietmar Maurer * x86.brg (CALL_VOID): fix bug #27751 * marshal.c (emit_ptr_to_str_conv): first impl. svn path=/trunk/mono/; revision=5827 --- diff --git a/mono/jit/ChangeLog b/mono/jit/ChangeLog index d210e60329f..e986bd6e37f 100644 --- a/mono/jit/ChangeLog +++ b/mono/jit/ChangeLog @@ -1,5 +1,7 @@ 2002-07-16 Dietmar Maurer + * x86.brg (CALL_VOID): fix bug #27751 + * jit.c (mono_analyze_stack): adjust valuetype size for pinvoke calls i2002-07-11 Dietmar Maurer diff --git a/mono/jit/emit-x86.c b/mono/jit/emit-x86.c index 8acf7b19cb3..3d569eaa144 100644 --- a/mono/jit/emit-x86.c +++ b/mono/jit/emit-x86.c @@ -128,7 +128,7 @@ enter_method (MonoMethod *method, char *ebp) g_assert (!method->signature->ret->byref); - size = mono_type_stack_size (method->signature->ret, &align); + mono_get_param_info (method->signature, -1, &size, &align); printf ("VALUERET:%p, ", *((gpointer *)ebp)); ebp += sizeof (gpointer); @@ -155,9 +155,8 @@ enter_method (MonoMethod *method, char *ebp) } for (i = 0; i < method->signature->param_count; ++i) { - MonoType *type = method->signature->params [i]; int size, align; - size = mono_type_stack_size (type, &align); + MonoType *type = mono_get_param_info (method->signature, i, &size, &align); if (type->byref) { printf ("[BYREF:%p], ", *((gpointer *)ebp)); diff --git a/mono/jit/jit.c b/mono/jit/jit.c index d818c6e5cf9..61132f3e2b9 100644 --- a/mono/jit/jit.c +++ b/mono/jit/jit.c @@ -1388,7 +1388,7 @@ mono_analyze_stack (MonoFlowGraph *cfg) for (i = 0; i < signature->param_count; ++i) { int argvar; - size = mono_type_stack_size (signature->params [i], &align); + mono_get_param_info (signature, i, &size, &align); argvar = arch_allocate_var (cfg, size, align, MONO_ARGVAR, VAL_UNKNOWN); VARINFO (cfg, argvar).isvolatile = 1; } @@ -1865,9 +1865,13 @@ mono_analyze_stack (MonoFlowGraph *cfg) ip++; --sp; token = read32 (ip); - class = mono_class_get (image, token); ip += 4; + if (method->wrapper_type != MONO_WRAPPER_NONE) + class = (MonoClass *)mono_method_get_wrapper_data (method, token); + else + class = mono_class_get (image, token); + if (cfg->share_code) { t1 = mono_ctree_new (mp, MB_TERM_NEWARR, *sp, NULL); t1->data.p = class; @@ -1966,9 +1970,7 @@ mono_analyze_stack (MonoFlowGraph *cfg) args_size += sizeof (gpointer); /* this argument */ for (k = csig->param_count - 1; k >= 0; k--) { - MonoType *type = cm->signature->params [k]; - - size = mono_type_stack_size (type, &align); + MonoType *type = mono_get_param_info (cm->signature, k, &size, &align); t1 = mono_ctree_new (mp, mono_map_arg_type (type), arg_sp [k], NULL); t1->data.i = size; ADD_TREE (t1, cli_addr); @@ -2139,13 +2141,8 @@ mono_analyze_stack (MonoFlowGraph *cfg) } for (k = nargs - 1; k >= 0; k--) { - MonoType *type = csig->params [k]; + MonoType *type = mono_get_param_info (csig, k, &size, NULL); t1 = mono_ctree_new (mp, mono_map_arg_type (type), arg_sp [k], NULL); - if (csig->pinvoke && ISSTRUCT (type)) { - size = mono_class_native_size (type->data.klass); - } else { - size = mono_type_stack_size (type, &align); - } t1->data.i = size; ADD_TREE (t1, cli_addr); args_size += size; diff --git a/mono/metadata/ChangeLog b/mono/metadata/ChangeLog index 6e9a80f2572..a97860a5544 100644 --- a/mono/metadata/ChangeLog +++ b/mono/metadata/ChangeLog @@ -1,3 +1,6 @@ +2002-07-16 Dietmar Maurer + + * marshal.c (emit_ptr_to_str_conv): first impl. Tue Jul 16 12:39:33 CEST 2002 Paolo Molaro diff --git a/mono/metadata/marshal.c b/mono/metadata/marshal.c index c77ae04cc53..e689d13c082 100644 --- a/mono/metadata/marshal.c +++ b/mono/metadata/marshal.c @@ -339,6 +339,19 @@ mono_mb_emit_ldarg_addr (MonoMethodBuilder *mb, guint argnum) } } +void +mono_mb_emit_ldloc_addr (MonoMethodBuilder *mb, guint locnum) +{ + if (locnum < 256) { + mono_mb_emit_byte (mb, CEE_LDLOCA_S); + mono_mb_emit_byte (mb, locnum); + } else { + mono_mb_emit_byte (mb, CEE_PREFIX1); + mono_mb_emit_byte (mb, CEE_LDLOCA); + mono_mb_emit_i4 (mb, locnum); + } +} + void mono_mb_emit_ldloc (MonoMethodBuilder *mb, guint num) { @@ -423,13 +436,90 @@ mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint8 local, gint8 incr) } static void -emit_ptr_to_str_conv (MonoMethodBuilder *mb, MonoMarshalConv conv, int usize, int msize) +emit_ptr_to_str_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, + int usize, int msize) { - /* fixme: dont know what do do here - docs say - this does not work for value types */ + switch (conv) { + case MONO_MARSHAL_CONV_BOOL_I4: + mono_mb_emit_byte (mb, CEE_LDLOC_0); + mono_mb_emit_byte (mb, CEE_LDIND_I); + mono_mb_emit_byte (mb, CEE_BRFALSE_S); + mono_mb_emit_byte (mb, 5); + mono_mb_emit_byte (mb, CEE_LDLOC_1); + mono_mb_emit_byte (mb, CEE_LDC_I4_1); + mono_mb_emit_byte (mb, CEE_STIND_I1); + mono_mb_emit_byte (mb, CEE_BR_S); + mono_mb_emit_byte (mb, 3); + mono_mb_emit_byte (mb, CEE_LDLOC_1); + mono_mb_emit_byte (mb, CEE_LDC_I4_0); + mono_mb_emit_byte (mb, CEE_STIND_I1); + break; + case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: { + MonoClass *eclass; + int esize; - g_warning ("not implemented"); - g_assert_not_reached (); + if (type->type == MONO_TYPE_ARRAY) + eclass = mono_class_from_mono_type (type->data.array->type); + else if (type->type == MONO_TYPE_SZARRAY) { + eclass = mono_class_from_mono_type (type->data.type); + } else { + g_assert_not_reached (); + } + + if (eclass->valuetype) + esize = mono_class_instance_size (eclass) - sizeof (MonoObject); + else + esize = sizeof (gpointer); + + /* create a new array */ + mono_mb_emit_byte (mb, CEE_LDLOC_1); + mono_mb_emit_icon (mb, msize / esize); + mono_mb_emit_byte (mb, CEE_NEWARR); + mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eclass)); + mono_mb_emit_byte (mb, CEE_STIND_I); + + /* copy the elements */ + mono_mb_emit_byte (mb, CEE_LDLOC_1); + mono_mb_emit_byte (mb, CEE_LDIND_I); + mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector)); + mono_mb_emit_byte (mb, CEE_ADD); + mono_mb_emit_byte (mb, CEE_LDLOC_0); + mono_mb_emit_icon (mb, usize); + mono_mb_emit_byte (mb, CEE_PREFIX1); + mono_mb_emit_byte (mb, CEE_CPBLK); + + break; + } + case MONO_MARSHAL_CONV_STR_BYVALSTR: + mono_mb_emit_byte (mb, CEE_LDLOC_1); + mono_mb_emit_byte (mb, CEE_LDLOC_0); + mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); + mono_mb_emit_byte (mb, CEE_MONO_FUNC1); + mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR); + mono_mb_emit_byte (mb, CEE_STIND_I); + break; + case MONO_MARSHAL_CONV_STR_LPTSTR: + case MONO_MARSHAL_CONV_STR_LPSTR: + mono_mb_emit_byte (mb, CEE_LDLOC_1); + mono_mb_emit_byte (mb, CEE_LDLOC_0); + mono_mb_emit_byte (mb, CEE_LDIND_I); + mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); + mono_mb_emit_byte (mb, CEE_MONO_FUNC1); + mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR); + mono_mb_emit_byte (mb, CEE_STIND_I); + break; + case MONO_MARSHAL_CONV_STR_LPWSTR: + case MONO_MARSHAL_CONV_STR_BSTR: + case MONO_MARSHAL_CONV_STR_ANSIBSTR: + case MONO_MARSHAL_CONV_STR_TBSTR: + case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY: + case MONO_MARSHAL_CONV_ARRAY_LPARRAY: + case MONO_MARSHAL_CONV_STR_BYVALWSTR: + case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL: + default: + g_warning ("marshalling conversion %d not implemented", conv); + g_assert_not_reached (); + } } static void @@ -504,7 +594,8 @@ emit_str_to_ptr_conv (MonoMethodBuilder *mb, MonoMarshalConv conv, int usize, in } case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL: default: - g_error ("marshalling conversion %d not implemented", conv); + g_warning ("marshalling conversion %d not implemented", conv); + g_assert_not_reached (); } } @@ -594,7 +685,7 @@ emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object) break; case MONO_TYPE_VALUETYPE: emit_struct_conv (mb, ftype->data.klass, to_object); - break; + continue; default: g_error ("marshalling type %02x not implemented", ftype->type); } @@ -602,12 +693,15 @@ emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object) default: if (to_object) - emit_ptr_to_str_conv (mb, conv, usize, msize); + emit_ptr_to_str_conv (mb, ftype, conv, usize, msize); else emit_str_to_ptr_conv (mb, conv, usize, msize); } - if (!last_field) { + if (to_object) { + mono_mb_emit_add_to_local (mb, 0, usize); + mono_mb_emit_add_to_local (mb, 1, msize); + } else { mono_mb_emit_add_to_local (mb, 0, msize); mono_mb_emit_add_to_local (mb, 1, usize); } @@ -1339,7 +1433,7 @@ handle_enum: mono_mb_emit_managed_call (mb, method, strsig); } else mono_mb_emit_managed_call (mb, method, NULL); - + switch (sig->ret->type) { case MONO_TYPE_VOID: if (!method->string_ctor) @@ -1437,7 +1531,7 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this) MonoClass *klass; MonoMethod *res; GHashTable *cache; - int i, sigsize; + int i, sigsize, *tmp_locals; g_assert (method != NULL); @@ -1450,10 +1544,21 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this) mb = mono_mb_new (method->klass, method->name); mb->method->wrapper_type = MONO_WRAPPER_NATIVE_TO_MANAGED; + /* allocate local 0 (pointer) src_ptr */ + mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg); + /* allocate local 1 (pointer) dst_ptr */ + mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg); + /* allocate local 2 (boolean) delete_old */ + mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg); + + mono_mb_emit_byte (mb, CEE_LDNULL); + mono_mb_emit_byte (mb, CEE_STLOC_2); + /* we copy the signature, so that we can modify it */ sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *); csig = g_memdup (sig, sigsize); csig->hasthis = 0; + csig->pinvoke = 1; /* fixme: howto handle this ? */ if (sig->hasthis) { @@ -1470,6 +1575,46 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this) } } + + /* we first do all conversions */ + tmp_locals = alloca (sizeof (int) * sig->param_count); + for (i = 0; i < sig->param_count; i ++) { + MonoType *t = sig->params [i]; + + tmp_locals [i] = 0; + + switch (t->type) { + case MONO_TYPE_VALUETYPE: + + klass = sig->params [i]->data.klass; + if (klass->enumtype) + break; + + tmp_locals [i] = mono_mb_add_local (mb, &klass->byval_arg); + + mono_mb_emit_ldarg_addr (mb, i); + mono_mb_emit_byte (mb, CEE_STLOC_0); + mono_mb_emit_ldloc_addr (mb, tmp_locals [i]); + mono_mb_emit_byte (mb, CEE_STLOC_1); + + /* emit valuetype convnversion code code */ + emit_struct_conv (mb, klass, TRUE); + break; + case MONO_TYPE_STRING: + + tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg); + + csig->params [i] = &mono_defaults.int_class->byval_arg; + mono_mb_emit_ldarg (mb, i); + mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); + mono_mb_emit_byte (mb, CEE_MONO_FUNC1); + mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR); + mono_mb_emit_stloc (mb, tmp_locals [i]); + break; + } + + } + for (i = 0; i < sig->param_count; i++) { MonoType *t = sig->params [i]; @@ -1495,11 +1640,8 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this) mono_mb_emit_ldarg (mb, i); break; case MONO_TYPE_STRING: - csig->params [i] = &mono_defaults.int_class->byval_arg; - mono_mb_emit_ldarg (mb, i); - mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); - mono_mb_emit_byte (mb, CEE_MONO_FUNC1); - mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR); + g_assert (tmp_locals [i]); + mono_mb_emit_ldloc (mb, tmp_locals [i]); break; case MONO_TYPE_CLASS: case MONO_TYPE_ARRAY: @@ -1515,7 +1657,8 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this) break; } - g_assert_not_reached (); + g_assert (tmp_locals [i]); + mono_mb_emit_ldloc (mb, tmp_locals [i]); break; default: g_warning ("type 0x%02x unknown", t->type); @@ -1663,7 +1806,7 @@ mono_marshal_get_native_wrapper (MonoMethod *method) mono_mb_emit_byte (mb, CEE_STLOC_1); /* emit valuetype convnversion code code */ - emit_struct_conv (mb, sig->params [i]->data.klass, FALSE); + emit_struct_conv (mb, klass, FALSE); break; case MONO_TYPE_STRING: csig->params [argnum] = &mono_defaults.int_class->byval_arg; @@ -1928,7 +2071,8 @@ mono_marshal_get_ptr_to_struct (MonoClass *klass) mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg); /* allocate local 2 (boolean) delete_old */ mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg); - mono_mb_emit_byte (mb, CEE_LDARG_2); + + mono_mb_emit_byte (mb, CEE_LDNULL); mono_mb_emit_byte (mb, CEE_STLOC_2); /* initialize src_ptr to point to the start of object data */ diff --git a/mono/metadata/metadata.c b/mono/metadata/metadata.c index bffd8db8087..10003353c35 100644 --- a/mono/metadata/metadata.c +++ b/mono/metadata/metadata.c @@ -2176,6 +2176,33 @@ mono_type_stack_size (MonoType *t, gint *align) return 0; } +MonoType * +mono_get_param_info (MonoMethodSignature *sig, int param_num, int *size, int *align) +{ + MonoType *type; + int s, a; + + if (!size) + size = &s; + + if (!align) + align = &a; + + if (param_num == -1) + type = sig->ret; + else + type = sig->params [param_num]; + + if (sig->pinvoke && !type->byref && type->type == MONO_TYPE_VALUETYPE && + !type->data.klass->enumtype) { + *size = mono_class_native_size (type->data.klass); + } else { + *size = mono_type_stack_size (type, align); + } + + return type; +} + /* * mono_metadata_type_hash: * @t1: a type diff --git a/mono/metadata/metadata.h b/mono/metadata/metadata.h index ff81fe406ab..04f3f77b601 100644 --- a/mono/metadata/metadata.h +++ b/mono/metadata/metadata.h @@ -323,14 +323,20 @@ MonoType *mono_metadata_parse_field_type (MonoImage *m, short field_flags, const char *ptr, const char **rptr); -MonoType *mono_type_create_from_typespec (MonoImage *image, - guint32 type_spec); +MonoType *mono_type_create_from_typespec (MonoImage *image, + guint32 type_spec); void mono_metadata_free_type (MonoType *type); int mono_type_size (MonoType *type, int *alignment); int mono_type_stack_size (MonoType *type, int *alignment); +MonoType *mono_get_param_info (MonoMethodSignature *sig, + int param_num, + int *size, + int *align); + + guint mono_metadata_type_hash (MonoType *t1); gboolean mono_metadata_type_equal (MonoType *t1, MonoType *t2); diff --git a/mono/metadata/object.c b/mono/metadata/object.c index d8f49930393..e146496bc69 100644 --- a/mono/metadata/object.c +++ b/mono/metadata/object.c @@ -926,7 +926,10 @@ mono_string_new_wrapper (const char *text) { MonoDomain *domain = mono_domain_get (); - return mono_string_new (domain, text); + if (text) + return mono_string_new (domain, text); + + return NULL; } /** @@ -1499,11 +1502,11 @@ mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoAr int i, j, type, size, align; for (i = 0, j = 0; i < sig->param_count; i++) { - size = mono_type_stack_size (sig->params [i], &align); - - if (sig->params [i]->byref) { + MonoType *pt = mono_get_param_info (sig, i, &size, &align); + + if (pt->byref) { char *arg = mono_array_get (out_args, gpointer, j); - type = sig->params [i]->type; + type = pt->type; switch (type) { case MONO_TYPE_VOID: diff --git a/mono/tests/marshal2.cs b/mono/tests/marshal2.cs index bb19ef2e5a1..a98fbdfbb46 100755 --- a/mono/tests/marshal2.cs +++ b/mono/tests/marshal2.cs @@ -19,6 +19,7 @@ public class Test { [MarshalAs (UnmanagedType.ByValArray, SizeConst=2)] public short[] a1; [MarshalAs (UnmanagedType.ByValTStr, SizeConst=4)] public string s1; public SimpleStruct2 emb1; + public string s2; } public unsafe static int Main () { @@ -27,7 +28,7 @@ public class Test { int size = Marshal.SizeOf (typeof (SimpleStruct)); Console.WriteLine ("SimpleStruct:" + size); - if (size != 32) + if (size != 36) return 1; IntPtr p = Marshal.AllocHGlobal (size); @@ -42,7 +43,8 @@ public class Test { ss.emb1 = new SimpleStruct2 (); ss.emb1.a = 3; ss.emb1.b = 4; - + ss.s2 = "just a test"; + Marshal.StructureToPtr (ss, p, false); if (Marshal.ReadInt32 (p, 0) != 1) return 1; @@ -68,10 +70,42 @@ public class Test { return 1; if (Marshal.ReadInt32 (p, 28) != 4) return 1; + if (Marshal.ReadInt32 (p, 32) == 0) + return 1; object o = cp; Marshal.PtrToStructure (p, o); cp = (SimpleStruct)o; + + if (cp.a != 1) + return 2; + + if (cp.bool1 != true) + return 2; + + if (cp.bool2 != false) + return 2; + + if (cp.b != 2) + return 2; + + if (cp.a1 [0] != 6) + return 2; + + if (cp.a1 [1] != 5) + return 2; + + if (cp.s1 != "abc") + return 3; + + if (cp.emb1.a != 3) + return 2; + + if (cp.emb1.b != 4) + return 2; + + if (cp.s2 != "just a test") + return 2; return 0; } diff --git a/mono/tests/pinvoke3.cs b/mono/tests/pinvoke3.cs index fe1914aa3aa..7b16f5483f2 100755 --- a/mono/tests/pinvoke3.cs +++ b/mono/tests/pinvoke3.cs @@ -13,7 +13,7 @@ public class Test { public static int delegate_test (SimpleStruct ss) { - Console.WriteLine ("Delegate: " + ss); + Console.WriteLine ("delegate called"); if (!ss.a && ss.b && !ss.c && ss.d == "TEST") return 0;