2 * marshal.c: Routines for marshaling complex types in P/Invoke methods.
5 * Paolo Molaro (lupus@ximian.com)
7 * (C) 2002 Ximian, Inc. http://www.ximian.com
14 #include "metadata/marshal.h"
15 #include "metadata/tabledefs.h"
16 #include "metadata/exception.h"
17 #include "metadata/appdomain.h"
18 #include "mono/metadata/debug-helpers.h"
19 #include "mono/metadata/threadpool.h"
20 #include "mono/metadata/threads.h"
21 #include "mono/metadata/monitor.h"
22 #include "mono/metadata/metadata-internals.h"
23 #include <mono/os/gc_wrapper.h>
27 /* #define DEBUG_RUNTIME_CODE */
29 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
33 #include "mono/cil/opcode.def"
38 struct _MonoMethodBuilder {
42 guint32 code_size, pos;
47 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object);
50 mono_find_method_by_name (MonoClass *klass, const char *name, int param_count)
52 MonoMethod *res = NULL;
55 for (i = 0; i < klass->method.count; ++i) {
56 if (klass->methods [i]->name[0] == name [0] &&
57 !strcmp (name, klass->methods [i]->name) &&
58 klass->methods [i]->signature->param_count == param_count) {
59 res = klass->methods [i];
66 #ifdef DEBUG_RUNTIME_CODE
68 indenter (MonoDisHelper *dh, MonoMethod *method, guint32 ip_offset)
70 return g_strdup (" ");
73 static MonoDisHelper marshal_dh = {
83 /* This mutex protects the various marshalling related caches in MonoImage */
84 static CRITICAL_SECTION marshal_mutex;
86 /* Maps wrapper methods to the methods they wrap */
87 static MonoGHashTable *wrapper_hash;
89 static guint32 last_error_tls_id;
92 register_icall (gpointer func, const char *name, const char *sigstr, gboolean save)
94 MonoMethodSignature *sig = mono_create_icall_signature (sigstr);
96 mono_register_jit_icall (func, name, sig, save);
100 mono_marshal_init (void)
102 static gboolean module_initialized = FALSE;
104 if (!module_initialized) {
105 module_initialized = TRUE;
106 InitializeCriticalSection (&marshal_mutex);
107 MONO_GC_REGISTER_ROOT (wrapper_hash);
108 wrapper_hash = mono_g_hash_table_new (NULL, NULL);
109 last_error_tls_id = TlsAlloc ();
111 register_icall (mono_string_to_utf16, "mono_string_to_utf16", "ptr obj", FALSE);
112 register_icall (mono_string_from_utf16, "mono_string_from_utf16", "obj ptr", FALSE);
113 register_icall (mono_string_new_wrapper, "mono_string_new_wrapper", "obj ptr", FALSE);
114 register_icall (mono_string_to_utf8, "mono_string_to_utf8", "ptr obj", FALSE);
115 register_icall (mono_string_to_bstr, "mono_string_to_bstr", "ptr obj", FALSE);
116 register_icall (mono_string_to_ansibstr, "mono_string_to_ansibstr", "ptr object", FALSE);
117 register_icall (mono_string_builder_to_utf8, "mono_string_builder_to_utf8", "ptr object", FALSE);
118 register_icall (mono_string_builder_to_utf16, "mono_string_builder_to_utf16", "ptr object", FALSE);
119 register_icall (mono_array_to_savearray, "mono_array_to_savearray", "ptr object", FALSE);
120 register_icall (mono_array_to_lparray, "mono_array_to_lparray", "ptr object", FALSE);
121 register_icall (mono_delegate_to_ftnptr, "mono_delegate_to_ftnptr", "ptr object", FALSE);
122 register_icall (mono_ftnptr_to_delegate, "mono_ftnptr_to_delegate", "object ptr ptr", FALSE);
123 register_icall (mono_marshal_string_array, "mono_marshal_string_array", "ptr object", FALSE);
124 register_icall (mono_marshal_string_array_to_unicode, "mono_marshal_string_array_to_unicode", "ptr object", FALSE);
125 register_icall (mono_marshal_asany, "mono_marshal_asany", "ptr object int32", FALSE);
126 register_icall (mono_marshal_free_asany, "mono_marshal_free_asany", "void object ptr int32", FALSE);
127 register_icall (mono_string_utf8_to_builder, "mono_string_utf8_to_builder", "void ptr ptr", FALSE);
128 register_icall (mono_string_utf16_to_builder, "mono_string_utf16_to_builder", "void ptr ptr", FALSE);
129 register_icall (mono_marshal_free_array, "mono_marshal_free_array", "void ptr int32", FALSE);
130 register_icall (mono_string_to_byvalstr, "mono_string_to_byvalstr", "void ptr ptr int32", FALSE);
131 register_icall (mono_string_to_byvalwstr, "mono_string_to_byvalwstr", "void ptr ptr int32", FALSE);
132 register_icall (g_free, "g_free", "void ptr", FALSE);
133 register_icall (mono_object_isinst, "mono_object_isinst", "object object ptr", FALSE);
138 mono_delegate_to_ftnptr (MonoDelegate *delegate)
140 MonoMethod *method, *wrapper, *invoke;
141 MonoMarshalSpec **mspecs;
148 if (delegate->delegate_trampoline)
149 return delegate->delegate_trampoline;
151 klass = ((MonoObject *)delegate)->vtable->klass;
152 g_assert (klass->delegate);
155 method = delegate->method_info->method;
156 invoke = mono_find_method_by_name (klass, "Invoke", method->signature->param_count);
158 mspecs = g_new (MonoMarshalSpec*, invoke->signature->param_count + 1);
159 mono_method_get_marshal_info (invoke, mspecs);
161 wrapper = mono_marshal_get_managed_wrapper (method, delegate->target, mspecs);
163 for (i = invoke->signature->param_count; i >= 0; i--)
167 delegate->delegate_trampoline = mono_compile_method (wrapper);
169 return delegate->delegate_trampoline;
173 mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn)
178 d = (MonoDelegate*)mono_object_new (mono_domain_get (), klass);
180 ji = mono_jit_info_table_find (mono_domain_get (), ftn);
182 mono_raise_exception (mono_get_exception_argument ("", "Function pointer was not created by a Delegate."));
184 /* FIXME: discard the wrapper and call the original method */
185 mono_delegate_ctor ((MonoObject*)d, NULL, ftn);
191 mono_array_to_savearray (MonoArray *array)
196 g_assert_not_reached ();
201 mono_array_to_lparray (MonoArray *array)
206 /* fixme: maybe we need to make a copy */
207 return array->vector;
211 mono_string_utf8_to_builder (MonoStringBuilder *sb, char *text)
213 GError *error = NULL;
223 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
225 if (items_written > mono_stringbuilder_capacity (sb))
226 items_written = mono_stringbuilder_capacity (sb);
229 memcpy (mono_string_chars (sb->str), ut, items_written * 2);
230 sb->length = items_written;
232 g_error_free (error);
238 mono_string_utf16_to_builder (MonoStringBuilder *sb, gunichar2 *text)
245 g_assert (mono_string_chars (sb->str) == text);
247 for (len = 0; text [len] != 0; ++len)
254 mono_string_builder_to_utf8 (MonoStringBuilder *sb)
256 GError *error = NULL;
263 res = g_malloc0 (mono_stringbuilder_capacity (sb) + 1);
265 tmp = g_utf16_to_utf8 (mono_string_chars (sb->str), sb->length, NULL, res, &error);
267 g_error_free (error);
268 mono_raise_exception (mono_get_exception_execution_engine ("Failed to convert StringBuilder from utf16 to utf8"));
271 memcpy (res, tmp, sb->length + 1);
277 mono_string_builder_to_utf16 (MonoStringBuilder *sb)
282 return mono_string_chars (sb->str);
286 mono_string_to_ansibstr (MonoString *string_obj)
288 g_error ("implement me");
293 mono_string_to_bstr (MonoString *string_obj)
295 g_error ("implement me");
300 mono_string_to_byvalstr (gpointer dst, MonoString *src, int size)
305 g_assert (dst != NULL);
308 memset (dst, 0, size);
313 s = mono_string_to_utf8 (src);
314 len = MIN (size, strlen (s));
315 memcpy (dst, s, len);
318 *((char *)dst + size - 1) = 0;
322 mono_string_to_byvalwstr (gpointer dst, MonoString *src, int size)
326 g_assert (dst != NULL);
330 memset (dst, 0, size);
334 len = MIN (size, (mono_string_length (src) * 2));
335 memcpy (dst, mono_string_chars (src), len);
337 *((char *)dst + size - 1) = 0;
338 *((char *)dst + size - 2) = 0;
342 mono_mb_free (MonoMethodBuilder *mb)
344 g_list_free (mb->locals_list);
349 mono_mb_new (MonoClass *klass, const char *name, MonoWrapperType type)
351 MonoMethodBuilder *mb;
354 g_assert (klass != NULL);
355 g_assert (name != NULL);
357 mb = g_new0 (MonoMethodBuilder, 1);
359 mb->method = m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
362 m->name = g_strdup (name);
364 m->inline_count = -1;
365 m->wrapper_type = type;
368 mb->code = g_malloc (mb->code_size);
374 mono_mb_add_local (MonoMethodBuilder *mb, MonoType *type)
376 int res = mb->locals;
378 g_assert (mb != NULL);
379 g_assert (type != NULL);
381 mb->locals_list = g_list_append (mb->locals_list, type);
388 mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack)
390 MonoMethodHeader *header;
394 g_assert (mb != NULL);
396 ((MonoMethodNormal *)mb->method)->header = header = (MonoMethodHeader *)
397 g_malloc0 (sizeof (MonoMethodHeader) + mb->locals * sizeof (MonoType *));
402 header->max_stack = max_stack;
404 for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
405 header->locals [i] = (MonoType *)l->data;
408 mb->method->signature = signature;
409 header->code = mb->code;
410 header->code_size = mb->pos;
411 header->num_locals = mb->locals;
413 #ifdef DEBUG_RUNTIME_CODE
414 printf ("RUNTIME CODE FOR %s\n", mono_method_full_name (mb->method, TRUE));
415 printf ("%s\n", mono_disasm_code (&marshal_dh, mb->method, mb->code, mb->code + mb->pos));
422 mono_mb_add_data (MonoMethodBuilder *mb, gpointer data)
424 MonoMethodWrapper *mw;
426 g_assert (mb != NULL);
428 mw = (MonoMethodWrapper *)mb->method;
430 mw->data = g_list_append (mw->data, data);
432 return g_list_length (mw->data);
436 mono_mb_patch_addr (MonoMethodBuilder *mb, int pos, int value)
438 mb->code [pos] = value & 0xff;
439 mb->code [pos + 1] = (value >> 8) & 0xff;
440 mb->code [pos + 2] = (value >> 16) & 0xff;
441 mb->code [pos + 3] = (value >> 24) & 0xff;
445 mono_mb_patch_addr_s (MonoMethodBuilder *mb, int pos, gint8 value)
447 *((gint8 *)(&mb->code [pos])) = value;
451 mono_mb_emit_byte (MonoMethodBuilder *mb, guint8 op)
453 if (mb->pos >= mb->code_size) {
455 mb->code = g_realloc (mb->code, mb->code_size);
458 mb->code [mb->pos++] = op;
462 mono_mb_emit_ldflda (MonoMethodBuilder *mb, gint32 offset)
464 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
465 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
468 mono_mb_emit_icon (mb, offset);
469 mono_mb_emit_byte (mb, CEE_ADD);
474 mono_mb_emit_proxy_check (MonoMethodBuilder *mb, int branch_code)
477 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoObject, vtable));
478 mono_mb_emit_byte (mb, CEE_LDIND_I);
479 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoVTable, klass));
480 mono_mb_emit_byte (mb, CEE_ADD);
481 mono_mb_emit_byte (mb, CEE_LDIND_I);
482 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
483 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
484 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_defaults.transparent_proxy_class));
485 mono_mb_emit_byte (mb, branch_code);
487 mono_mb_emit_i4 (mb, 0);
492 mono_mb_emit_i4 (MonoMethodBuilder *mb, gint32 data)
494 if ((mb->pos + 4) >= mb->code_size) {
496 mb->code = g_realloc (mb->code, mb->code_size);
499 mono_mb_patch_addr (mb, mb->pos, data);
504 mono_mb_emit_i2 (MonoMethodBuilder *mb, gint16 data)
506 if ((mb->pos + 2) >= mb->code_size) {
508 mb->code = g_realloc (mb->code, mb->code_size);
511 mb->code [mb->pos] = data & 0xff;
512 mb->code [mb->pos + 1] = (data >> 8) & 0xff;
517 mono_mb_emit_ldstr (MonoMethodBuilder *mb, char *str)
519 mono_mb_emit_byte (mb, CEE_LDSTR);
520 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, str));
525 mono_mb_emit_ldarg (MonoMethodBuilder *mb, guint argnum)
528 mono_mb_emit_byte (mb, CEE_LDARG_0 + argnum);
529 } else if (argnum < 256) {
530 mono_mb_emit_byte (mb, CEE_LDARG_S);
531 mono_mb_emit_byte (mb, argnum);
533 mono_mb_emit_byte (mb, CEE_PREFIX1);
534 mono_mb_emit_byte (mb, CEE_LDARG);
535 mono_mb_emit_i2 (mb, argnum);
540 mono_mb_emit_ldarg_addr (MonoMethodBuilder *mb, guint argnum)
543 mono_mb_emit_byte (mb, CEE_LDARGA_S);
544 mono_mb_emit_byte (mb, argnum);
546 mono_mb_emit_byte (mb, CEE_PREFIX1);
547 mono_mb_emit_byte (mb, CEE_LDARGA);
548 mono_mb_emit_i2 (mb, argnum);
553 mono_mb_emit_ldloc_addr (MonoMethodBuilder *mb, guint locnum)
556 mono_mb_emit_byte (mb, CEE_LDLOCA_S);
557 mono_mb_emit_byte (mb, locnum);
559 mono_mb_emit_byte (mb, CEE_PREFIX1);
560 mono_mb_emit_byte (mb, CEE_LDLOCA);
561 mono_mb_emit_i2 (mb, locnum);
566 mono_mb_emit_ldloc (MonoMethodBuilder *mb, guint num)
569 mono_mb_emit_byte (mb, CEE_LDLOC_0 + num);
570 } else if (num < 256) {
571 mono_mb_emit_byte (mb, CEE_LDLOC_S);
572 mono_mb_emit_byte (mb, num);
574 mono_mb_emit_byte (mb, CEE_PREFIX1);
575 mono_mb_emit_byte (mb, CEE_LDLOC);
576 mono_mb_emit_i2 (mb, num);
581 mono_mb_emit_stloc (MonoMethodBuilder *mb, guint num)
584 mono_mb_emit_byte (mb, CEE_STLOC_0 + num);
585 } else if (num < 256) {
586 mono_mb_emit_byte (mb, CEE_STLOC_S);
587 mono_mb_emit_byte (mb, num);
589 mono_mb_emit_byte (mb, CEE_PREFIX1);
590 mono_mb_emit_byte (mb, CEE_STLOC);
591 mono_mb_emit_i2 (mb, num);
596 mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value)
598 if (value >= -1 && value < 8) {
599 mono_mb_emit_byte (mb, CEE_LDC_I4_0 + value);
600 } else if (value >= -128 && value <= 127) {
601 mono_mb_emit_byte (mb, CEE_LDC_I4_S);
602 mono_mb_emit_byte (mb, value);
604 mono_mb_emit_byte (mb, CEE_LDC_I4);
605 mono_mb_emit_i4 (mb, value);
610 mono_mb_emit_branch (MonoMethodBuilder *mb, guint8 op)
613 mono_mb_emit_byte (mb, op);
615 mono_mb_emit_i4 (mb, 0);
620 mono_mb_emit_calli (MonoMethodBuilder *mb, MonoMethodSignature *sig)
622 mono_mb_emit_byte (mb, CEE_CALLI);
623 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
627 mono_mb_emit_managed_call (MonoMethodBuilder *mb, MonoMethod *method, MonoMethodSignature *opt_sig)
629 mono_mb_emit_byte (mb, CEE_PREFIX1);
630 mono_mb_emit_byte (mb, CEE_LDFTN);
631 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
632 mono_mb_emit_calli (mb, opt_sig ? opt_sig : method->signature);
636 mono_mb_emit_native_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, gpointer func)
638 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
639 mono_mb_emit_byte (mb, CEE_MONO_SAVE_LMF);
640 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
641 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
642 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, func));
643 mono_mb_emit_calli (mb, sig);
644 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
645 mono_mb_emit_byte (mb, CEE_MONO_RESTORE_LMF);
649 mono_mb_emit_icall (MonoMethodBuilder *mb, gpointer func)
651 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
652 mono_mb_emit_byte (mb, CEE_MONO_ICALL);
653 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, func));
657 mono_mb_emit_exception (MonoMethodBuilder *mb, const char *exc_name, const char *msg)
659 /* fixme: we need a better way to throw exception,
660 * supporting several exception types and messages */
661 MonoMethod *ctor = NULL;
663 MonoClass *mme = mono_class_from_name (mono_defaults.corlib, "System", exc_name);
665 mono_class_init (mme);
666 for (i = 0; i < mme->method.count; ++i) {
667 if (strcmp (mme->methods [i]->name, ".ctor") == 0 && mme->methods [i]->signature->param_count == 0) {
668 ctor = mme->methods [i];
673 mono_mb_emit_byte (mb, CEE_NEWOBJ);
674 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, ctor));
676 mono_mb_emit_byte (mb, CEE_DUP);
677 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoException, message));
678 mono_mb_emit_ldstr (mb, (char*)msg);
679 mono_mb_emit_byte (mb, CEE_STIND_I);
681 mono_mb_emit_byte (mb, CEE_THROW);
685 mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint16 local, gint32 incr)
687 mono_mb_emit_ldloc (mb, local);
688 mono_mb_emit_icon (mb, incr);
689 mono_mb_emit_byte (mb, CEE_ADD);
690 mono_mb_emit_stloc (mb, local);
694 emit_ptr_to_str_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv,
695 int usize, int msize, MonoMarshalSpec *mspec)
698 case MONO_MARSHAL_CONV_BOOL_I4:
699 mono_mb_emit_byte (mb, CEE_LDLOC_1);
700 mono_mb_emit_byte (mb, CEE_LDLOC_0);
701 mono_mb_emit_byte (mb, CEE_LDIND_I4);
702 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
703 mono_mb_emit_byte (mb, 3);
704 mono_mb_emit_byte (mb, CEE_LDC_I4_1);
705 mono_mb_emit_byte (mb, CEE_BR_S);
706 mono_mb_emit_byte (mb, 1);
707 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
708 mono_mb_emit_byte (mb, CEE_STIND_I1);
710 case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
711 mono_mb_emit_byte (mb, CEE_LDLOC_1);
712 mono_mb_emit_byte (mb, CEE_LDLOC_0);
713 mono_mb_emit_byte (mb, CEE_LDIND_I2);
714 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
715 mono_mb_emit_byte (mb, 3);
716 mono_mb_emit_byte (mb, CEE_LDC_I4_1);
717 mono_mb_emit_byte (mb, CEE_BR_S);
718 mono_mb_emit_byte (mb, 1);
719 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
720 mono_mb_emit_byte (mb, CEE_STIND_I1);
722 case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
723 MonoClass *eclass = NULL;
726 if (type->type == MONO_TYPE_SZARRAY) {
727 eclass = type->data.klass;
729 g_assert_not_reached ();
732 if (eclass->valuetype)
733 esize = mono_class_instance_size (eclass) - sizeof (MonoObject);
735 esize = sizeof (gpointer);
737 /* create a new array */
738 mono_mb_emit_byte (mb, CEE_LDLOC_1);
739 mono_mb_emit_icon (mb, mspec->data.array_data.num_elem);
740 mono_mb_emit_byte (mb, CEE_NEWARR);
741 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eclass));
742 mono_mb_emit_byte (mb, CEE_STIND_I);
744 /* copy the elements */
745 mono_mb_emit_byte (mb, CEE_LDLOC_1);
746 mono_mb_emit_byte (mb, CEE_LDIND_I);
747 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
748 mono_mb_emit_byte (mb, CEE_ADD);
749 mono_mb_emit_byte (mb, CEE_LDLOC_0);
750 mono_mb_emit_icon (mb, mspec->data.array_data.num_elem * esize);
751 mono_mb_emit_byte (mb, CEE_PREFIX1);
752 mono_mb_emit_byte (mb, CEE_CPBLK);
756 case MONO_MARSHAL_CONV_STR_BYVALSTR:
757 mono_mb_emit_byte (mb, CEE_LDLOC_1);
758 mono_mb_emit_byte (mb, CEE_LDLOC_0);
759 mono_mb_emit_icall (mb, mono_string_new_wrapper);
760 mono_mb_emit_byte (mb, CEE_STIND_I);
762 case MONO_MARSHAL_CONV_STR_LPTSTR:
763 case MONO_MARSHAL_CONV_STR_LPSTR:
764 mono_mb_emit_byte (mb, CEE_LDLOC_1);
765 mono_mb_emit_byte (mb, CEE_LDLOC_0);
766 mono_mb_emit_byte (mb, CEE_LDIND_I);
767 mono_mb_emit_icall (mb, mono_string_new_wrapper);
768 mono_mb_emit_byte (mb, CEE_STIND_I);
770 case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
771 MonoClass *klass = mono_class_from_mono_type (type);
772 int src_var, dst_var;
774 src_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
775 dst_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
777 /* *dst = new object */
778 mono_mb_emit_byte (mb, CEE_LDLOC_1);
779 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
780 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
781 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
782 mono_mb_emit_byte (mb, CEE_STIND_I);
784 /* save the old src pointer */
785 mono_mb_emit_byte (mb, CEE_LDLOC_0);
786 mono_mb_emit_stloc (mb, src_var);
787 /* save the old dst pointer */
788 mono_mb_emit_byte (mb, CEE_LDLOC_1);
789 mono_mb_emit_stloc (mb, dst_var);
791 /* dst = pointer to newly created object data */
792 mono_mb_emit_byte (mb, CEE_LDLOC_1);
793 mono_mb_emit_byte (mb, CEE_LDIND_I);
794 mono_mb_emit_icon (mb, sizeof (MonoObject));
795 mono_mb_emit_byte (mb, CEE_ADD);
796 mono_mb_emit_byte (mb, CEE_STLOC_1);
798 emit_struct_conv (mb, klass, TRUE);
800 /* restore the old src pointer */
801 mono_mb_emit_ldloc (mb, src_var);
802 mono_mb_emit_byte (mb, CEE_STLOC_0);
803 /* restore the old dst pointer */
804 mono_mb_emit_ldloc (mb, dst_var);
805 mono_mb_emit_byte (mb, CEE_STLOC_1);
808 case MONO_MARSHAL_CONV_DEL_FTN: {
809 /* fixme: we never convert functions back to delegates, dont
810 // know if thats the correct behaviour
814 case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
815 g_error ("Structure field of type %s can't be marshalled as LPArray", mono_class_from_mono_type (type)->name);
817 case MONO_MARSHAL_CONV_STR_LPWSTR:
818 case MONO_MARSHAL_CONV_STR_BSTR:
819 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
820 case MONO_MARSHAL_CONV_STR_TBSTR:
821 case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
822 case MONO_MARSHAL_CONV_STR_BYVALWSTR:
824 g_warning ("marshaling conversion %d not implemented", conv);
825 g_assert_not_reached ();
830 conv_to_icall (MonoMarshalConv conv)
833 case MONO_MARSHAL_CONV_STR_LPWSTR:
834 return mono_string_to_utf16;
835 case MONO_MARSHAL_CONV_LPWSTR_STR:
836 return mono_string_from_utf16;
837 case MONO_MARSHAL_CONV_LPSTR_STR:
838 return mono_string_new_wrapper;
839 case MONO_MARSHAL_CONV_STR_LPTSTR:
840 case MONO_MARSHAL_CONV_STR_LPSTR:
841 return mono_string_to_utf8;
842 case MONO_MARSHAL_CONV_STR_BSTR:
843 return mono_string_to_bstr;
844 case MONO_MARSHAL_CONV_STR_TBSTR:
845 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
846 return mono_string_to_ansibstr;
847 case MONO_MARSHAL_CONV_SB_LPSTR:
848 case MONO_MARSHAL_CONV_SB_LPTSTR:
849 return mono_string_builder_to_utf8;
850 case MONO_MARSHAL_CONV_SB_LPWSTR:
851 return mono_string_builder_to_utf16;
852 case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
853 return mono_array_to_savearray;
854 case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
855 return mono_array_to_lparray;
856 case MONO_MARSHAL_CONV_DEL_FTN:
857 return mono_delegate_to_ftnptr;
858 case MONO_MARSHAL_CONV_FTN_DEL:
859 return mono_ftnptr_to_delegate;
860 case MONO_MARSHAL_CONV_LPSTR_SB:
861 case MONO_MARSHAL_CONV_LPTSTR_SB:
862 return mono_string_utf8_to_builder;
863 case MONO_MARSHAL_CONV_LPWSTR_SB:
864 return mono_string_utf16_to_builder;
865 case MONO_MARSHAL_FREE_ARRAY:
866 return mono_marshal_free_array;
867 case MONO_MARSHAL_CONV_STR_BYVALSTR:
868 return mono_string_to_byvalstr;
869 case MONO_MARSHAL_CONV_STR_BYVALWSTR:
870 return mono_string_to_byvalwstr;
872 g_assert_not_reached ();
879 emit_str_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, int usize, int msize,
880 MonoMarshalSpec *mspec)
885 case MONO_MARSHAL_CONV_BOOL_I4:
886 mono_mb_emit_byte (mb, CEE_LDLOC_1);
887 mono_mb_emit_byte (mb, CEE_LDLOC_0);
888 mono_mb_emit_byte (mb, CEE_LDIND_U1);
889 mono_mb_emit_byte (mb, CEE_STIND_I4);
891 case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
892 mono_mb_emit_byte (mb, CEE_LDLOC_1);
893 mono_mb_emit_byte (mb, CEE_LDLOC_0);
894 mono_mb_emit_byte (mb, CEE_LDIND_U1);
895 mono_mb_emit_byte (mb, CEE_NEG);
896 mono_mb_emit_byte (mb, CEE_STIND_I2);
898 case MONO_MARSHAL_CONV_STR_LPWSTR:
899 case MONO_MARSHAL_CONV_STR_LPSTR:
900 case MONO_MARSHAL_CONV_STR_LPTSTR:
901 case MONO_MARSHAL_CONV_STR_BSTR:
902 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
903 case MONO_MARSHAL_CONV_STR_TBSTR: {
906 /* free space if free == true */
907 mono_mb_emit_byte (mb, CEE_LDLOC_2);
908 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
910 mono_mb_emit_byte (mb, 0);
911 mono_mb_emit_byte (mb, CEE_LDLOC_1);
912 mono_mb_emit_byte (mb, CEE_LDIND_I);
913 mono_mb_emit_icall (mb, g_free);
914 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
916 mono_mb_emit_byte (mb, CEE_LDLOC_1);
917 mono_mb_emit_byte (mb, CEE_LDLOC_0);
918 mono_mb_emit_byte (mb, CEE_LDIND_I);
919 mono_mb_emit_icall (mb, conv_to_icall (conv));
920 mono_mb_emit_byte (mb, CEE_STIND_I);
923 case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
924 case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
925 case MONO_MARSHAL_CONV_DEL_FTN:
926 mono_mb_emit_byte (mb, CEE_LDLOC_1);
927 mono_mb_emit_byte (mb, CEE_LDLOC_0);
928 mono_mb_emit_byte (mb, CEE_LDIND_I);
929 mono_mb_emit_icall (mb, conv_to_icall (conv));
930 mono_mb_emit_byte (mb, CEE_STIND_I);
932 case MONO_MARSHAL_CONV_STR_BYVALSTR:
933 case MONO_MARSHAL_CONV_STR_BYVALWSTR: {
937 mono_mb_emit_byte (mb, CEE_LDLOC_1); /* dst */
938 mono_mb_emit_byte (mb, CEE_LDLOC_0);
939 mono_mb_emit_byte (mb, CEE_LDIND_I); /* src String */
940 mono_mb_emit_icon (mb, usize);
941 mono_mb_emit_icall (mb, conv_to_icall (conv));
944 case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
945 MonoClass *eclass = NULL;
948 if (type->type == MONO_TYPE_SZARRAY) {
949 eclass = type->data.klass;
951 g_assert_not_reached ();
954 if (eclass->valuetype)
955 esize = mono_class_native_size (eclass, NULL);
957 esize = sizeof (gpointer);
962 mono_mb_emit_byte (mb, CEE_LDLOC_0);
963 mono_mb_emit_byte (mb, CEE_LDIND_I);
964 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
966 mono_mb_emit_byte (mb, 0);
968 mono_mb_emit_byte (mb, CEE_LDLOC_1);
969 mono_mb_emit_byte (mb, CEE_LDLOC_0);
970 mono_mb_emit_byte (mb, CEE_LDIND_I);
971 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
972 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
973 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
974 mono_mb_emit_byte (mb, CEE_ADD);
975 mono_mb_emit_icon (mb, mspec->data.array_data.num_elem * esize);
976 mono_mb_emit_byte (mb, CEE_PREFIX1);
977 mono_mb_emit_byte (mb, CEE_CPBLK);
978 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
981 case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
982 int src_var, dst_var;
984 src_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
985 dst_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
987 mono_mb_emit_byte (mb, CEE_LDLOC_0);
988 mono_mb_emit_byte (mb, CEE_LDIND_I);
989 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
991 mono_mb_emit_byte (mb, 0);
993 /* save the old src pointer */
994 mono_mb_emit_byte (mb, CEE_LDLOC_0);
995 mono_mb_emit_stloc (mb, src_var);
996 /* save the old dst pointer */
997 mono_mb_emit_byte (mb, CEE_LDLOC_1);
998 mono_mb_emit_stloc (mb, dst_var);
1000 /* src = pointer to object data */
1001 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1002 mono_mb_emit_byte (mb, CEE_LDIND_I);
1003 mono_mb_emit_icon (mb, sizeof (MonoObject));
1004 mono_mb_emit_byte (mb, CEE_ADD);
1005 mono_mb_emit_byte (mb, CEE_STLOC_0);
1007 emit_struct_conv (mb, mono_class_from_mono_type (type), FALSE);
1009 /* restore the old src pointer */
1010 mono_mb_emit_ldloc (mb, src_var);
1011 mono_mb_emit_byte (mb, CEE_STLOC_0);
1012 /* restore the old dst pointer */
1013 mono_mb_emit_ldloc (mb, dst_var);
1014 mono_mb_emit_byte (mb, CEE_STLOC_1);
1016 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
1020 char *msg = g_strdup_printf ("marshalling conversion %d not implemented", conv);
1021 MonoException *exc = mono_get_exception_not_implemented (msg);
1024 mono_raise_exception (exc);
1030 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
1032 MonoMarshalType *info;
1036 emit_struct_conv(mb, klass->parent, to_object);
1038 info = mono_marshal_load_type_info (klass);
1040 if (info->native_size == 0)
1043 if (klass->blittable) {
1044 int msize = mono_class_value_size (klass, NULL);
1045 g_assert (msize == info->native_size);
1046 mono_mb_emit_byte (mb, CEE_LDLOC_1);
1047 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1048 mono_mb_emit_icon (mb, msize);
1049 mono_mb_emit_byte (mb, CEE_PREFIX1);
1050 mono_mb_emit_byte (mb, CEE_CPBLK);
1052 mono_mb_emit_add_to_local (mb, 0, msize);
1053 mono_mb_emit_add_to_local (mb, 1, msize);
1057 for (i = 0; i < info->num_fields; i++) {
1058 MonoMarshalNative ntype;
1059 MonoMarshalConv conv;
1060 MonoType *ftype = info->fields [i].field->type;
1063 gboolean last_field = i < (info->num_fields -1) ? 0 : 1;
1065 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
1068 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, klass->unicode, &conv);
1071 msize = klass->instance_size - info->fields [i].field->offset;
1072 usize = info->native_size - info->fields [i].offset;
1074 msize = info->fields [i + 1].field->offset - info->fields [i].field->offset;
1075 usize = info->fields [i + 1].offset - info->fields [i].offset;
1077 if ((msize < 0) || (usize < 0))
1078 /* This happens with GC aware auto layout */
1079 g_error ("Type %s which is passed to unmanaged code must have a StructLayout attribute", mono_type_full_name (&klass->byval_arg));
1081 g_assert ((msize >= 0) && (usize >= 0));
1084 case MONO_MARSHAL_CONV_NONE: {
1087 if (ftype->byref || ftype->type == MONO_TYPE_I ||
1088 ftype->type == MONO_TYPE_U) {
1089 mono_mb_emit_byte (mb, CEE_LDLOC_1);
1090 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1091 mono_mb_emit_byte (mb, CEE_LDIND_I);
1092 mono_mb_emit_byte (mb, CEE_STIND_I);
1101 #if SIZEOF_VOID_P == 4
1104 mono_mb_emit_byte (mb, CEE_LDLOC_1);
1105 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1106 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1107 mono_mb_emit_byte (mb, CEE_STIND_I4);
1111 case MONO_TYPE_BOOLEAN:
1112 mono_mb_emit_byte (mb, CEE_LDLOC_1);
1113 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1114 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1115 mono_mb_emit_byte (mb, CEE_STIND_I1);
1119 case MONO_TYPE_CHAR:
1120 mono_mb_emit_byte (mb, CEE_LDLOC_1);
1121 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1122 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1123 mono_mb_emit_byte (mb, CEE_STIND_I2);
1127 #if SIZEOF_VOID_P == 8
1130 mono_mb_emit_byte (mb, CEE_LDLOC_1);
1131 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1132 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1133 mono_mb_emit_byte (mb, CEE_STIND_I8);
1136 mono_mb_emit_byte (mb, CEE_LDLOC_1);
1137 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1138 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1139 mono_mb_emit_byte (mb, CEE_STIND_R4);
1142 mono_mb_emit_byte (mb, CEE_LDLOC_1);
1143 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1144 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1145 mono_mb_emit_byte (mb, CEE_STIND_R8);
1147 case MONO_TYPE_VALUETYPE:
1148 if (ftype->data.klass->enumtype) {
1149 t = ftype->data.klass->enum_basetype->type;
1152 emit_struct_conv (mb, ftype->data.klass, to_object);
1155 g_warning ("marshaling type %02x not implemented", ftype->type);
1156 g_assert_not_reached ();
1162 emit_ptr_to_str_conv (mb, ftype, conv, usize, msize, info->fields [i].mspec);
1164 emit_str_to_ptr_conv (mb, ftype, conv, usize, msize, info->fields [i].mspec);
1168 mono_mb_emit_add_to_local (mb, 0, usize);
1169 mono_mb_emit_add_to_local (mb, 1, msize);
1171 mono_mb_emit_add_to_local (mb, 0, msize);
1172 mono_mb_emit_add_to_local (mb, 1, usize);
1178 emit_thread_interrupt_checkpoint (MonoMethodBuilder *mb)
1180 static MonoMethodSignature *state_check_sig = NULL;
1183 if (!state_check_sig) {
1184 state_check_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
1185 state_check_sig->ret = &mono_defaults.void_class->byval_arg;
1186 state_check_sig->pinvoke = 0;
1189 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1190 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1191 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, (gpointer) mono_thread_interruption_request_flag ()));
1192 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1193 pos_noabort = mono_mb_emit_branch (mb, CEE_BRFALSE);
1195 mono_mb_emit_native_call (mb, state_check_sig, mono_thread_interruption_checkpoint);
1197 mono_mb_patch_addr (mb, pos_noabort, mb->pos - (pos_noabort + 4));
1200 static MonoAsyncResult *
1201 mono_delegate_begin_invoke (MonoDelegate *delegate, gpointer *params)
1203 MonoMethodMessage *msg;
1204 MonoDelegate *async_callback;
1208 MonoMethod *method = NULL;
1211 g_assert (delegate);
1213 if (delegate->target && mono_object_class (delegate->target) == mono_defaults.transparent_proxy_class) {
1215 MonoTransparentProxy* tp = (MonoTransparentProxy *)delegate->target;
1216 if (!tp->remote_class->proxy_class->contextbound || tp->rp->context != (MonoObject *) mono_context_get ()) {
1218 /* If the target is a proxy, make a direct call. Is proxy's work
1219 // to make the call asynchronous.
1221 MonoAsyncResult *ares;
1223 MonoArray *out_args;
1225 method = delegate->method_info->method;
1227 msg = mono_method_call_message_new (mono_marshal_method_from_wrapper (method), params, NULL, &async_callback, &state);
1228 handle = CreateEvent (NULL, TRUE, FALSE, NULL);
1229 ares = mono_async_result_new (mono_domain_get (), handle, state, handle);
1230 ares->async_delegate = (MonoObject *)delegate;
1231 ares->async_callback = (MonoObject *)async_callback;
1232 msg->async_result = ares;
1233 msg->call_type = CallType_BeginInvoke;
1235 mono_remoting_invoke ((MonoObject *)tp->rp, msg, &exc, &out_args);
1240 klass = delegate->object.vtable->klass;
1242 method = mono_get_delegate_invoke (klass);
1243 for (i = 0; i < klass->method.count; ++i) {
1244 if (klass->methods [i]->name[0] == 'B' &&
1245 !strcmp ("BeginInvoke", klass->methods [i]->name)) {
1246 method = klass->methods [i];
1251 g_assert (method != NULL);
1253 im = mono_get_delegate_invoke (method->klass);
1254 msg = mono_method_call_message_new (method, params, im, &async_callback, &state);
1256 return mono_thread_pool_add ((MonoObject *)delegate, msg, async_callback, state);
1260 mono_mb_emit_save_args (MonoMethodBuilder *mb, MonoMethodSignature *sig, gboolean save_this)
1262 int i, params_var, tmp_var;
1264 /* allocate local (pointer) *params[] */
1265 params_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1266 /* allocate local (pointer) tmp */
1267 tmp_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1269 /* alloate space on stack to store an array of pointers to the arguments */
1270 mono_mb_emit_icon (mb, sizeof (gpointer) * (sig->param_count + 1));
1271 mono_mb_emit_byte (mb, CEE_PREFIX1);
1272 mono_mb_emit_byte (mb, CEE_LOCALLOC);
1273 mono_mb_emit_stloc (mb, params_var);
1276 mono_mb_emit_ldloc (mb, params_var);
1277 mono_mb_emit_stloc (mb, tmp_var);
1279 if (save_this && sig->hasthis) {
1280 mono_mb_emit_ldloc (mb, tmp_var);
1281 mono_mb_emit_ldarg_addr (mb, 0);
1282 mono_mb_emit_byte (mb, CEE_STIND_I);
1283 /* tmp = tmp + sizeof (gpointer) */
1284 if (sig->param_count)
1285 mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
1289 for (i = 0; i < sig->param_count; i++) {
1290 mono_mb_emit_ldloc (mb, tmp_var);
1291 mono_mb_emit_ldarg_addr (mb, i + sig->hasthis);
1292 mono_mb_emit_byte (mb, CEE_STIND_I);
1293 /* tmp = tmp + sizeof (gpointer) */
1294 if (i < (sig->param_count - 1))
1295 mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
1302 mono_signature_to_name (MonoMethodSignature *sig, const char *prefix)
1306 GString *res = g_string_new ("");
1309 g_string_append (res, prefix);
1310 g_string_append_c (res, '_');
1313 mono_type_get_desc (res, sig->ret, FALSE);
1315 for (i = 0; i < sig->param_count; ++i) {
1316 g_string_append_c (res, '_');
1317 mono_type_get_desc (res, sig->params [i], FALSE);
1320 g_string_free (res, FALSE);
1325 * mono_marshal_get_string_encoding:
1327 * Return the string encoding which should be used for a given parameter.
1329 static MonoMarshalNative
1330 mono_marshal_get_string_encoding (MonoMethodPInvoke *piinfo, MonoMarshalSpec *spec)
1332 /* First try the parameter marshal info */
1334 if (spec->native == MONO_NATIVE_LPARRAY) {
1335 if (spec->data.array_data.elem_type != 0)
1336 return spec->data.array_data.elem_type;
1339 return spec->native;
1343 return MONO_NATIVE_LPSTR;
1345 /* Then try the method level marshal info */
1346 switch (piinfo->piflags & PINVOKE_ATTRIBUTE_CHAR_SET_MASK) {
1347 case PINVOKE_ATTRIBUTE_CHAR_SET_ANSI:
1348 return MONO_NATIVE_LPSTR;
1349 case PINVOKE_ATTRIBUTE_CHAR_SET_UNICODE:
1350 return MONO_NATIVE_LPWSTR;
1351 case PINVOKE_ATTRIBUTE_CHAR_SET_AUTO:
1352 return MONO_NATIVE_LPTSTR;
1354 return MONO_NATIVE_LPSTR;
1358 static MonoMarshalNative
1359 mono_marshal_get_stringbuilder_to_ptr_encoding (MonoMethodPInvoke *piinfo, MonoMarshalSpec *spec)
1361 MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, spec);
1364 case MONO_NATIVE_LPWSTR:
1365 return MONO_MARSHAL_CONV_SB_LPWSTR;
1367 case MONO_NATIVE_LPSTR:
1368 return MONO_MARSHAL_CONV_SB_LPSTR;
1370 case MONO_NATIVE_LPTSTR:
1371 return MONO_MARSHAL_CONV_SB_LPTSTR;
1378 static MonoMarshalNative
1379 mono_marshal_get_ptr_to_stringbuilder_encoding (MonoMethodPInvoke *piinfo, MonoMarshalSpec *spec, gboolean *need_free)
1381 MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, spec);
1386 case MONO_NATIVE_LPWSTR:
1388 * mono_string_builder_to_utf16 does not allocate a
1389 * new buffer, so no need to free it.
1392 return MONO_MARSHAL_CONV_LPWSTR_SB;
1393 case MONO_NATIVE_LPSTR:
1394 return MONO_MARSHAL_CONV_LPSTR_SB;
1396 case MONO_NATIVE_LPTSTR:
1397 return MONO_MARSHAL_CONV_LPTSTR_SB;
1404 static inline MonoMethod*
1405 mono_marshal_find_in_cache (GHashTable *cache, gpointer key)
1409 EnterCriticalSection (&marshal_mutex);
1410 res = g_hash_table_lookup (cache, key);
1411 LeaveCriticalSection (&marshal_mutex);
1415 /* Create the method from the builder and place it in the cache */
1416 static inline MonoMethod*
1417 mono_mb_create_and_cache (GHashTable *cache, gpointer key,
1418 MonoMethodBuilder *mb, MonoMethodSignature *sig,
1423 EnterCriticalSection (&marshal_mutex);
1424 res = g_hash_table_lookup (cache, key);
1426 /* This does not acquire any locks */
1427 res = mono_mb_create_method (mb, sig, max_stack);
1428 g_hash_table_insert (cache, key, res);
1429 mono_g_hash_table_insert (wrapper_hash, res, key);
1432 /* Somebody created it before us */
1434 LeaveCriticalSection (&marshal_mutex);
1440 mono_marshal_method_from_wrapper (MonoMethod *wrapper)
1444 if (wrapper->wrapper_type == MONO_WRAPPER_NONE)
1447 EnterCriticalSection (&marshal_mutex);
1448 res = mono_g_hash_table_lookup (wrapper_hash, wrapper);
1449 LeaveCriticalSection (&marshal_mutex);
1451 if (res && wrapper->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)
1452 /* See mono_marshal_get_remoting_invoke_with_check */
1453 return (MonoMethod*)((char*)res - 1);
1459 mono_marshal_get_delegate_begin_invoke (MonoMethod *method)
1461 MonoMethodSignature *sig;
1462 static MonoMethodSignature *csig = NULL;
1463 MonoMethodBuilder *mb;
1469 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1470 !strcmp (method->name, "BeginInvoke"));
1472 sig = method->signature;
1474 cache = method->klass->image->delegate_begin_invoke_cache;
1475 if ((res = mono_marshal_find_in_cache (cache, sig)))
1478 g_assert (sig->hasthis);
1481 csig = mono_metadata_signature_alloc (method->klass->image, 2);
1483 /* MonoAsyncResult * begin_invoke (MonoDelegate *delegate, gpointer params[]) */
1484 csig->ret = &mono_defaults.object_class->byval_arg;
1485 csig->params [0] = &mono_defaults.object_class->byval_arg;
1486 csig->params [1] = &mono_defaults.int_class->byval_arg;
1489 name = mono_signature_to_name (sig, "begin_invoke");
1490 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_BEGIN_INVOKE);
1493 mb->method->save_lmf = 1;
1495 params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1497 mono_mb_emit_ldarg (mb, 0);
1498 mono_mb_emit_ldloc (mb, params_var);
1499 mono_mb_emit_native_call (mb, csig, mono_delegate_begin_invoke);
1500 emit_thread_interrupt_checkpoint (mb);
1501 mono_mb_emit_byte (mb, CEE_RET);
1503 res = mono_mb_create_and_cache (cache, sig, mb, sig, sig->param_count + 16);
1509 mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params)
1511 MonoDomain *domain = mono_domain_get ();
1512 MonoAsyncResult *ares;
1513 MonoMethod *method = NULL;
1514 MonoMethodSignature *sig;
1515 MonoMethodMessage *msg;
1516 MonoObject *res, *exc;
1517 MonoArray *out_args;
1521 g_assert (delegate);
1523 if (!delegate->method_info || !delegate->method_info->method)
1524 g_assert_not_reached ();
1526 klass = delegate->object.vtable->klass;
1528 for (i = 0; i < klass->method.count; ++i) {
1529 if (klass->methods [i]->name[0] == 'E' &&
1530 !strcmp ("EndInvoke", klass->methods [i]->name)) {
1531 method = klass->methods [i];
1536 g_assert (method != NULL);
1538 sig = method->signature;
1540 msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1542 ares = mono_array_get (msg->args, gpointer, sig->param_count - 1);
1545 if (delegate->target && mono_object_class (delegate->target) == mono_defaults.transparent_proxy_class) {
1546 MonoTransparentProxy* tp = (MonoTransparentProxy *)delegate->target;
1547 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
1548 mono_message_init (domain, msg, delegate->method_info, NULL);
1549 msg->call_type = CallType_EndInvoke;
1550 msg->async_result = ares;
1551 res = mono_remoting_invoke ((MonoObject *)tp->rp, msg, &exc, &out_args);
1554 res = mono_thread_pool_finish (ares, &out_args, &exc);
1557 if (((MonoException*)exc)->stack_trace) {
1558 char *strace = mono_string_to_utf8 (((MonoException*)exc)->stack_trace);
1560 tmp = g_strdup_printf ("%s\nException Rethrown at:\n", strace);
1562 ((MonoException*)exc)->stack_trace = mono_string_new (domain, tmp);
1565 mono_raise_exception ((MonoException*)exc);
1568 mono_method_return_message_restore (method, params, out_args);
1573 mono_mb_emit_restore_result (MonoMethodBuilder *mb, MonoType *return_type)
1575 if (return_type->byref)
1576 return_type = &mono_defaults.int_class->byval_arg;
1577 else if (return_type->type == MONO_TYPE_VALUETYPE && return_type->data.klass->enumtype)
1578 return_type = return_type->data.klass->enum_basetype;
1580 switch (return_type->type) {
1581 case MONO_TYPE_VOID:
1582 g_assert_not_reached ();
1585 case MONO_TYPE_STRING:
1586 case MONO_TYPE_CLASS:
1587 case MONO_TYPE_OBJECT:
1588 case MONO_TYPE_ARRAY:
1589 case MONO_TYPE_SZARRAY:
1593 case MONO_TYPE_BOOLEAN:
1594 mono_mb_emit_byte (mb, CEE_UNBOX);
1595 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1596 mono_mb_emit_byte (mb, CEE_LDIND_U1);
1599 mono_mb_emit_byte (mb, CEE_UNBOX);
1600 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1601 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1604 case MONO_TYPE_CHAR:
1605 mono_mb_emit_byte (mb, CEE_UNBOX);
1606 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1607 mono_mb_emit_byte (mb, CEE_LDIND_U2);
1610 mono_mb_emit_byte (mb, CEE_UNBOX);
1611 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1612 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1616 mono_mb_emit_byte (mb, CEE_UNBOX);
1617 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1618 mono_mb_emit_byte (mb, CEE_LDIND_I);
1621 mono_mb_emit_byte (mb, CEE_UNBOX);
1622 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1623 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1626 mono_mb_emit_byte (mb, CEE_UNBOX);
1627 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1628 mono_mb_emit_byte (mb, CEE_LDIND_U4);
1632 mono_mb_emit_byte (mb, CEE_UNBOX);
1633 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1634 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1637 mono_mb_emit_byte (mb, CEE_UNBOX);
1638 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1639 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1642 mono_mb_emit_byte (mb, CEE_UNBOX);
1643 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1644 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1646 case MONO_TYPE_VALUETYPE: {
1648 mono_mb_emit_byte (mb, CEE_UNBOX);
1649 class = mono_mb_add_data (mb, mono_class_from_mono_type (return_type));
1650 mono_mb_emit_i4 (mb, class);
1651 mono_mb_emit_byte (mb, CEE_LDOBJ);
1652 mono_mb_emit_i4 (mb, class);
1656 g_warning ("type 0x%x not handled", return_type->type);
1657 g_assert_not_reached ();
1660 mono_mb_emit_byte (mb, CEE_RET);
1664 mono_marshal_get_delegate_end_invoke (MonoMethod *method)
1666 MonoMethodSignature *sig;
1667 static MonoMethodSignature *csig = NULL;
1668 MonoMethodBuilder *mb;
1674 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1675 !strcmp (method->name, "EndInvoke"));
1677 sig = method->signature;
1679 cache = method->klass->image->delegate_end_invoke_cache;
1680 if ((res = mono_marshal_find_in_cache (cache, sig)))
1683 g_assert (sig->hasthis);
1686 csig = mono_metadata_signature_alloc (method->klass->image, 2);
1688 /* MonoObject *end_invoke (MonoDelegate *delegate, gpointer params[]) */
1689 csig->ret = &mono_defaults.object_class->byval_arg;
1690 csig->params [0] = &mono_defaults.object_class->byval_arg;
1691 csig->params [1] = &mono_defaults.int_class->byval_arg;
1694 name = mono_signature_to_name (sig, "end_invoke");
1695 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_END_INVOKE);
1698 mb->method->save_lmf = 1;
1700 params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1702 mono_mb_emit_ldarg (mb, 0);
1703 mono_mb_emit_ldloc (mb, params_var);
1704 mono_mb_emit_native_call (mb, csig, mono_delegate_end_invoke);
1705 emit_thread_interrupt_checkpoint (mb);
1707 if (sig->ret->type == MONO_TYPE_VOID) {
1708 mono_mb_emit_byte (mb, CEE_POP);
1709 mono_mb_emit_byte (mb, CEE_RET);
1711 mono_mb_emit_restore_result (mb, sig->ret);
1713 res = mono_mb_create_and_cache (cache, sig,
1714 mb, sig, sig->param_count + 16);
1721 mono_remoting_wrapper (MonoMethod *method, gpointer *params)
1723 MonoMethodMessage *msg;
1724 MonoTransparentProxy *this;
1725 MonoObject *res, *exc;
1726 MonoArray *out_args;
1728 this = *((MonoTransparentProxy **)params [0]);
1731 g_assert (((MonoObject *)this)->vtable->klass == mono_defaults.transparent_proxy_class);
1733 /* skip the this pointer */
1736 if (this->remote_class->proxy_class->contextbound && this->rp->context == (MonoObject *) mono_context_get ())
1739 MonoMethodSignature *sig = method->signature;
1740 int count = sig->param_count;
1741 gpointer* mparams = (gpointer*) alloca(count*sizeof(gpointer));
1743 for (i=0; i<count; i++) {
1744 MonoClass *class = mono_class_from_mono_type (sig->params [i]);
1745 if (class->valuetype) {
1746 if (sig->params [i]->byref)
1747 mparams[i] = *((gpointer *)params [i]);
1749 mparams[i] = params [i];
1751 mparams[i] = *((gpointer**)params [i]);
1755 return mono_runtime_invoke (method, method->klass->valuetype? mono_object_unbox ((MonoObject*)this): this, mparams, NULL);
1758 msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1760 res = mono_remoting_invoke ((MonoObject *)this->rp, msg, &exc, &out_args);
1763 mono_raise_exception ((MonoException *)exc);
1765 mono_method_return_message_restore (method, params, out_args);
1771 mono_marshal_get_remoting_invoke (MonoMethod *method)
1773 MonoMethodSignature *sig;
1774 static MonoMethodSignature *csig = NULL;
1775 MonoMethodBuilder *mb;
1782 if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE)
1785 sig = method->signature;
1787 /* we cant remote methods without this pointer */
1791 cache = method->klass->image->remoting_invoke_cache;
1792 if ((res = mono_marshal_find_in_cache (cache, method)))
1796 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
1797 csig->params [0] = &mono_defaults.int_class->byval_arg;
1798 csig->params [1] = &mono_defaults.int_class->byval_arg;
1799 csig->ret = &mono_defaults.object_class->byval_arg;
1803 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE);
1804 mb->method->save_lmf = 1;
1806 params_var = mono_mb_emit_save_args (mb, sig, TRUE);
1808 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1809 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1810 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
1811 mono_mb_emit_ldloc (mb, params_var);
1812 mono_mb_emit_native_call (mb, csig, mono_remoting_wrapper);
1813 emit_thread_interrupt_checkpoint (mb);
1815 if (sig->ret->type == MONO_TYPE_VOID) {
1816 mono_mb_emit_byte (mb, CEE_POP);
1817 mono_mb_emit_byte (mb, CEE_RET);
1819 mono_mb_emit_restore_result (mb, sig->ret);
1822 res = mono_mb_create_and_cache (cache, method, mb, sig, sig->param_count + 16);
1829 mono_marshal_get_remoting_invoke_with_check (MonoMethod *method)
1831 MonoMethodSignature *sig;
1832 MonoMethodBuilder *mb;
1833 MonoMethod *res, *native;
1839 if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)
1842 sig = method->signature;
1844 /* we cant remote methods without this pointer */
1845 g_assert (sig->hasthis);
1847 cache = method->klass->image->remoting_invoke_cache;
1848 if ((res = mono_marshal_find_in_cache (cache, (char *)method + 1)))
1851 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK);
1853 mono_mb_emit_ldarg (mb, 0);
1854 pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
1856 native = mono_marshal_get_remoting_invoke (method);
1858 for (i = 0; i <= sig->param_count; i++)
1859 mono_mb_emit_ldarg (mb, i);
1861 mono_mb_emit_managed_call (mb, native, native->signature);
1862 mono_mb_emit_byte (mb, CEE_RET);
1864 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1866 for (i = 0; i <= sig->param_count; i++)
1867 mono_mb_emit_ldarg (mb, i);
1869 mono_mb_emit_managed_call (mb, method, method->signature);
1870 mono_mb_emit_byte (mb, CEE_RET);
1872 res = mono_mb_create_and_cache (cache, (char*)method + 1,
1873 mb, sig, sig->param_count + 16);
1880 * the returned method invokes all methods in a multicast delegate
1883 mono_marshal_get_delegate_invoke (MonoMethod *method)
1885 MonoMethodSignature *sig, *static_sig;
1887 MonoMethodBuilder *mb;
1893 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1894 !strcmp (method->name, "Invoke"));
1896 sig = method->signature;
1898 cache = method->klass->image->delegate_invoke_cache;
1899 if ((res = mono_marshal_find_in_cache (cache, sig)))
1902 static_sig = mono_metadata_signature_dup (sig);
1903 static_sig->hasthis = 0;
1905 name = mono_signature_to_name (sig, "invoke");
1906 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_INVOKE);
1909 /* allocate local 0 (object) */
1910 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1912 g_assert (sig->hasthis);
1916 * prev.Invoke( args .. );
1917 * return this.<target>( args .. );
1920 /* this wrapper can be used in unmanaged-managed transitions */
1921 emit_thread_interrupt_checkpoint (mb);
1923 /* get this->prev */
1924 mono_mb_emit_ldarg (mb, 0);
1925 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoMulticastDelegate, prev));
1926 mono_mb_emit_byte (mb, CEE_LDIND_I );
1927 mono_mb_emit_stloc (mb, 0);
1929 /* if prev != null */
1930 mono_mb_emit_ldloc (mb, 0);
1931 mono_mb_emit_byte (mb, CEE_BRFALSE);
1934 mono_mb_emit_i4 (mb, 0);
1937 mono_mb_emit_ldloc (mb, 0);
1938 for (i = 0; i < sig->param_count; i++)
1939 mono_mb_emit_ldarg (mb, i + 1);
1940 mono_mb_emit_managed_call (mb, method, method->signature);
1941 if (sig->ret->type != MONO_TYPE_VOID)
1942 mono_mb_emit_byte (mb, CEE_POP);
1944 /* continued or prev == null */
1945 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1947 /* get this->target */
1948 mono_mb_emit_ldarg (mb, 0);
1949 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, target));
1950 mono_mb_emit_byte (mb, CEE_LDIND_I );
1951 mono_mb_emit_stloc (mb, 0);
1953 /* if target != null */
1954 mono_mb_emit_ldloc (mb, 0);
1955 mono_mb_emit_byte (mb, CEE_BRFALSE);
1957 mono_mb_emit_i4 (mb, 0);
1959 /* then call this->method_ptr nonstatic */
1960 mono_mb_emit_ldloc (mb, 0);
1961 for (i = 0; i < sig->param_count; ++i)
1962 mono_mb_emit_ldarg (mb, i + 1);
1963 mono_mb_emit_ldarg (mb, 0);
1964 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1965 mono_mb_emit_byte (mb, CEE_LDIND_I );
1966 mono_mb_emit_byte (mb, CEE_CALLI);
1967 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
1969 mono_mb_emit_byte (mb, CEE_BR);
1971 mono_mb_emit_i4 (mb, 0);
1973 /* else [target == null] call this->method_ptr static */
1974 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1976 for (i = 0; i < sig->param_count; ++i)
1977 mono_mb_emit_ldarg (mb, i + 1);
1978 mono_mb_emit_ldarg (mb, 0);
1979 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1980 mono_mb_emit_byte (mb, CEE_LDIND_I );
1981 mono_mb_emit_byte (mb, CEE_CALLI);
1982 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, static_sig));
1985 mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
1986 mono_mb_emit_byte (mb, CEE_RET);
1988 res = mono_mb_create_and_cache (cache, sig,
1989 mb, sig, sig->param_count + 16);
1996 * signature_dup_add_this:
1998 * Make a copy of @sig, adding an explicit this argument.
2000 static MonoMethodSignature*
2001 signature_dup_add_this (MonoMethodSignature *sig, MonoClass *klass)
2003 MonoMethodSignature *res;
2006 res = mono_metadata_signature_alloc (klass->image, sig->param_count + 1);
2007 memcpy (res, sig, sizeof (MonoMethodSignature));
2008 res->param_count = sig->param_count + 1;
2009 res->hasthis = FALSE;
2010 for (i = sig->param_count - 1; i >= 0; i --)
2011 res->params [i + 1] = sig->params [i];
2012 res->params [0] = &mono_ptr_class_get (&klass->byval_arg)->byval_arg;
2019 MonoMethodSignature *sig;
2023 * generates IL code for the runtime invoke function
2024 * MonoObject *runtime_invoke (MonoObject *this, void **params, MonoObject **exc, void* method)
2026 * we also catch exceptions if exc != null
2029 mono_marshal_get_runtime_invoke (MonoMethod *method)
2031 MonoMethodSignature *sig, *csig, *callsig;
2032 MonoExceptionClause *clause;
2033 MonoMethodHeader *header;
2034 MonoMethodBuilder *mb;
2035 GHashTable *cache = NULL;
2036 MonoClass *target_klass;
2037 MonoMethod *res = NULL;
2039 static MonoString *string_dummy = NULL;
2045 target_klass = method->klass;
2047 EnterCriticalSection (&marshal_mutex);
2049 if (method->string_ctor) {
2050 static GSList *strsig_list = NULL;
2054 for (item = strsig_list; item; item = item->next) {
2056 if (mono_metadata_signature_equal (method->signature, cs->ctor->signature)) {
2062 callsig = mono_metadata_signature_dup (method->signature);
2063 callsig->ret = &mono_defaults.string_class->byval_arg;
2064 cs = g_new (CtorSigPair, 1);
2067 strsig_list = g_slist_prepend (strsig_list, cs);
2070 if (method->klass->valuetype && method->signature->hasthis) {
2072 * Valuetype methods receive a managed pointer as the this argument.
2073 * Create a new signature to reflect this.
2075 callsig = signature_dup_add_this (method->signature, method->klass);
2078 callsig = method->signature;
2081 cache = method->klass->image->runtime_invoke_cache;
2083 /* from mono_marshal_find_in_cache */
2084 res = g_hash_table_lookup (cache, callsig);
2085 LeaveCriticalSection (&marshal_mutex);
2091 target_klass = mono_defaults.object_class;
2093 /* to make it work with our special string constructors */
2094 if (!string_dummy) {
2095 MONO_GC_REGISTER_ROOT (string_dummy);
2096 string_dummy = mono_string_new_wrapper ("dummy");
2099 sig = method->signature;
2101 csig = mono_metadata_signature_alloc (method->klass->image, 4);
2103 csig->ret = &mono_defaults.object_class->byval_arg;
2104 if (method->klass->valuetype && method->signature->hasthis)
2105 csig->params [0] = callsig->params [0];
2107 csig->params [0] = &mono_defaults.object_class->byval_arg;
2108 csig->params [1] = &mono_defaults.int_class->byval_arg;
2109 csig->params [2] = &mono_defaults.int_class->byval_arg;
2110 csig->params [3] = &mono_defaults.int_class->byval_arg;
2112 name = mono_signature_to_name (callsig, "runtime_invoke");
2113 mb = mono_mb_new (target_klass, name, MONO_WRAPPER_RUNTIME_INVOKE);
2116 /* allocate local 0 (object) tmp */
2117 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2118 /* allocate local 1 (object) exc */
2119 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2121 /* cond set *exc to null */
2122 mono_mb_emit_byte (mb, CEE_LDARG_2);
2123 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
2124 mono_mb_emit_byte (mb, 3);
2125 mono_mb_emit_byte (mb, CEE_LDARG_2);
2126 mono_mb_emit_byte (mb, CEE_LDNULL);
2127 mono_mb_emit_byte (mb, CEE_STIND_I);
2130 if (method->string_ctor) {
2131 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2132 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
2133 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, string_dummy));
2135 mono_mb_emit_ldarg (mb, 0);
2139 for (i = 0; i < sig->param_count; i++) {
2140 MonoType *t = sig->params [i];
2143 mono_mb_emit_ldarg (mb, 1);
2145 mono_mb_emit_icon (mb, sizeof (gpointer) * i);
2146 mono_mb_emit_byte (mb, CEE_ADD);
2148 mono_mb_emit_byte (mb, CEE_LDIND_I);
2153 type = sig->params [i]->type;
2157 mono_mb_emit_byte (mb, CEE_LDIND_I1);
2159 case MONO_TYPE_BOOLEAN:
2161 mono_mb_emit_byte (mb, CEE_LDIND_U1);
2164 mono_mb_emit_byte (mb, CEE_LDIND_I2);
2167 case MONO_TYPE_CHAR:
2168 mono_mb_emit_byte (mb, CEE_LDIND_U2);
2172 mono_mb_emit_byte (mb, CEE_LDIND_I);
2175 mono_mb_emit_byte (mb, CEE_LDIND_I4);
2178 mono_mb_emit_byte (mb, CEE_LDIND_U4);
2181 mono_mb_emit_byte (mb, CEE_LDIND_R4);
2184 mono_mb_emit_byte (mb, CEE_LDIND_R8);
2188 mono_mb_emit_byte (mb, CEE_LDIND_I8);
2190 case MONO_TYPE_STRING:
2191 case MONO_TYPE_CLASS:
2192 case MONO_TYPE_ARRAY:
2194 case MONO_TYPE_SZARRAY:
2195 case MONO_TYPE_OBJECT:
2198 case MONO_TYPE_VALUETYPE:
2199 if (t->data.klass->enumtype) {
2200 type = t->data.klass->enum_basetype->type;
2203 mono_mb_emit_byte (mb, CEE_LDOBJ);
2204 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, t->data.klass));
2207 g_assert_not_reached ();
2211 mono_mb_emit_ldarg (mb, 3);
2212 mono_mb_emit_calli (mb, callsig);
2214 if (sig->ret->byref) {
2216 g_assert_not_reached ();
2220 switch (sig->ret->type) {
2221 case MONO_TYPE_VOID:
2222 if (!method->string_ctor)
2223 mono_mb_emit_byte (mb, CEE_LDNULL);
2225 case MONO_TYPE_BOOLEAN:
2226 case MONO_TYPE_CHAR:
2239 case MONO_TYPE_VALUETYPE:
2240 /* box value types */
2241 mono_mb_emit_byte (mb, CEE_BOX);
2242 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (sig->ret)));
2244 case MONO_TYPE_STRING:
2245 case MONO_TYPE_CLASS:
2246 case MONO_TYPE_ARRAY:
2247 case MONO_TYPE_SZARRAY:
2248 case MONO_TYPE_OBJECT:
2253 g_assert_not_reached ();
2256 mono_mb_emit_stloc (mb, 0);
2258 mono_mb_emit_byte (mb, CEE_LEAVE);
2260 mono_mb_emit_i4 (mb, 0);
2262 clause = g_new0 (MonoExceptionClause, 1);
2263 clause->flags = MONO_EXCEPTION_CLAUSE_FILTER;
2264 clause->try_len = mb->pos;
2267 clause->token_or_filter = mb->pos;
2269 mono_mb_emit_byte (mb, CEE_POP);
2270 mono_mb_emit_byte (mb, CEE_LDARG_2);
2271 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
2272 mono_mb_emit_byte (mb, CEE_PREFIX1);
2273 mono_mb_emit_byte (mb, CEE_CGT_UN);
2274 mono_mb_emit_byte (mb, CEE_PREFIX1);
2275 mono_mb_emit_byte (mb, CEE_ENDFILTER);
2277 clause->handler_offset = mb->pos;
2280 /* store exception */
2281 mono_mb_emit_stloc (mb, 1);
2283 mono_mb_emit_byte (mb, CEE_LDARG_2);
2284 mono_mb_emit_ldloc (mb, 1);
2285 mono_mb_emit_byte (mb, CEE_STIND_I);
2287 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
2288 mono_mb_emit_stloc (mb, 0);
2290 mono_mb_emit_byte (mb, CEE_LEAVE);
2291 mono_mb_emit_i4 (mb, 0);
2293 clause->handler_len = mb->pos - clause->handler_offset;
2296 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2297 mono_mb_emit_ldloc (mb, 0);
2298 mono_mb_emit_byte (mb, CEE_RET);
2300 /* taken from mono_mb_create_and_cache */
2301 EnterCriticalSection (&marshal_mutex);
2303 res = g_hash_table_lookup (cache, callsig);
2304 /* Somebody may have created it before us */
2306 res = mono_mb_create_method (mb, csig, sig->param_count + 16);
2307 g_hash_table_insert (cache, callsig, res);
2308 mono_g_hash_table_insert (wrapper_hash, res, callsig);
2311 LeaveCriticalSection (&marshal_mutex);
2312 /* end mono_mb_create_and_cache */
2316 header = ((MonoMethodNormal *)res)->header;
2317 header->num_clauses = 1;
2318 header->clauses = clause;
2324 * generates IL code to call managed methods from unmanaged code
2327 mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this, MonoMarshalSpec **mspecs)
2329 MonoMethodSignature *sig, *csig;
2330 MonoMethodBuilder *mb;
2331 MonoClass *klass = NULL;
2334 int i, pos = 0, *tmp_locals;
2335 static MonoMethodSignature *alloc_sig = NULL;
2338 g_assert (method != NULL);
2339 g_assert (!method->signature->pinvoke);
2341 cache = method->klass->image->managed_wrapper_cache;
2342 if (!this && (res = mono_marshal_find_in_cache (cache, method)))
2345 /* Under MS, the allocation should be done using CoTaskMemAlloc */
2347 alloc_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
2348 alloc_sig->params [0] = &mono_defaults.int_class->byval_arg;
2349 alloc_sig->ret = &mono_defaults.int_class->byval_arg;
2350 alloc_sig->pinvoke = 1;
2354 /* fime: howto free that memory ? */
2357 sig = method->signature;
2359 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_NATIVE_TO_MANAGED);
2361 /* allocate local 0 (pointer) src_ptr */
2362 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2363 /* allocate local 1 (pointer) dst_ptr */
2364 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2365 /* allocate local 2 (boolean) delete_old */
2366 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2368 if (!MONO_TYPE_IS_VOID(sig->ret)) {
2369 /* allocate local 3 to store the return value */
2370 mono_mb_add_local (mb, sig->ret);
2373 mono_mb_emit_icon (mb, 0);
2374 mono_mb_emit_byte (mb, CEE_STLOC_2);
2376 /* we copy the signature, so that we can modify it */
2377 csig = mono_metadata_signature_dup (sig);
2381 #ifdef PLATFORM_WIN32
2383 * Under windows, delegates passed to native code must use the STDCALL
2384 * calling convention.
2386 csig->call_convention = MONO_CALL_STDCALL;
2389 /* fixme: howto handle this ? */
2393 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2394 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
2395 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, this));
2400 g_assert_not_reached ();
2405 /* we first do all conversions */
2406 tmp_locals = alloca (sizeof (int) * sig->param_count);
2407 for (i = 0; i < sig->param_count; i ++) {
2408 MonoType *t = sig->params [i];
2409 MonoMarshalSpec *spec = mspecs [i + 1];
2413 /* Ensure that we have marshalling info for this param */
2414 mono_marshal_load_type_info (mono_class_from_mono_type (t));
2416 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
2419 MonoMethod *marshal_native_to_managed;
2420 MonoMethod *get_instance;
2422 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
2423 g_assert (mtype != NULL);
2424 mklass = mono_class_from_mono_type (mtype);
2425 g_assert (mklass != NULL);
2427 marshal_native_to_managed = mono_find_method_by_name (mklass, "MarshalNativeToManaged", 1);
2428 g_assert (marshal_native_to_managed);
2429 get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
2430 g_assert (get_instance);
2433 case MONO_TYPE_CLASS:
2434 case MONO_TYPE_OBJECT:
2435 case MONO_TYPE_STRING:
2436 case MONO_TYPE_ARRAY:
2437 case MONO_TYPE_SZARRAY:
2441 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2443 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
2445 mono_mb_emit_byte (mb, CEE_CALL);
2446 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
2448 mono_mb_emit_ldarg (mb, i);
2450 mono_mb_emit_byte (mb, CEE_CALLVIRT);
2451 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_native_to_managed));
2453 mono_mb_emit_stloc (mb, tmp_locals [i]);
2456 g_warning ("custom marshalling of type %x is currently not supported", t->type);
2457 g_assert_not_reached ();
2464 case MONO_TYPE_CLASS: {
2465 klass = t->data.klass;
2467 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2469 if (klass->delegate) {
2470 g_assert (!t->byref);
2471 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2472 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
2473 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2474 mono_mb_emit_ldarg (mb, i);
2475 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL));
2476 mono_mb_emit_stloc (mb, tmp_locals [i]);
2480 /* FIXME: Raise a MarshalDirectiveException here */
2481 g_assert ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT);
2483 if (t->attrs & PARAM_ATTRIBUTE_OUT) {
2484 mono_mb_emit_byte (mb, CEE_LDNULL);
2485 mono_mb_emit_stloc (mb, tmp_locals [i]);
2490 mono_mb_emit_ldarg (mb, i);
2494 /* Check for NULL and raise an exception */
2495 mono_mb_emit_byte (mb, CEE_BRTRUE);
2497 mono_mb_emit_i4 (mb, 0);
2499 mono_mb_emit_exception (mb, "ArgumentNullException", NULL);
2501 mono_mb_patch_addr (mb, pos2, mb->pos - (pos2 + 4));
2502 mono_mb_emit_ldarg (mb, i);
2503 mono_mb_emit_byte (mb, CEE_LDIND_I);
2506 mono_mb_emit_byte (mb, CEE_STLOC_0);
2508 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
2509 mono_mb_emit_stloc (mb, tmp_locals [i]);
2511 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2512 mono_mb_emit_byte (mb, CEE_BRFALSE);
2514 mono_mb_emit_i4 (mb, 0);
2516 /* Create and set dst */
2517 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2518 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
2519 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2520 mono_mb_emit_stloc (mb, tmp_locals [i]);
2521 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2522 mono_mb_emit_icon (mb, sizeof (MonoObject));
2523 mono_mb_emit_byte (mb, CEE_ADD);
2524 mono_mb_emit_byte (mb, CEE_STLOC_1);
2526 /* emit valuetype conversion code */
2527 emit_struct_conv (mb, klass, TRUE);
2529 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2532 case MONO_TYPE_VALUETYPE:
2534 klass = sig->params [i]->data.klass;
2535 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2536 klass->blittable || klass->enumtype)
2539 tmp_locals [i] = mono_mb_add_local (mb, &klass->byval_arg);
2541 if (t->attrs & PARAM_ATTRIBUTE_OUT)
2545 mono_mb_emit_ldarg (mb, i);
2547 mono_mb_emit_ldarg_addr (mb, i);
2548 mono_mb_emit_byte (mb, CEE_STLOC_0);
2551 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2552 mono_mb_emit_byte (mb, CEE_BRFALSE);
2554 mono_mb_emit_i4 (mb, 0);
2557 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2558 mono_mb_emit_byte (mb, CEE_STLOC_1);
2560 /* emit valuetype conversion code */
2561 emit_struct_conv (mb, klass, TRUE);
2564 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2566 case MONO_TYPE_STRING: {
2567 MonoMarshalNative encoding = mono_marshal_get_string_encoding (NULL, spec);
2572 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2573 csig->params [i] = &mono_defaults.int_class->byval_arg;
2575 mono_mb_emit_ldarg (mb, i);
2578 case MONO_NATIVE_LPWSTR:
2579 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_LPWSTR_STR));
2581 case MONO_NATIVE_LPSTR:
2582 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_LPSTR_STR));
2585 char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding);
2586 MonoException *exc = mono_get_exception_not_implemented (msg);
2589 mono_raise_exception (exc);
2593 mono_mb_emit_stloc (mb, tmp_locals [i]);
2596 case MONO_TYPE_ARRAY:
2597 case MONO_TYPE_SZARRAY:
2601 klass = mono_class_from_mono_type (t);
2603 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2604 csig->params [i] = &mono_defaults.int_class->byval_arg;
2606 g_warning ("array marshaling not implemented");
2607 g_assert_not_reached ();
2612 for (i = 0; i < sig->param_count; i++) {
2613 MonoType *t = sig->params [i];
2616 case MONO_TYPE_BOOLEAN:
2630 mono_mb_emit_ldarg (mb, i);
2632 case MONO_TYPE_STRING:
2634 mono_mb_emit_ldarg (mb, i);
2636 g_assert (tmp_locals [i]);
2637 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2640 case MONO_TYPE_CLASS:
2642 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2644 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2646 case MONO_TYPE_ARRAY:
2647 case MONO_TYPE_SZARRAY:
2648 case MONO_TYPE_OBJECT:
2650 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2652 mono_mb_emit_ldarg (mb, i);
2654 case MONO_TYPE_VALUETYPE:
2655 klass = sig->params [i]->data.klass;
2656 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2657 klass->blittable || klass->enumtype) {
2658 mono_mb_emit_ldarg (mb, i);
2662 g_assert (tmp_locals [i]);
2664 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2666 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2669 g_warning ("type 0x%02x unknown", t->type);
2670 g_assert_not_reached ();
2674 emit_thread_interrupt_checkpoint (mb);
2675 mono_mb_emit_managed_call (mb, method, NULL);
2677 /* Ensure that we have marshalling info for the return */
2678 mono_marshal_load_type_info (mono_class_from_mono_type (sig->ret));
2680 if (mspecs [0] && mspecs [0]->native == MONO_NATIVE_CUSTOM) {
2681 MonoMarshalSpec *spec = mspecs [0];
2686 g_assert (!sig->ret->byref);
2688 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
2690 mklass = mono_class_from_mono_type (mtype);
2693 loc1 = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2695 switch (sig->ret->type) {
2696 case MONO_TYPE_CLASS:
2697 case MONO_TYPE_OBJECT:
2698 case MONO_TYPE_STRING:
2699 case MONO_TYPE_ARRAY:
2700 case MONO_TYPE_SZARRAY:
2701 mono_mb_emit_byte (mb, CEE_STLOC_3);
2703 mono_mb_emit_byte (mb, CEE_LDLOC_3);
2704 mono_mb_emit_stloc (mb, loc1);
2706 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
2707 mono_mb_emit_byte (mb, CEE_CALL);
2708 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_find_method_by_name (mklass, "GetInstance", 1)));
2709 mono_mb_emit_byte (mb, CEE_DUP);
2711 mono_mb_emit_byte (mb, CEE_LDLOC_3);
2712 mono_mb_emit_byte (mb, CEE_CALLVIRT);
2713 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_find_method_by_name (mklass, "MarshalManagedToNative", 1)));
2714 mono_mb_emit_byte (mb, CEE_STLOC_3);
2716 mono_mb_emit_ldloc (mb, loc1);
2717 mono_mb_emit_byte (mb, CEE_CALLVIRT);
2718 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_find_method_by_name (mklass, "CleanUpManagedData", 1)));
2722 g_warning ("custom marshalling of type %x is currently not supported", sig->ret->type);
2723 g_assert_not_reached ();
2728 if (!sig->ret->byref) {
2729 switch (sig->ret->type) {
2730 case MONO_TYPE_VOID:
2732 case MONO_TYPE_BOOLEAN:
2746 case MONO_TYPE_OBJECT:
2747 mono_mb_emit_byte (mb, CEE_STLOC_3);
2749 case MONO_TYPE_STRING:
2750 csig->ret = &mono_defaults.int_class->byval_arg;
2752 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_STR_LPSTR));
2753 mono_mb_emit_byte (mb, CEE_STLOC_3);
2755 case MONO_TYPE_VALUETYPE:
2756 klass = sig->ret->data.klass;
2757 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2758 klass->blittable || klass->enumtype)
2761 /* load pointer to returned value type */
2762 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2763 mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
2765 /* store the address of the source into local variable 0 */
2766 mono_mb_emit_byte (mb, CEE_STLOC_0);
2767 /* allocate space for the native struct and
2768 * store the address into dst_ptr */
2769 retobj_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2770 g_assert (retobj_var);
2771 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2772 mono_mb_emit_byte (mb, CEE_CONV_I);
2773 mono_mb_emit_native_call (mb, alloc_sig, mono_marshal_alloc);
2774 emit_thread_interrupt_checkpoint (mb);
2775 mono_mb_emit_byte (mb, CEE_STLOC_1);
2776 mono_mb_emit_byte (mb, CEE_LDLOC_1);
2777 mono_mb_emit_stloc (mb, retobj_var);
2779 /* emit valuetype conversion code */
2780 emit_struct_conv (mb, klass, FALSE);
2782 case MONO_TYPE_CLASS: {
2785 klass = sig->ret->data.klass;
2787 if (klass->delegate) {
2788 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN));
2789 mono_mb_emit_byte (mb, CEE_STLOC_3);
2793 /* FIXME: Raise a MarshalDirectiveException here */
2794 g_assert ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT);
2796 mono_mb_emit_byte (mb, CEE_STLOC_0);
2797 /* Check for null */
2798 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2799 pos = mono_mb_emit_branch (mb, CEE_BRTRUE);
2800 mono_mb_emit_byte (mb, CEE_LDNULL);
2801 mono_mb_emit_byte (mb, CEE_STLOC_3);
2802 pos2 = mono_mb_emit_branch (mb, CEE_BR);
2804 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2807 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2808 mono_mb_emit_icon (mb, sizeof (MonoObject));
2809 mono_mb_emit_byte (mb, CEE_ADD);
2810 mono_mb_emit_byte (mb, CEE_STLOC_0);
2812 /* Allocate and set dest */
2813 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2814 mono_mb_emit_byte (mb, CEE_CONV_I);
2815 mono_mb_emit_native_call (mb, alloc_sig, mono_marshal_alloc);
2816 emit_thread_interrupt_checkpoint (mb);
2817 mono_mb_emit_byte (mb, CEE_DUP);
2818 mono_mb_emit_byte (mb, CEE_STLOC_1);
2819 mono_mb_emit_byte (mb, CEE_STLOC_3);
2821 emit_struct_conv (mb, klass, FALSE);
2823 mono_mb_patch_addr (mb, pos2, mb->pos - (pos2 + 4));
2827 g_warning ("return type 0x%02x unknown", sig->ret->type);
2828 g_assert_not_reached ();
2831 mono_mb_emit_byte (mb, CEE_STLOC_3);
2834 /* Convert byref arguments back */
2835 for (i = 0; i < sig->param_count; i ++) {
2836 MonoType *t = sig->params [i];
2837 MonoMarshalSpec *spec = mspecs [i + 1];
2839 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
2842 MonoMethod *cleanup_managed;
2843 MonoMethod *get_instance;
2845 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
2846 g_assert (mtype != NULL);
2847 mklass = mono_class_from_mono_type (mtype);
2848 g_assert (mklass != NULL);
2850 get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
2851 g_assert (get_instance);
2852 cleanup_managed = mono_find_method_by_name (mklass, "CleanUpManagedData", 1);
2853 g_assert (cleanup_managed);
2856 case MONO_TYPE_CLASS:
2857 case MONO_TYPE_OBJECT:
2858 case MONO_TYPE_STRING:
2859 case MONO_TYPE_ARRAY:
2860 case MONO_TYPE_SZARRAY:
2862 g_assert_not_reached ();
2864 /* Call CleanUpManagedData */
2866 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
2868 mono_mb_emit_byte (mb, CEE_CALL);
2869 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
2871 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2872 mono_mb_emit_byte (mb, CEE_CALLVIRT);
2873 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, cleanup_managed));
2877 g_warning ("custom marshalling of type %x is currently not supported", t->type);
2878 g_assert_not_reached ();
2888 case MONO_TYPE_CLASS: {
2891 klass = t->data.klass;
2893 /* Check for null */
2894 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2895 pos = mono_mb_emit_branch (mb, CEE_BRTRUE);
2896 mono_mb_emit_ldarg (mb, i);
2897 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
2898 mono_mb_emit_byte (mb, CEE_STIND_I);
2899 pos2 = mono_mb_emit_branch (mb, CEE_BR);
2901 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2904 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2905 mono_mb_emit_icon (mb, sizeof (MonoObject));
2906 mono_mb_emit_byte (mb, CEE_ADD);
2907 mono_mb_emit_byte (mb, CEE_STLOC_0);
2909 /* Allocate and set dest */
2910 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2911 mono_mb_emit_byte (mb, CEE_CONV_I);
2912 mono_mb_emit_native_call (mb, alloc_sig, mono_marshal_alloc);
2913 emit_thread_interrupt_checkpoint (mb);
2914 mono_mb_emit_byte (mb, CEE_STLOC_1);
2916 /* Update argument pointer */
2917 mono_mb_emit_ldarg (mb, i);
2918 mono_mb_emit_byte (mb, CEE_LDLOC_1);
2919 mono_mb_emit_byte (mb, CEE_STIND_I);
2921 /* emit valuetype conversion code */
2922 emit_struct_conv (mb, klass, FALSE);
2924 mono_mb_patch_addr (mb, pos2, mb->pos - (pos2 + 4));
2927 case MONO_TYPE_VALUETYPE: {
2930 klass = t->data.klass;
2932 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2933 klass->blittable || klass->enumtype) {
2937 /* Check for null */
2938 mono_mb_emit_ldarg (mb, i);
2939 pos2 = mono_mb_emit_branch (mb, CEE_BRFALSE);
2942 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2943 mono_mb_emit_byte (mb, CEE_STLOC_0);
2946 mono_mb_emit_ldarg (mb, i);
2947 mono_mb_emit_byte (mb, CEE_STLOC_1);
2949 /* emit valuetype conversion code */
2950 emit_struct_conv (mb, klass, FALSE);
2952 mono_mb_patch_addr (mb, pos2, mb->pos - (pos2 + 4));
2959 mono_mb_emit_ldloc (mb, retobj_var);
2960 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2961 mono_mb_emit_byte (mb, CEE_MONO_RETOBJ);
2962 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2965 if (!MONO_TYPE_IS_VOID(sig->ret))
2966 mono_mb_emit_byte (mb, CEE_LDLOC_3);
2967 mono_mb_emit_byte (mb, CEE_RET);
2971 res = mono_mb_create_and_cache (cache, method,
2972 mb, csig, sig->param_count + 16);
2974 res = mono_mb_create_method (mb, csig, sig->param_count + 16);
2977 /* printf ("CODE FOR %s: \n%s.\n", mono_method_full_name (res, TRUE), mono_disasm_code (0, res, ((MonoMethodNormal*)res)->header->code, ((MonoMethodNormal*)res)->header->code + ((MonoMethodNormal*)res)->header->code_size)); */
2983 * mono_marshal_get_ldfld_wrapper:
2984 * @type: the type of the field
2986 * This method generates a function which can be use to load a field with type
2987 * @type from an object. The generated function has the following signature:
2988 * <@type> ldfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset)
2991 mono_marshal_get_ldfld_wrapper (MonoType *type)
2993 MonoMethodSignature *sig, *csig;
2994 MonoMethodBuilder *mb;
2997 static GHashTable *ldfld_hash = NULL;
2999 int t, pos0, pos1 = 0;
3004 if (type->type == MONO_TYPE_SZARRAY) {
3005 klass = mono_defaults.array_class;
3006 } else if (type->type == MONO_TYPE_VALUETYPE) {
3007 klass = type->data.klass;
3008 if (klass->enumtype) {
3009 t = klass->enum_basetype->type;
3010 klass = mono_class_from_mono_type (klass->enum_basetype);
3012 } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
3013 t == MONO_TYPE_CLASS) {
3014 klass = mono_defaults.object_class;
3015 } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
3016 klass = mono_defaults.int_class;
3018 klass = mono_class_from_mono_type (type);
3021 klass = mono_defaults.int_class;
3024 EnterCriticalSection (&marshal_mutex);
3026 ldfld_hash = g_hash_table_new (NULL, NULL);
3027 res = g_hash_table_lookup (ldfld_hash, klass);
3028 LeaveCriticalSection (&marshal_mutex);
3032 name = g_strdup_printf ("__ldfld_wrapper_%s.%s", klass->name_space, klass->name);
3033 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_LDFLD);
3036 mb->method->save_lmf = 1;
3038 sig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
3039 sig->params [0] = &mono_defaults.object_class->byval_arg;
3040 sig->params [1] = &mono_defaults.int_class->byval_arg;
3041 sig->params [2] = &mono_defaults.int_class->byval_arg;
3042 sig->params [3] = &mono_defaults.int_class->byval_arg;
3043 sig->ret = &klass->byval_arg;
3045 mono_mb_emit_ldarg (mb, 0);
3046 pos0 = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
3048 mono_mb_emit_ldarg (mb, 0);
3049 mono_mb_emit_ldarg (mb, 1);
3050 mono_mb_emit_ldarg (mb, 2);
3052 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
3053 csig->params [0] = &mono_defaults.object_class->byval_arg;
3054 csig->params [1] = &mono_defaults.int_class->byval_arg;
3055 csig->params [2] = &mono_defaults.int_class->byval_arg;
3056 csig->ret = &klass->this_arg;
3059 mono_mb_emit_native_call (mb, csig, mono_load_remote_field_new);
3060 emit_thread_interrupt_checkpoint (mb);
3062 if (klass->valuetype) {
3063 mono_mb_emit_byte (mb, CEE_UNBOX);
3064 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3065 mono_mb_emit_byte (mb, CEE_BR);
3067 mono_mb_emit_i4 (mb, 0);
3069 mono_mb_emit_byte (mb, CEE_RET);
3073 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
3075 mono_mb_emit_ldarg (mb, 0);
3076 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3077 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
3078 mono_mb_emit_ldarg (mb, 3);
3079 mono_mb_emit_byte (mb, CEE_ADD);
3081 if (klass->valuetype)
3082 mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
3087 case MONO_TYPE_BOOLEAN:
3088 mono_mb_emit_byte (mb, CEE_LDIND_I1);
3090 case MONO_TYPE_CHAR:
3093 mono_mb_emit_byte (mb, CEE_LDIND_I2);
3097 mono_mb_emit_byte (mb, CEE_LDIND_I4);
3101 mono_mb_emit_byte (mb, CEE_LDIND_I8);
3104 mono_mb_emit_byte (mb, CEE_LDIND_R4);
3107 mono_mb_emit_byte (mb, CEE_LDIND_R8);
3109 case MONO_TYPE_ARRAY:
3111 case MONO_TYPE_FNPTR:
3112 case MONO_TYPE_SZARRAY:
3113 case MONO_TYPE_OBJECT:
3114 case MONO_TYPE_CLASS:
3115 case MONO_TYPE_STRING:
3118 mono_mb_emit_byte (mb, CEE_LDIND_I);
3120 case MONO_TYPE_VALUETYPE:
3121 g_assert (!klass->enumtype);
3122 mono_mb_emit_byte (mb, CEE_LDOBJ);
3123 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3126 g_warning ("type %x not implemented", type->type);
3127 g_assert_not_reached ();
3130 mono_mb_emit_byte (mb, CEE_RET);
3132 res = mono_mb_create_and_cache (ldfld_hash, klass,
3133 mb, sig, sig->param_count + 16);
3140 * mono_marshal_get_stfld_wrapper:
3141 * @type: the type of the field
3143 * This method generates a function which can be use to store a field with type
3144 * @type. The generated function has the following signature:
3145 * void stfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset, <@type> val)
3148 mono_marshal_get_stfld_wrapper (MonoType *type)
3150 MonoMethodSignature *sig, *csig;
3151 MonoMethodBuilder *mb;
3154 static GHashTable *stfld_hash = NULL;
3161 if (type->type == MONO_TYPE_SZARRAY) {
3162 klass = mono_defaults.array_class;
3163 } else if (type->type == MONO_TYPE_VALUETYPE) {
3164 klass = type->data.klass;
3165 if (klass->enumtype) {
3166 t = klass->enum_basetype->type;
3167 klass = mono_class_from_mono_type (klass->enum_basetype);
3169 } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
3170 t == MONO_TYPE_CLASS) {
3171 klass = mono_defaults.object_class;
3172 } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
3173 klass = mono_defaults.int_class;
3175 klass = mono_class_from_mono_type (type);
3178 klass = mono_defaults.int_class;
3181 EnterCriticalSection (&marshal_mutex);
3183 stfld_hash = g_hash_table_new (NULL, NULL);
3184 res = g_hash_table_lookup (stfld_hash, klass);
3185 LeaveCriticalSection (&marshal_mutex);
3189 name = g_strdup_printf ("__stfld_wrapper_%s.%s", klass->name_space, klass->name);
3190 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_STFLD);
3193 mb->method->save_lmf = 1;
3195 sig = mono_metadata_signature_alloc (mono_defaults.corlib, 5);
3196 sig->params [0] = &mono_defaults.object_class->byval_arg;
3197 sig->params [1] = &mono_defaults.int_class->byval_arg;
3198 sig->params [2] = &mono_defaults.int_class->byval_arg;
3199 sig->params [3] = &mono_defaults.int_class->byval_arg;
3200 sig->params [4] = &klass->byval_arg;
3201 sig->ret = &mono_defaults.void_class->byval_arg;
3203 mono_mb_emit_ldarg (mb, 0);
3204 pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
3206 mono_mb_emit_ldarg (mb, 0);
3207 mono_mb_emit_ldarg (mb, 1);
3208 mono_mb_emit_ldarg (mb, 2);
3209 mono_mb_emit_ldarg (mb, 4);
3211 if (klass->valuetype) {
3212 mono_mb_emit_byte (mb, CEE_BOX);
3213 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3216 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
3217 csig->params [0] = &mono_defaults.object_class->byval_arg;
3218 csig->params [1] = &mono_defaults.int_class->byval_arg;
3219 csig->params [2] = &mono_defaults.int_class->byval_arg;
3220 csig->params [3] = &klass->this_arg;
3221 csig->ret = &mono_defaults.void_class->byval_arg;
3224 mono_mb_emit_native_call (mb, csig, mono_store_remote_field_new);
3225 emit_thread_interrupt_checkpoint (mb);
3227 mono_mb_emit_byte (mb, CEE_RET);
3229 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3231 mono_mb_emit_ldarg (mb, 0);
3232 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3233 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
3234 mono_mb_emit_ldarg (mb, 3);
3235 mono_mb_emit_byte (mb, CEE_ADD);
3236 mono_mb_emit_ldarg (mb, 4);
3241 case MONO_TYPE_BOOLEAN:
3242 mono_mb_emit_byte (mb, CEE_STIND_I1);
3244 case MONO_TYPE_CHAR:
3247 mono_mb_emit_byte (mb, CEE_STIND_I2);
3251 mono_mb_emit_byte (mb, CEE_STIND_I4);
3255 mono_mb_emit_byte (mb, CEE_STIND_I8);
3258 mono_mb_emit_byte (mb, CEE_STIND_R4);
3261 mono_mb_emit_byte (mb, CEE_STIND_R8);
3263 case MONO_TYPE_ARRAY:
3265 case MONO_TYPE_FNPTR:
3266 case MONO_TYPE_SZARRAY:
3267 case MONO_TYPE_OBJECT:
3268 case MONO_TYPE_CLASS:
3269 case MONO_TYPE_STRING:
3272 mono_mb_emit_byte (mb, CEE_STIND_I);
3274 case MONO_TYPE_VALUETYPE:
3275 g_assert (!klass->enumtype);
3276 mono_mb_emit_byte (mb, CEE_STOBJ);
3277 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3280 g_warning ("type %x not implemented", type->type);
3281 g_assert_not_reached ();
3284 mono_mb_emit_byte (mb, CEE_RET);
3286 res = mono_mb_create_and_cache (stfld_hash, klass,
3287 mb, sig, sig->param_count + 16);
3294 * generates IL code for the icall wrapper (the generated method
3295 * calls the unmanaged code in func)
3298 mono_marshal_get_icall_wrapper (MonoMethodSignature *sig, const char *name, gconstpointer func)
3300 MonoMethodSignature *csig;
3301 MonoMethodBuilder *mb;
3305 g_assert (sig->pinvoke);
3307 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_MANAGED_TO_NATIVE);
3309 mb->method->save_lmf = 1;
3311 /* we copy the signature, so that we can modify it */
3314 mono_mb_emit_byte (mb, CEE_LDARG_0);
3316 for (i = 0; i < sig->param_count; i++)
3317 mono_mb_emit_ldarg (mb, i + sig->hasthis);
3319 mono_mb_emit_native_call (mb, sig, (gpointer) func);
3320 emit_thread_interrupt_checkpoint (mb);
3321 mono_mb_emit_byte (mb, CEE_RET);
3323 csig = mono_metadata_signature_dup (sig);
3325 if (csig->call_convention == MONO_CALL_VARARG)
3326 csig->call_convention = 0;
3328 res = mono_mb_create_method (mb, csig, csig->param_count + 16);
3335 * mono_marshal_get_native_wrapper:
3336 * @method: The MonoMethod to wrap.
3338 * generates IL code for the pinvoke wrapper (the generated method
3339 * calls the unmanaged code in method->addr)
3342 mono_marshal_get_native_wrapper (MonoMethod *method)
3344 MonoMethodSignature *sig, *csig;
3345 MonoMethodPInvoke *piinfo;
3346 MonoMethodBuilder *mb;
3347 MonoMarshalSpec **mspecs;
3351 gboolean pinvoke = FALSE;
3352 int i, pos, argnum, *tmp_locals;
3354 const char *exc_class = "MissingMethodException";
3355 const char *exc_arg = NULL;
3357 g_assert (method != NULL);
3358 g_assert (method->signature->pinvoke);
3360 cache = method->klass->image->native_wrapper_cache;
3361 if ((res = mono_marshal_find_in_cache (cache, method)))
3364 sig = method->signature;
3366 if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
3367 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
3370 if (!method->addr) {
3372 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
3374 method->addr = mono_lookup_internal_call (method);
3377 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_MANAGED_TO_NATIVE);
3379 mb->method->save_lmf = 1;
3381 piinfo = (MonoMethodPInvoke *)method;
3383 if (!method->addr) {
3384 mono_mb_emit_exception (mb, exc_class, exc_arg);
3385 csig = mono_metadata_signature_dup (sig);
3387 res = mono_mb_create_and_cache (cache, method,
3388 mb, csig, csig->param_count + 16);
3393 /* internal calls: we simply push all arguments and call the method (no conversions) */
3394 if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
3396 /* hack - string constructors returns a value */
3397 if (method->string_ctor) {
3398 csig = mono_metadata_signature_dup (sig);
3399 csig->ret = &mono_defaults.string_class->byval_arg;
3404 mono_mb_emit_byte (mb, CEE_LDARG_0);
3406 for (i = 0; i < sig->param_count; i++)
3407 mono_mb_emit_ldarg (mb, i + sig->hasthis);
3409 g_assert (method->addr);
3410 mono_mb_emit_native_call (mb, csig, method->addr);
3411 emit_thread_interrupt_checkpoint (mb);
3412 mono_mb_emit_byte (mb, CEE_RET);
3414 csig = mono_metadata_signature_dup (csig);
3416 res = mono_mb_create_and_cache (cache, method,
3417 mb, csig, csig->param_count + 16);
3424 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
3425 mono_method_get_marshal_info (method, mspecs);
3427 /* pinvoke: we need to convert the arguments if necessary */
3429 /* we copy the signature, so that we can set pinvoke to 0 */
3430 csig = mono_metadata_signature_dup (sig);
3433 /* we allocate local for use with emit_struct_conv() */
3434 /* allocate local 0 (pointer) src_ptr */
3435 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3436 /* allocate local 1 (pointer) dst_ptr */
3437 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3438 /* allocate local 2 (boolean) delete_old */
3439 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
3441 /* delete_old = FALSE */
3442 mono_mb_emit_icon (mb, 0);
3443 mono_mb_emit_byte (mb, CEE_STLOC_2);
3445 if (!MONO_TYPE_IS_VOID(sig->ret)) {
3446 /* allocate local 3 to store the return value */
3447 mono_mb_add_local (mb, sig->ret);
3450 if (mspecs [0] && mspecs [0]->native == MONO_NATIVE_CUSTOM) {
3451 /* Return type custom marshaling */
3453 * Since we can't determine the return type of the unmanaged function,
3454 * we assume it returns a pointer, and pass that pointer to
3455 * MarshalNativeToManaged.
3457 csig->ret = &mono_defaults.int_class->byval_arg;
3460 /* we first do all conversions */
3461 tmp_locals = alloca (sizeof (int) * sig->param_count);
3463 for (i = 0; i < sig->param_count; i ++) {
3464 MonoType *t = sig->params [i];
3465 MonoMarshalSpec *spec = mspecs [i + 1];
3467 argnum = i + sig->hasthis;
3470 /* Ensure that we have marshalling info for this param */
3471 mono_marshal_load_type_info (mono_class_from_mono_type (t));
3473 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
3476 MonoMethod *marshal_managed_to_native;
3477 MonoMethod *get_instance;
3479 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
3480 g_assert (mtype != NULL);
3481 mklass = mono_class_from_mono_type (mtype);
3482 g_assert (mklass != NULL);
3484 marshal_managed_to_native = mono_find_method_by_name (mklass, "MarshalManagedToNative", 1);
3485 g_assert (marshal_managed_to_native);
3486 get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
3487 g_assert (get_instance);
3490 case MONO_TYPE_CLASS:
3491 case MONO_TYPE_OBJECT:
3492 case MONO_TYPE_STRING:
3493 case MONO_TYPE_ARRAY:
3494 case MONO_TYPE_SZARRAY:
3495 case MONO_TYPE_VALUETYPE:
3499 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3501 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
3503 mono_mb_emit_byte (mb, CEE_CALL);
3504 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
3506 mono_mb_emit_ldarg (mb, argnum);
3508 if (t->type == MONO_TYPE_VALUETYPE) {
3510 * Since we can't determine the type of the argument, we
3511 * will assume the unmanaged function takes a pointer.
3513 csig->params [i] = &mono_defaults.int_class->byval_arg;
3515 mono_mb_emit_byte (mb, CEE_BOX);
3516 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (t)));
3519 mono_mb_emit_byte (mb, CEE_CALLVIRT);
3520 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_managed_to_native));
3522 mono_mb_emit_stloc (mb, tmp_locals [i]);
3526 g_warning ("custom marshalling of type %x is currently not supported", t->type);
3527 g_assert_not_reached ();
3533 if (spec && spec->native == MONO_NATIVE_ASANY) {
3534 MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, NULL);
3536 g_assert (t->type == MONO_TYPE_OBJECT);
3537 g_assert (!t->byref);
3539 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3540 mono_mb_emit_ldarg (mb, argnum);
3541 mono_mb_emit_icon (mb, encoding);
3542 mono_mb_emit_icall (mb, mono_marshal_asany);
3543 mono_mb_emit_stloc (mb, tmp_locals [i]);
3548 case MONO_TYPE_VALUETYPE:
3549 klass = t->data.klass;
3551 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3552 klass->blittable || klass->enumtype)
3555 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3557 /* store the address of the source into local variable 0 */
3559 mono_mb_emit_ldarg (mb, argnum);
3561 mono_mb_emit_ldarg_addr (mb, argnum);
3563 mono_mb_emit_byte (mb, CEE_STLOC_0);
3565 /* allocate space for the native struct and
3566 * store the address into local variable 1 (dest) */
3567 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
3568 mono_mb_emit_byte (mb, CEE_PREFIX1);
3569 mono_mb_emit_byte (mb, CEE_LOCALLOC);
3570 mono_mb_emit_stloc (mb, tmp_locals [i]);
3573 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3574 mono_mb_emit_byte (mb, CEE_BRFALSE);
3576 mono_mb_emit_i4 (mb, 0);
3580 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3581 mono_mb_emit_byte (mb, CEE_STLOC_1);
3583 /* emit valuetype conversion code */
3584 emit_struct_conv (mb, klass, FALSE);
3587 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3589 case MONO_TYPE_STRING: {
3590 MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, spec);
3592 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3593 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3596 if (t->attrs & PARAM_ATTRIBUTE_OUT)
3599 mono_mb_emit_ldarg (mb, argnum);
3600 mono_mb_emit_byte (mb, CEE_LDIND_I);
3602 mono_mb_emit_ldarg (mb, argnum);
3606 case MONO_NATIVE_LPWSTR:
3607 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_STR_LPWSTR));
3609 case MONO_NATIVE_LPSTR:
3610 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_STR_LPSTR));
3612 case MONO_NATIVE_LPTSTR:
3613 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_STR_LPTSTR));
3616 char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding);
3617 MonoException *exc = mono_get_exception_not_implemented (msg);
3620 mono_raise_exception (exc);
3624 mono_mb_emit_stloc (mb, tmp_locals [i]);
3627 case MONO_TYPE_CLASS:
3628 case MONO_TYPE_OBJECT:
3629 klass = t->data.klass;
3631 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3632 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3634 if (klass->delegate) {
3635 g_assert (!t->byref);
3636 mono_mb_emit_ldarg (mb, argnum);
3637 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN));
3638 mono_mb_emit_stloc (mb, tmp_locals [i]);
3639 } else if (klass == mono_defaults.stringbuilder_class) {
3640 MonoMarshalNative encoding = mono_marshal_get_stringbuilder_to_ptr_encoding (piinfo, spec);
3642 g_assert (!t->byref);
3643 mono_mb_emit_ldarg (mb, argnum);
3646 mono_mb_emit_icall (mb, conv_to_icall (encoding));
3648 char *msg = g_strdup_printf ("stringbuilder marshalling conversion %d not implemented", encoding);
3649 MonoException *exc = mono_get_exception_not_implemented (msg);
3652 mono_raise_exception (exc);
3655 mono_mb_emit_stloc (mb, tmp_locals [i]);
3656 } else if (klass->blittable) {
3657 mono_mb_emit_ldarg (mb, argnum);
3658 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3659 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
3660 mono_mb_emit_icon (mb, sizeof (MonoObject));
3661 mono_mb_emit_byte (mb, CEE_ADD);
3662 mono_mb_emit_stloc (mb, tmp_locals [i]);
3665 mono_mb_emit_byte (mb, CEE_LDNULL);
3666 mono_mb_emit_stloc (mb, tmp_locals [i]);
3669 /* we dont need any conversions for out parameters */
3670 if (t->attrs & PARAM_ATTRIBUTE_OUT)
3673 mono_mb_emit_ldarg (mb, argnum);
3674 mono_mb_emit_byte (mb, CEE_LDIND_I);
3677 mono_mb_emit_ldarg (mb, argnum);
3678 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3679 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
3682 /* store the address of the source into local variable 0 */
3683 mono_mb_emit_byte (mb, CEE_STLOC_0);
3684 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3685 mono_mb_emit_byte (mb, CEE_BRFALSE);
3687 mono_mb_emit_i4 (mb, 0);
3689 /* allocate space for the native struct and store the address */
3690 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
3691 mono_mb_emit_byte (mb, CEE_PREFIX1);
3692 mono_mb_emit_byte (mb, CEE_LOCALLOC);
3693 mono_mb_emit_stloc (mb, tmp_locals [i]);
3695 /* set the src_ptr */
3696 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3697 mono_mb_emit_icon (mb, sizeof (MonoObject));
3698 mono_mb_emit_byte (mb, CEE_ADD);
3699 mono_mb_emit_byte (mb, CEE_STLOC_0);
3702 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3703 mono_mb_emit_byte (mb, CEE_STLOC_1);
3705 /* emit valuetype conversion code */
3706 emit_struct_conv (mb, klass, FALSE);
3708 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3712 case MONO_TYPE_ARRAY:
3713 case MONO_TYPE_SZARRAY:
3714 klass = mono_class_from_mono_type (t);
3716 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3717 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3719 if (klass->element_class == mono_defaults.string_class) {
3720 MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, spec);
3722 mono_mb_emit_ldarg (mb, argnum);
3724 mono_mb_emit_byte (mb, CEE_LDIND_I);
3727 case MONO_NATIVE_LPSTR:
3728 mono_mb_emit_icall (mb, mono_marshal_string_array);
3730 case MONO_NATIVE_LPWSTR:
3731 mono_mb_emit_icall (mb, mono_marshal_string_array_to_unicode);
3734 char *msg = g_strdup_printf ("string array marshalling conversion %d not implemented", encoding);
3735 MonoException *exc = mono_get_exception_not_implemented (msg);
3738 mono_raise_exception (exc);
3741 mono_mb_emit_stloc (mb, tmp_locals [i]);
3743 else if (klass->element_class->blittable) {
3744 mono_mb_emit_ldarg (mb, argnum);
3746 mono_mb_emit_byte (mb, CEE_LDIND_I);
3747 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_ARRAY_LPARRAY));
3748 mono_mb_emit_stloc (mb, tmp_locals [i]);
3752 guint32 label1, label2, label3;
3753 int index_var, src_var, dest_ptr, esize;
3754 MonoMarshalNative encoding = mono_marshal_get_stringbuilder_to_ptr_encoding (piinfo, spec);
3756 dest_ptr = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3758 eklass = klass->element_class;
3760 src_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3761 mono_mb_emit_ldarg (mb, argnum);
3763 mono_mb_emit_byte (mb, CEE_LDIND_I);
3764 mono_mb_emit_stloc (mb, src_var);
3767 mono_mb_emit_ldloc (mb, src_var);
3768 mono_mb_emit_stloc (mb, tmp_locals [i]);
3769 mono_mb_emit_ldloc (mb, src_var);
3770 mono_mb_emit_byte (mb, CEE_BRFALSE);
3772 mono_mb_emit_i4 (mb, 0);
3774 if (eklass == mono_defaults.stringbuilder_class) {
3775 if (encoding == -1) {
3776 char *msg = g_strdup_printf ("stringbuilder marshalling conversion %d not implemented", encoding);
3777 MonoException *exc = mono_get_exception_not_implemented (msg);
3780 mono_raise_exception (exc);
3784 if (eklass == mono_defaults.stringbuilder_class)
3785 esize = sizeof (gpointer);
3787 esize = mono_class_native_size (eklass, NULL);
3789 /* allocate space for the native struct and store the address */
3790 mono_mb_emit_icon (mb, esize);
3791 mono_mb_emit_ldloc (mb, src_var);
3792 mono_mb_emit_byte (mb, CEE_LDLEN);
3793 mono_mb_emit_byte (mb, CEE_MUL);
3794 mono_mb_emit_byte (mb, CEE_PREFIX1);
3795 mono_mb_emit_byte (mb, CEE_LOCALLOC);
3796 mono_mb_emit_stloc (mb, tmp_locals [i]);
3798 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3799 mono_mb_emit_stloc (mb, dest_ptr);
3801 /* Emit marshalling loop */
3802 index_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3803 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
3804 mono_mb_emit_stloc (mb, index_var);
3806 mono_mb_emit_ldloc (mb, index_var);
3807 mono_mb_emit_ldloc (mb, src_var);
3808 mono_mb_emit_byte (mb, CEE_LDLEN);
3809 mono_mb_emit_byte (mb, CEE_BGE);
3811 mono_mb_emit_i4 (mb, 0);
3813 /* Emit marshalling code */
3815 if (eklass == mono_defaults.stringbuilder_class) {
3816 mono_mb_emit_ldloc (mb, dest_ptr);
3817 mono_mb_emit_ldloc (mb, src_var);
3818 mono_mb_emit_ldloc (mb, index_var);
3819 mono_mb_emit_byte (mb, CEE_LDELEM_REF);
3820 mono_mb_emit_icall (mb, conv_to_icall (encoding));
3821 mono_mb_emit_byte (mb, CEE_STIND_I);
3824 /* set the src_ptr */
3825 mono_mb_emit_ldloc (mb, src_var);
3826 mono_mb_emit_ldloc (mb, index_var);
3827 mono_mb_emit_byte (mb, CEE_LDELEMA);
3828 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eklass));
3829 mono_mb_emit_byte (mb, CEE_STLOC_0);
3832 mono_mb_emit_ldloc (mb, dest_ptr);
3833 mono_mb_emit_byte (mb, CEE_STLOC_1);
3835 /* emit valuetype conversion code */
3836 emit_struct_conv (mb, eklass, FALSE);
3839 mono_mb_emit_add_to_local (mb, index_var, 1);
3840 mono_mb_emit_add_to_local (mb, dest_ptr, esize);
3842 mono_mb_emit_byte (mb, CEE_BR);
3843 mono_mb_emit_i4 (mb, label2 - (mb->pos + 4));
3845 mono_mb_patch_addr (mb, label1, mb->pos - (label1 + 4));
3846 mono_mb_patch_addr (mb, label3, mb->pos - (label3 + 4));
3850 case MONO_TYPE_BOOLEAN: {
3851 MonoType *local_type;
3852 int variant_bool = 0;
3856 local_type = &mono_defaults.int32_class->byval_arg;
3858 switch (spec->native) {
3859 case MONO_NATIVE_I1:
3860 local_type = &mono_defaults.byte_class->byval_arg;
3862 case MONO_NATIVE_VARIANTBOOL:
3863 local_type = &mono_defaults.int16_class->byval_arg;
3867 g_warning ("marshalling bool as native type %x is currently not supported", spec->native);
3871 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3872 tmp_locals [i] = mono_mb_add_local (mb, local_type);
3873 mono_mb_emit_ldarg (mb, argnum);
3874 mono_mb_emit_byte (mb, CEE_LDIND_I1);
3876 mono_mb_emit_byte (mb, CEE_NEG);
3877 mono_mb_emit_stloc (mb, tmp_locals [i]);
3883 /* push all arguments */
3886 mono_mb_emit_byte (mb, CEE_LDARG_0);
3888 for (i = 0; i < sig->param_count; i++) {
3889 MonoType *t = sig->params [i];
3890 MonoMarshalSpec *spec = mspecs [i + 1];
3892 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
3893 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3896 if (spec && spec->native == MONO_NATIVE_ASANY) {
3897 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3900 argnum = i + sig->hasthis;
3903 case MONO_TYPE_BOOLEAN:
3905 g_assert (tmp_locals [i]);
3906 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
3908 mono_mb_emit_ldarg (mb, argnum);
3923 mono_mb_emit_ldarg (mb, argnum);
3925 case MONO_TYPE_VALUETYPE:
3926 klass = sig->params [i]->data.klass;
3927 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3928 klass->blittable || klass->enumtype) {
3929 mono_mb_emit_ldarg (mb, argnum);
3932 g_assert (tmp_locals [i]);
3933 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3935 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3936 mono_mb_emit_byte (mb, CEE_MONO_LDNATIVEOBJ);
3937 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3940 case MONO_TYPE_STRING:
3941 case MONO_TYPE_CLASS:
3942 case MONO_TYPE_OBJECT:
3943 case MONO_TYPE_ARRAY:
3944 case MONO_TYPE_SZARRAY:
3945 g_assert (tmp_locals [i]);
3947 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
3949 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3951 case MONO_TYPE_CHAR:
3952 /* fixme: dont know how to marshal that. We cant simply
3953 * convert it to a one byte UTF8 character, because an
3954 * unicode character may need more that one byte in UTF8 */
3955 mono_mb_emit_ldarg (mb, argnum);
3957 case MONO_TYPE_TYPEDBYREF:
3958 case MONO_TYPE_FNPTR:
3960 g_warning ("type 0x%02x unknown", t->type);
3961 g_assert_not_reached ();
3966 /* call the native method */
3967 mono_mb_emit_native_call (mb, csig, method->addr);
3969 /* Set LastError if needed */
3970 if (piinfo->piflags & PINVOKE_ATTRIBUTE_SUPPORTS_LAST_ERROR) {
3971 MonoMethodSignature *lasterr_sig;
3973 lasterr_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
3974 lasterr_sig->ret = &mono_defaults.void_class->byval_arg;
3975 lasterr_sig->pinvoke = 1;
3977 mono_mb_emit_native_call (mb, lasterr_sig, mono_marshal_set_last_error);
3980 /* Ensure that we have marshalling info for the return */
3981 mono_marshal_load_type_info (mono_class_from_mono_type (sig->ret));
3983 /* convert the result */
3984 if (!sig->ret->byref) {
3985 MonoMarshalSpec *spec = mspecs [0];
3986 type = sig->ret->type;
3988 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
3991 MonoMethod *marshal_native_to_managed;
3992 MonoMethod *get_instance;
3993 MonoMethod *cleanup_native;
3996 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
3997 g_assert (mtype != NULL);
3998 mklass = mono_class_from_mono_type (mtype);
3999 g_assert (mklass != NULL);
4001 marshal_native_to_managed = mono_find_method_by_name (mklass, "MarshalNativeToManaged", 1);
4002 g_assert (marshal_native_to_managed);
4003 cleanup_native = mono_find_method_by_name (mklass, "CleanUpNativeData", 1);
4004 g_assert (cleanup_native);
4005 get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
4006 g_assert (get_instance);
4008 loc1 = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
4011 case MONO_TYPE_CLASS:
4012 case MONO_TYPE_OBJECT:
4013 case MONO_TYPE_STRING:
4014 case MONO_TYPE_ARRAY:
4015 case MONO_TYPE_SZARRAY:
4016 mono_mb_emit_byte (mb, CEE_STLOC_3);
4018 mono_mb_emit_byte (mb, CEE_LDLOC_3);
4019 mono_mb_emit_stloc (mb, loc1);
4021 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
4023 mono_mb_emit_byte (mb, CEE_CALL);
4024 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
4025 mono_mb_emit_byte (mb, CEE_DUP);
4027 mono_mb_emit_byte (mb, CEE_LDLOC_3);
4028 mono_mb_emit_byte (mb, CEE_CALLVIRT);
4029 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_native_to_managed));
4030 mono_mb_emit_byte (mb, CEE_STLOC_3);
4032 mono_mb_emit_ldloc (mb, loc1);
4033 mono_mb_emit_byte (mb, CEE_CALLVIRT);
4034 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, cleanup_native));
4038 g_warning ("custom marshalling of type %x is currently not supported", type);
4039 g_assert_not_reached ();
4046 case MONO_TYPE_VOID:
4061 /* no conversions necessary */
4062 mono_mb_emit_byte (mb, CEE_STLOC_3);
4064 case MONO_TYPE_BOOLEAN:
4065 /* maybe we need to make sure that it fits within 8 bits */
4066 mono_mb_emit_byte (mb, CEE_STLOC_3);
4068 case MONO_TYPE_VALUETYPE:
4069 klass = sig->ret->data.klass;
4070 if (klass->enumtype) {
4071 type = sig->ret->data.klass->enum_basetype->type;
4075 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
4077 mono_mb_emit_byte (mb, CEE_STLOC_3);
4080 /* load pointer to returned value type */
4081 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4082 mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
4083 /* store the address of the source into local variable 0 */
4084 mono_mb_emit_byte (mb, CEE_STLOC_0);
4086 mono_mb_emit_ldloc_addr (mb, 3);
4087 mono_mb_emit_byte (mb, CEE_STLOC_1);
4089 /* emit valuetype conversion code */
4090 emit_struct_conv (mb, sig->ret->data.klass, TRUE);
4092 case MONO_TYPE_STRING:
4093 mono_mb_emit_byte (mb, CEE_STLOC_0);
4094 mono_mb_emit_byte (mb, CEE_LDLOC_0);
4097 switch (spec->native) {
4098 case MONO_NATIVE_LPWSTR:
4099 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_LPWSTR_STR));
4102 g_warning ("marshalling conversion not implemented");
4103 g_assert_not_reached ();
4106 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_LPSTR_STR));
4108 mono_mb_emit_byte (mb, CEE_STLOC_3);
4110 /* free the string */
4111 mono_mb_emit_byte (mb, CEE_LDLOC_0);
4112 mono_mb_emit_icall (mb, g_free);
4114 case MONO_TYPE_CLASS:
4115 case MONO_TYPE_OBJECT:
4116 klass = sig->ret->data.klass;
4119 mono_mb_emit_byte (mb, CEE_STLOC_0);
4121 mono_mb_emit_byte (mb, CEE_LDNULL);
4122 mono_mb_emit_byte (mb, CEE_STLOC_3);
4125 mono_mb_emit_byte (mb, CEE_LDLOC_0);
4126 mono_mb_emit_byte (mb, CEE_BRFALSE);
4128 mono_mb_emit_i4 (mb, 0);
4130 /* allocate result object */
4132 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4133 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
4134 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
4135 mono_mb_emit_byte (mb, CEE_STLOC_3);
4139 mono_mb_emit_byte (mb, CEE_LDLOC_3);
4140 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4141 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
4142 mono_mb_emit_icon (mb, sizeof (MonoObject));
4143 mono_mb_emit_byte (mb, CEE_ADD);
4144 mono_mb_emit_byte (mb, CEE_STLOC_1);
4146 /* emit conversion code */
4147 emit_struct_conv (mb, klass, TRUE);
4149 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
4151 case MONO_TYPE_ARRAY:
4152 case MONO_TYPE_SZARRAY:
4153 /* fixme: we need conversions here */
4154 mono_mb_emit_byte (mb, CEE_STLOC_3);
4156 case MONO_TYPE_CHAR:
4157 /* fixme: we need conversions here */
4158 mono_mb_emit_byte (mb, CEE_STLOC_3);
4160 case MONO_TYPE_TYPEDBYREF:
4161 case MONO_TYPE_FNPTR:
4163 g_warning ("return type 0x%02x unknown", sig->ret->type);
4164 g_assert_not_reached ();
4168 mono_mb_emit_byte (mb, CEE_STLOC_3);
4172 * Need to call this after converting the result since MONO_VTADDR needs
4173 * to be adjacent to the call instruction.
4175 emit_thread_interrupt_checkpoint (mb);
4177 /* we need to convert byref arguments back and free string arrays */
4178 for (i = 0; i < sig->param_count; i++) {
4179 MonoType *t = sig->params [i];
4180 MonoMarshalSpec *spec = mspecs [i + 1];
4182 argnum = i + sig->hasthis;
4184 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
4187 MonoMethod *get_instance;
4188 MonoMethod *cleanup_native;
4190 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
4191 g_assert (mtype != NULL);
4192 mklass = mono_class_from_mono_type (mtype);
4193 g_assert (mklass != NULL);
4195 get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
4196 g_assert (get_instance);
4197 cleanup_native = mono_find_method_by_name (mklass, "CleanUpNativeData", 1);
4198 g_assert (get_instance);
4201 case MONO_TYPE_CLASS:
4202 case MONO_TYPE_OBJECT:
4203 case MONO_TYPE_STRING:
4204 case MONO_TYPE_ARRAY:
4205 case MONO_TYPE_SZARRAY:
4206 case MONO_TYPE_VALUETYPE:
4207 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
4209 mono_mb_emit_byte (mb, CEE_CALL);
4210 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
4212 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4214 mono_mb_emit_byte (mb, CEE_CALLVIRT);
4215 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, cleanup_native));
4220 g_warning ("custom marshalling of type %x is currently not supported", t->type);
4221 g_assert_not_reached ();
4227 if (spec && spec->native == MONO_NATIVE_ASANY) {
4228 MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, NULL);
4230 mono_mb_emit_ldarg (mb, argnum);
4231 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4232 mono_mb_emit_icon (mb, encoding);
4233 mono_mb_emit_icall (mb, mono_marshal_free_asany);
4238 case MONO_TYPE_STRING:
4239 if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT)) {
4240 mono_mb_emit_ldarg (mb, argnum);
4241 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4242 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_LPSTR_STR));
4243 mono_mb_emit_byte (mb, CEE_STIND_I);
4245 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4246 mono_mb_emit_icall (mb, g_free);
4249 case MONO_TYPE_CLASS:
4250 case MONO_TYPE_OBJECT:
4251 if (t->data.klass == mono_defaults.stringbuilder_class) {
4253 MonoMarshalNative encoding;
4255 encoding = mono_marshal_get_ptr_to_stringbuilder_encoding (piinfo, spec, &need_free);
4257 g_assert (!t->byref);
4258 g_assert (encoding != -1);
4260 mono_mb_emit_ldarg (mb, argnum);
4261 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4263 mono_mb_emit_icall (mb, conv_to_icall (encoding));
4266 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4267 mono_mb_emit_icall (mb, g_free);
4272 if (!(t->byref || (t->attrs & PARAM_ATTRIBUTE_OUT)))
4275 if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT)) {
4276 /* allocate a new object new object */
4277 mono_mb_emit_ldarg (mb, argnum);
4278 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4279 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
4280 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
4281 mono_mb_emit_byte (mb, CEE_STIND_I);
4284 /* dst = *argument */
4285 mono_mb_emit_ldarg (mb, argnum);
4288 mono_mb_emit_byte (mb, CEE_LDIND_I);
4290 mono_mb_emit_byte (mb, CEE_STLOC_1);
4292 mono_mb_emit_byte (mb, CEE_LDLOC_1);
4293 mono_mb_emit_byte (mb, CEE_BRFALSE);
4295 mono_mb_emit_i4 (mb, 0);
4297 mono_mb_emit_byte (mb, CEE_LDLOC_1);
4298 mono_mb_emit_icon (mb, sizeof (MonoObject));
4299 mono_mb_emit_byte (mb, CEE_ADD);
4300 mono_mb_emit_byte (mb, CEE_STLOC_1);
4302 /* src = tmp_locals [i] */
4303 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4304 mono_mb_emit_byte (mb, CEE_STLOC_0);
4306 /* emit valuetype conversion code */
4307 emit_struct_conv (mb, klass, TRUE);
4309 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
4311 case MONO_TYPE_VALUETYPE:
4315 klass = t->data.klass;
4316 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
4317 klass->blittable || klass->enumtype)
4320 /* dst = argument */
4321 mono_mb_emit_ldarg (mb, argnum);
4322 mono_mb_emit_byte (mb, CEE_STLOC_1);
4324 mono_mb_emit_byte (mb, CEE_LDLOC_1);
4325 mono_mb_emit_byte (mb, CEE_BRFALSE);
4327 mono_mb_emit_i4 (mb, 0);
4329 /* src = tmp_locals [i] */
4330 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4331 mono_mb_emit_byte (mb, CEE_STLOC_0);
4333 /* emit valuetype conversion code */
4334 emit_struct_conv (mb, klass, TRUE);
4336 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
4338 case MONO_TYPE_SZARRAY:
4339 klass = mono_class_from_mono_type (t);
4341 if (klass->element_class == mono_defaults.string_class) {
4342 MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, spec);
4343 g_assert (tmp_locals [i]);
4345 mono_mb_emit_ldarg (mb, argnum);
4347 mono_mb_emit_byte (mb, CEE_LDIND_I);
4348 mono_mb_emit_byte (mb, CEE_BRFALSE);
4350 mono_mb_emit_i4 (mb, 0);
4352 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4355 case MONO_NATIVE_LPWSTR:
4357 * The array elements point to the managed string data so
4358 * they don't need to be freed.
4360 mono_mb_emit_icall (mb, g_free);
4363 mono_mb_emit_ldarg (mb, argnum);
4365 mono_mb_emit_byte (mb, CEE_LDIND_I);
4366 mono_mb_emit_byte (mb, CEE_LDLEN);
4367 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_FREE_ARRAY));
4371 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
4376 * FIXME: Need to convert data back but we don't know the
4377 * size of the array.
4381 /* Character arrays are implicitly marshalled as [Out] */
4382 if ((klass->element_class == mono_defaults.char_class) || (klass->element_class == mono_defaults.stringbuilder_class) || (t->attrs & PARAM_ATTRIBUTE_OUT)) {
4383 /* FIXME: Optimize blittable case */
4385 guint32 label1, label2, label3;
4386 int index_var, src_ptr, esize;
4388 eklass = klass->element_class;
4389 if (eklass == mono_defaults.stringbuilder_class)
4390 esize = sizeof (gpointer);
4392 esize = mono_class_native_size (eklass, NULL);
4393 src_ptr = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
4396 mono_mb_emit_ldarg (mb, argnum);
4397 mono_mb_emit_byte (mb, CEE_BRFALSE);
4399 mono_mb_emit_i4 (mb, 0);
4401 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4402 mono_mb_emit_stloc (mb, src_ptr);
4404 /* Emit marshalling loop */
4405 index_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
4406 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
4407 mono_mb_emit_stloc (mb, index_var);
4409 mono_mb_emit_ldloc (mb, index_var);
4410 mono_mb_emit_ldarg (mb, argnum);
4411 mono_mb_emit_byte (mb, CEE_LDLEN);
4412 mono_mb_emit_byte (mb, CEE_BGE);
4414 mono_mb_emit_i4 (mb, 0);
4416 /* Emit marshalling code */
4418 if (eklass == mono_defaults.stringbuilder_class) {
4420 MonoMarshalNative encoding = mono_marshal_get_ptr_to_stringbuilder_encoding (piinfo, spec, &need_free);
4422 g_assert (encoding != -1);
4425 mono_mb_emit_ldarg (mb, argnum);
4426 mono_mb_emit_ldloc (mb, index_var);
4427 mono_mb_emit_byte (mb, CEE_LDELEM_REF);
4430 mono_mb_emit_ldloc (mb, src_ptr);
4431 mono_mb_emit_byte (mb, CEE_LDIND_I);
4433 mono_mb_emit_icall (mb, conv_to_icall (encoding));
4437 mono_mb_emit_ldloc (mb, src_ptr);
4438 mono_mb_emit_byte (mb, CEE_LDIND_I);
4440 mono_mb_emit_icall (mb, g_free);
4444 /* set the src_ptr */
4445 mono_mb_emit_ldloc (mb, src_ptr);
4446 mono_mb_emit_byte (mb, CEE_STLOC_0);
4449 mono_mb_emit_ldarg (mb, argnum);
4450 mono_mb_emit_ldloc (mb, index_var);
4451 mono_mb_emit_byte (mb, CEE_LDELEMA);
4452 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eklass));
4453 mono_mb_emit_byte (mb, CEE_STLOC_1);
4455 /* emit valuetype conversion code */
4456 emit_struct_conv (mb, eklass, TRUE);
4459 mono_mb_emit_add_to_local (mb, index_var, 1);
4460 mono_mb_emit_add_to_local (mb, src_ptr, esize);
4462 mono_mb_emit_byte (mb, CEE_BR);
4463 mono_mb_emit_i4 (mb, label2 - (mb->pos + 4));
4465 mono_mb_patch_addr (mb, label1, mb->pos - (label1 + 4));
4466 mono_mb_patch_addr (mb, label3, mb->pos - (label3 + 4));
4469 case MONO_TYPE_BOOLEAN:
4472 mono_mb_emit_ldarg (mb, argnum);
4473 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4474 if (mspecs [i + 1] != NULL && mspecs [i + 1]->native == MONO_NATIVE_VARIANTBOOL)
4475 mono_mb_emit_byte (mb, CEE_NEG);
4476 mono_mb_emit_byte (mb, CEE_STIND_I1);
4480 if (!MONO_TYPE_IS_VOID(sig->ret))
4481 mono_mb_emit_byte (mb, CEE_LDLOC_3);
4483 mono_mb_emit_byte (mb, CEE_RET);
4485 csig = mono_metadata_signature_dup (sig);
4487 res = mono_mb_create_and_cache (cache, method,
4488 mb, csig, csig->param_count + 16);
4491 for (i = sig->param_count; i >= 0; i--)
4492 g_free (mspecs [i]);
4495 /* printf ("CODE FOR %s: \n%s.\n", mono_method_full_name (res, TRUE), mono_disasm_code (0, res, ((MonoMethodNormal*)res)->header->code, ((MonoMethodNormal*)res)->header->code + ((MonoMethodNormal*)res)->header->code_size)); */
4501 mono_upgrade_remote_class_wrapper (MonoReflectionType *rtype, MonoTransparentProxy *tproxy);
4503 static MonoReflectionType *
4504 type_from_handle (MonoType *handle)
4506 MonoDomain *domain = mono_domain_get ();
4507 MonoClass *klass = mono_class_from_mono_type (handle);
4509 MONO_ARCH_SAVE_REGS;
4511 mono_class_init (klass);
4512 return mono_type_get_object (domain, handle);
4516 * mono_marshal_get_isinst:
4517 * @klass: the type of the field
4519 * This method generates a function which can be used to check if an object is
4520 * an instance of the given type, icluding the case where the object is a proxy.
4521 * The generated function has the following signature:
4522 * MonoObject* __isinst_wrapper_ (MonoObject *obj)
4525 mono_marshal_get_isinst (MonoClass *klass)
4527 static MonoMethodSignature *isint_sig = NULL;
4528 static GHashTable *isinst_hash = NULL;
4530 int pos_was_ok, pos_failed, pos_end, pos_end2;
4532 MonoMethodBuilder *mb;
4534 EnterCriticalSection (&marshal_mutex);
4536 isinst_hash = g_hash_table_new (NULL, NULL);
4538 res = g_hash_table_lookup (isinst_hash, klass);
4539 LeaveCriticalSection (&marshal_mutex);
4544 isint_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
4545 isint_sig->params [0] = &mono_defaults.object_class->byval_arg;
4546 isint_sig->ret = &mono_defaults.object_class->byval_arg;
4547 isint_sig->pinvoke = 0;
4550 name = g_strdup_printf ("__isinst_wrapper_%s", klass->name);
4551 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_ISINST);
4554 mb->method->save_lmf = 1;
4556 /* check if the object is a proxy that needs special cast */
4557 mono_mb_emit_ldarg (mb, 0);
4558 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4559 mono_mb_emit_byte (mb, CEE_MONO_CISINST);
4560 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
4562 /* The result of MONO_ISINST can be:
4563 0) the type check succeeded
4564 1) the type check did not succeed
4565 2) a CanCastTo call is needed */
4567 mono_mb_emit_byte (mb, CEE_DUP);
4568 pos_was_ok = mono_mb_emit_branch (mb, CEE_BRFALSE);
4570 mono_mb_emit_byte (mb, CEE_LDC_I4_2);
4571 pos_failed = mono_mb_emit_branch (mb, CEE_BNE_UN);
4573 /* get the real proxy from the transparent proxy*/
4575 mono_mb_emit_ldarg (mb, 0);
4576 mono_mb_emit_managed_call (mb, mono_marshal_get_proxy_cancast (klass), NULL);
4577 pos_end = mono_mb_emit_branch (mb, CEE_BR);
4581 mono_mb_patch_addr (mb, pos_failed, mb->pos - (pos_failed + 4));
4582 mono_mb_emit_byte (mb, CEE_LDNULL);
4583 pos_end2 = mono_mb_emit_branch (mb, CEE_BR);
4587 mono_mb_patch_addr (mb, pos_was_ok, mb->pos - (pos_was_ok + 4));
4588 mono_mb_emit_byte (mb, CEE_POP);
4589 mono_mb_emit_ldarg (mb, 0);
4593 mono_mb_patch_addr (mb, pos_end, mb->pos - (pos_end + 4));
4594 mono_mb_patch_addr (mb, pos_end2, mb->pos - (pos_end2 + 4));
4595 mono_mb_emit_byte (mb, CEE_RET);
4597 res = mono_mb_create_and_cache (isinst_hash, klass, mb, isint_sig, isint_sig->param_count + 16);
4604 * mono_marshal_get_castclass:
4605 * @klass: the type of the field
4607 * This method generates a function which can be used to cast an object to
4608 * an instance of the given type, icluding the case where the object is a proxy.
4609 * The generated function has the following signature:
4610 * MonoObject* __castclass_wrapper_ (MonoObject *obj)
4613 mono_marshal_get_castclass (MonoClass *klass)
4615 static MonoMethodSignature *castclass_sig = NULL;
4616 static GHashTable *castclass_hash = NULL;
4618 int pos_was_ok, pos_was_ok2;
4620 MonoMethodBuilder *mb;
4622 EnterCriticalSection (&marshal_mutex);
4623 if (!castclass_hash)
4624 castclass_hash = g_hash_table_new (NULL, NULL);
4626 res = g_hash_table_lookup (castclass_hash, klass);
4627 LeaveCriticalSection (&marshal_mutex);
4631 if (!castclass_sig) {
4632 castclass_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
4633 castclass_sig->params [0] = &mono_defaults.object_class->byval_arg;
4634 castclass_sig->ret = &mono_defaults.object_class->byval_arg;
4635 castclass_sig->pinvoke = 0;
4638 name = g_strdup_printf ("__castclass_wrapper_%s", klass->name);
4639 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_CASTCLASS);
4642 mb->method->save_lmf = 1;
4644 /* check if the object is a proxy that needs special cast */
4645 mono_mb_emit_ldarg (mb, 0);
4646 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4647 mono_mb_emit_byte (mb, CEE_MONO_CCASTCLASS);
4648 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
4650 /* The result of MONO_ISINST can be:
4651 0) the cast is valid
4652 1) cast of unknown proxy type
4653 or an exception if the cast is is invalid
4656 pos_was_ok = mono_mb_emit_branch (mb, CEE_BRFALSE);
4658 /* get the real proxy from the transparent proxy*/
4660 mono_mb_emit_ldarg (mb, 0);
4661 mono_mb_emit_managed_call (mb, mono_marshal_get_proxy_cancast (klass), NULL);
4662 pos_was_ok2 = mono_mb_emit_branch (mb, CEE_BRTRUE);
4665 mono_mb_emit_exception (mb, "InvalidCastException", NULL);
4668 mono_mb_patch_addr (mb, pos_was_ok, mb->pos - (pos_was_ok + 4));
4669 mono_mb_patch_addr (mb, pos_was_ok2, mb->pos - (pos_was_ok2 + 4));
4670 mono_mb_emit_ldarg (mb, 0);
4673 mono_mb_emit_byte (mb, CEE_RET);
4675 res = mono_mb_create_and_cache (castclass_hash, klass, mb, castclass_sig, castclass_sig->param_count + 16);
4682 mono_marshal_get_proxy_cancast (MonoClass *klass)
4684 static MonoMethodSignature *from_handle_sig = NULL;
4685 static MonoMethodSignature *upgrade_proxy_sig = NULL;
4686 static MonoMethodSignature *isint_sig = NULL;
4687 static GHashTable *proxy_isinst_hash = NULL;
4689 int pos_failed, pos_end;
4691 MonoMethod *can_cast_to;
4692 MonoMethodDesc *desc;
4693 MonoMethodBuilder *mb;
4695 EnterCriticalSection (&marshal_mutex);
4696 if (!proxy_isinst_hash)
4697 proxy_isinst_hash = g_hash_table_new (NULL, NULL);
4699 res = g_hash_table_lookup (proxy_isinst_hash, klass);
4700 LeaveCriticalSection (&marshal_mutex);
4705 upgrade_proxy_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
4706 upgrade_proxy_sig->params [0] = &mono_defaults.object_class->byval_arg;
4707 upgrade_proxy_sig->params [1] = &mono_defaults.object_class->byval_arg;
4708 upgrade_proxy_sig->ret = &mono_defaults.void_class->byval_arg;
4709 upgrade_proxy_sig->pinvoke = 1;
4711 from_handle_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
4712 from_handle_sig->params [0] = &mono_defaults.object_class->byval_arg;
4713 from_handle_sig->ret = &mono_defaults.object_class->byval_arg;
4715 isint_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
4716 isint_sig->params [0] = &mono_defaults.object_class->byval_arg;
4717 isint_sig->ret = &mono_defaults.object_class->byval_arg;
4718 isint_sig->pinvoke = 0;
4721 name = g_strdup_printf ("__proxy_isinst_wrapper_%s", klass->name);
4722 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_PROXY_ISINST);
4725 mb->method->save_lmf = 1;
4727 /* get the real proxy from the transparent proxy*/
4728 mono_mb_emit_ldarg (mb, 0);
4729 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoTransparentProxy, rp));
4730 mono_mb_emit_byte (mb, CEE_LDIND_I);
4732 /* get the refletion type from the type handle */
4733 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4734 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
4735 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, &klass->byval_arg));
4736 mono_mb_emit_native_call (mb, from_handle_sig, type_from_handle);
4738 mono_mb_emit_ldarg (mb, 0);
4740 /* make the call to CanCastTo (type, ob) */
4741 desc = mono_method_desc_new ("IRemotingTypeInfo:CanCastTo", FALSE);
4742 can_cast_to = mono_method_desc_search_in_class (desc, mono_defaults.iremotingtypeinfo_class);
4743 g_assert (can_cast_to);
4744 mono_method_desc_free (desc);
4745 mono_mb_emit_byte (mb, CEE_CALLVIRT);
4746 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, can_cast_to));
4749 pos_failed = mono_mb_emit_branch (mb, CEE_BRFALSE);
4751 /* Upgrade the proxy vtable by calling: mono_upgrade_remote_class_wrapper (type, ob)*/
4752 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4753 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
4754 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, &klass->byval_arg));
4755 mono_mb_emit_native_call (mb, from_handle_sig, type_from_handle);
4756 mono_mb_emit_ldarg (mb, 0);
4758 mono_mb_emit_native_call (mb, upgrade_proxy_sig, mono_upgrade_remote_class_wrapper);
4759 emit_thread_interrupt_checkpoint (mb);
4761 mono_mb_emit_ldarg (mb, 0);
4762 pos_end = mono_mb_emit_branch (mb, CEE_BR);
4766 mono_mb_patch_addr (mb, pos_failed, mb->pos - (pos_failed + 4));
4767 mono_mb_emit_byte (mb, CEE_LDNULL);
4771 mono_mb_patch_addr (mb, pos_end, mb->pos - (pos_end + 4));
4772 mono_mb_emit_byte (mb, CEE_RET);
4774 res = mono_mb_create_and_cache (proxy_isinst_hash, klass, mb, isint_sig, isint_sig->param_count + 16);
4781 mono_upgrade_remote_class_wrapper (MonoReflectionType *rtype, MonoTransparentProxy *tproxy)
4784 klass = mono_class_from_mono_type (rtype->type);
4785 mono_upgrade_remote_class (((MonoObject*)tproxy)->vtable->domain, tproxy->remote_class, klass);
4786 ((MonoObject*)tproxy)->vtable = tproxy->remote_class->vtable;
4790 * mono_marshal_get_struct_to_ptr:
4793 * generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld)
4796 mono_marshal_get_struct_to_ptr (MonoClass *klass)
4798 MonoMethodBuilder *mb;
4799 static MonoMethod *stoptr = NULL;
4802 g_assert (klass != NULL);
4804 if (klass->str_to_ptr)
4805 return klass->str_to_ptr;
4808 stoptr = mono_find_method_by_name (mono_defaults.marshal_class, "StructureToPtr", 3);
4811 mb = mono_mb_new (klass, stoptr->name, MONO_WRAPPER_UNKNOWN);
4813 if (klass->blittable) {
4814 mono_mb_emit_byte (mb, CEE_LDARG_1);
4815 mono_mb_emit_byte (mb, CEE_LDARG_0);
4816 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
4817 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
4818 mono_mb_emit_byte (mb, CEE_PREFIX1);
4819 mono_mb_emit_byte (mb, CEE_CPBLK);
4822 /* allocate local 0 (pointer) src_ptr */
4823 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
4824 /* allocate local 1 (pointer) dst_ptr */
4825 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
4826 /* allocate local 2 (boolean) delete_old */
4827 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
4828 mono_mb_emit_byte (mb, CEE_LDARG_2);
4829 mono_mb_emit_byte (mb, CEE_STLOC_2);
4831 /* initialize src_ptr to point to the start of object data */
4832 mono_mb_emit_byte (mb, CEE_LDARG_0);
4833 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
4834 mono_mb_emit_byte (mb, CEE_STLOC_0);
4836 /* initialize dst_ptr */
4837 mono_mb_emit_byte (mb, CEE_LDARG_1);
4838 mono_mb_emit_byte (mb, CEE_STLOC_1);
4840 emit_struct_conv (mb, klass, FALSE);
4843 mono_mb_emit_byte (mb, CEE_RET);
4845 res = mono_mb_create_method (mb, stoptr->signature, 0);
4848 klass->str_to_ptr = res;
4853 * mono_marshal_get_ptr_to_struct:
4856 * generates IL code for PtrToStructure (IntPtr src, object structure)
4859 mono_marshal_get_ptr_to_struct (MonoClass *klass)
4861 MonoMethodBuilder *mb;
4862 static MonoMethod *ptostr = NULL;
4865 g_assert (klass != NULL);
4867 if (klass->ptr_to_str)
4868 return klass->ptr_to_str;
4871 ptostr = mono_find_method_by_name (mono_defaults.marshal_class, "PtrToStructure", 2);
4874 mb = mono_mb_new (klass, ptostr->name, MONO_WRAPPER_UNKNOWN);
4876 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable) {
4877 mono_mb_emit_byte (mb, CEE_LDARG_1);
4878 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
4879 mono_mb_emit_byte (mb, CEE_LDARG_0);
4880 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
4881 mono_mb_emit_byte (mb, CEE_PREFIX1);
4882 mono_mb_emit_byte (mb, CEE_CPBLK);
4885 /* allocate local 0 (pointer) src_ptr */
4886 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
4887 /* allocate local 1 (pointer) dst_ptr */
4888 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
4890 /* initialize src_ptr to point to the start of object data */
4891 mono_mb_emit_byte (mb, CEE_LDARG_0);
4892 mono_mb_emit_byte (mb, CEE_STLOC_0);
4894 /* initialize dst_ptr */
4895 mono_mb_emit_byte (mb, CEE_LDARG_1);
4896 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
4897 mono_mb_emit_byte (mb, CEE_STLOC_1);
4899 emit_struct_conv (mb, klass, TRUE);
4902 mono_mb_emit_byte (mb, CEE_RET);
4904 res = mono_mb_create_method (mb, ptostr->signature, 0);
4907 klass->ptr_to_str = res;
4912 * generates IL code for the synchronized wrapper: the generated method
4913 * calls METHOD while locking 'this' or the parent type.
4916 mono_marshal_get_synchronized_wrapper (MonoMethod *method)
4918 static MonoMethodSignature *from_handle_sig = NULL;
4919 static MonoMethod *enter_method, *exit_method;
4920 MonoMethodSignature *sig;
4921 MonoExceptionClause *clause;
4922 MonoMethodHeader *header;
4923 MonoMethodBuilder *mb;
4926 int i, pos, this_local, ret_local;
4930 if (method->wrapper_type == MONO_WRAPPER_SYNCHRONIZED)
4933 cache = method->klass->image->synchronized_cache;
4934 if ((res = mono_marshal_find_in_cache (cache, method)))
4937 sig = method->signature;
4939 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_SYNCHRONIZED);
4942 if (!MONO_TYPE_IS_VOID (sig->ret))
4943 ret_local = mono_mb_add_local (mb, sig->ret);
4946 this_local = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
4948 clause = g_new0 (MonoExceptionClause, 1);
4949 clause->flags = MONO_EXCEPTION_CLAUSE_FINALLY;
4951 if (!enter_method) {
4952 MonoMethodDesc *desc;
4954 desc = mono_method_desc_new ("Monitor:Enter", FALSE);
4955 enter_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
4956 g_assert (enter_method);
4957 mono_method_desc_free (desc);
4958 desc = mono_method_desc_new ("Monitor:Exit", FALSE);
4959 exit_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
4960 g_assert (exit_method);
4961 mono_method_desc_free (desc);
4964 * GetTypeFromHandle isn't called as a managed method because it has
4965 * a funky calling sequence, e.g. ldtoken+GetTypeFromHandle gets
4966 * transformed into something else by the JIT.
4968 from_handle_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
4969 from_handle_sig->params [0] = &mono_defaults.object_class->byval_arg;
4970 from_handle_sig->ret = &mono_defaults.object_class->byval_arg;
4973 /* Push this or the type object */
4974 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4975 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4976 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
4977 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, &method->klass->byval_arg));
4978 mono_mb_emit_native_call (mb, from_handle_sig, type_from_handle);
4981 mono_mb_emit_ldarg (mb, 0);
4982 mono_mb_emit_stloc (mb, this_local);
4984 /* Call Monitor::Enter() */
4985 mono_mb_emit_ldloc (mb, this_local);
4986 mono_mb_emit_managed_call (mb, enter_method, NULL);
4988 clause->try_offset = mb->pos;
4990 /* Call the method */
4992 mono_mb_emit_ldarg (mb, 0);
4993 for (i = 0; i < sig->param_count; i++)
4994 mono_mb_emit_ldarg (mb, i + (sig->hasthis == TRUE));
4995 mono_mb_emit_managed_call (mb, method, method->signature);
4996 if (!MONO_TYPE_IS_VOID (sig->ret))
4997 mono_mb_emit_stloc (mb, ret_local);
4999 mono_mb_emit_byte (mb, CEE_LEAVE);
5001 mono_mb_emit_i4 (mb, 0);
5003 clause->try_len = mb->pos - clause->try_offset;
5004 clause->handler_offset = mb->pos;
5006 /* Call Monitor::Exit() */
5007 mono_mb_emit_ldloc (mb, this_local);
5008 /* mono_mb_emit_native_call (mb, exit_sig, mono_monitor_exit); */
5009 mono_mb_emit_managed_call (mb, exit_method, NULL);
5010 mono_mb_emit_byte (mb, CEE_ENDFINALLY);
5012 clause->handler_len = mb->pos - clause->handler_offset;
5014 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
5015 if (!MONO_TYPE_IS_VOID (sig->ret))
5016 mono_mb_emit_ldloc (mb, ret_local);
5017 mono_mb_emit_byte (mb, CEE_RET);
5019 res = mono_mb_create_and_cache (cache, method,
5020 mb, sig, sig->param_count + 16);
5023 header = ((MonoMethodNormal *)res)->header;
5024 header->num_clauses = 1;
5025 header->clauses = clause;
5031 mono_marshal_get_stelemref ()
5033 static MonoMethod* ret = NULL;
5034 MonoMethodSignature *sig;
5035 MonoMethodBuilder *mb;
5037 guint32 b1, b2, b3, b4;
5044 mb = mono_mb_new (mono_defaults.object_class, "stelemref", MONO_WRAPPER_STELEMREF);
5047 sig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
5049 /* void stelemref (void* array, int idx, void* value) */
5050 sig->ret = &mono_defaults.void_class->byval_arg;
5051 sig->params [0] = &mono_defaults.int_class->byval_arg;
5052 sig->params [1] = &mono_defaults.int_class->byval_arg; /* this is a natural sized int */
5053 sig->params [2] = &mono_defaults.int_class->byval_arg;
5055 aklass = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
5056 vklass = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
5064 aklass = array->vtable->klass->element_class;
5065 vklass = value->vtable->klass;
5067 if (vklass->idepth < aklass->idepth)
5070 if (vklass->supertypes [aklass->idepth - 1] != aklass)
5074 array [idx] = value;
5078 if (mono_object_isinst (value, aklass))
5081 throw new ArrayTypeMismatchException ();
5085 mono_mb_emit_ldarg (mb, 0);
5086 mono_mb_emit_ldarg (mb, 1);
5087 mono_mb_emit_byte (mb, CEE_LDELEMA);
5088 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_defaults.int_class));
5089 mono_mb_emit_byte (mb, CEE_POP);
5091 /* if (!value) goto do_store */
5092 mono_mb_emit_ldarg (mb, 2);
5093 b1 = mono_mb_emit_branch (mb, CEE_BRFALSE);
5095 /* aklass = array->vtable->klass->element_class */
5096 mono_mb_emit_ldarg (mb, 0);
5097 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoObject, vtable));
5098 mono_mb_emit_byte (mb, CEE_LDIND_I);
5099 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoVTable, klass));
5100 mono_mb_emit_byte (mb, CEE_LDIND_I);
5101 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoClass, element_class));
5102 mono_mb_emit_byte (mb, CEE_LDIND_I);
5103 mono_mb_emit_stloc (mb, aklass);
5105 /* vklass = value->vtable->klass */
5106 mono_mb_emit_ldarg (mb, 2);
5107 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoObject, vtable));
5108 mono_mb_emit_byte (mb, CEE_LDIND_I);
5109 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoVTable, klass));
5110 mono_mb_emit_byte (mb, CEE_LDIND_I);
5111 mono_mb_emit_stloc (mb, vklass);
5113 /* if (vklass->idepth < aklass->idepth) goto failue */
5114 mono_mb_emit_ldloc (mb, vklass);
5115 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoClass, idepth));
5116 mono_mb_emit_byte (mb, CEE_LDIND_I4);
5118 mono_mb_emit_ldloc (mb, aklass);
5119 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoClass, idepth));
5120 mono_mb_emit_byte (mb, CEE_LDIND_I4);
5122 b2 = mono_mb_emit_branch (mb, CEE_BLT_UN);
5124 /* if (vklass->supertypes [aklass->idepth - 1] != aklass) goto failure */
5125 mono_mb_emit_ldloc (mb, vklass);
5126 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoClass, supertypes));
5127 mono_mb_emit_byte (mb, CEE_LDIND_I);
5129 mono_mb_emit_ldloc (mb, aklass);
5130 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoClass, idepth));
5131 mono_mb_emit_byte (mb, CEE_LDIND_I4);
5132 mono_mb_emit_icon (mb, 1);
5133 mono_mb_emit_byte (mb, CEE_SUB);
5134 mono_mb_emit_icon (mb, sizeof (void*));
5135 mono_mb_emit_byte (mb, CEE_MUL);
5136 mono_mb_emit_byte (mb, CEE_ADD);
5137 mono_mb_emit_byte (mb, CEE_LDIND_I);
5139 mono_mb_emit_ldloc (mb, aklass);
5141 b3 = mono_mb_emit_branch (mb, CEE_BNE_UN);
5145 mono_mb_patch_addr (mb, b1, mb->pos - (b1 + 4));
5146 mono_mb_emit_ldarg (mb, 0);
5147 mono_mb_emit_ldarg (mb, 1);
5148 mono_mb_emit_ldarg (mb, 2);
5149 mono_mb_emit_byte (mb, CEE_STELEM_I);
5151 mono_mb_emit_byte (mb, CEE_RET);
5154 mono_mb_patch_addr (mb, b2, mb->pos - (b2 + 4));
5155 mono_mb_patch_addr (mb, b3, mb->pos - (b3 + 4));
5157 mono_mb_emit_ldarg (mb, 2);
5158 mono_mb_emit_ldloc (mb, aklass);
5159 mono_mb_emit_icall (mb, mono_object_isinst);
5161 b4 = mono_mb_emit_branch (mb, CEE_BRTRUE);
5162 mono_mb_patch_addr (mb, b4, copy_pos - (b4 + 4));
5163 mono_mb_emit_exception (mb, "ArrayTypeMismatchException", NULL);
5165 mono_mb_emit_byte (mb, CEE_RET);
5166 ret = mono_mb_create_method (mb, sig, 4);
5170 /* FIXME: on win32 we should probably use GlobalAlloc(). */
5172 mono_marshal_alloc (gpointer size)
5174 MONO_ARCH_SAVE_REGS;
5176 return g_try_malloc ((gulong)size);
5180 mono_marshal_free (gpointer ptr)
5182 MONO_ARCH_SAVE_REGS;
5188 mono_marshal_free_array (gpointer *ptr, int size)
5195 for (i = 0; i < size; i++)
5201 mono_marshal_realloc (gpointer ptr, gpointer size)
5203 MONO_ARCH_SAVE_REGS;
5205 return g_try_realloc (ptr, (gulong)size);
5209 mono_marshal_string_array (MonoArray *array)
5217 len = mono_array_length (array);
5219 result = g_malloc (sizeof (char *) * (len + 1));
5220 for (i = 0; i < len; ++i) {
5221 MonoString *s = (MonoString *)mono_array_get (array, gpointer, i);
5222 result [i] = s ? mono_string_to_utf8 (s): NULL;
5224 /* null terminate the array */
5231 mono_marshal_string_array_to_unicode (MonoArray *array)
5239 len = mono_array_length (array);
5241 result = g_malloc (sizeof (gunichar2 *) * (len + 1));
5242 for (i = 0; i < len; ++i) {
5243 MonoString *s = (MonoString *)mono_array_get (array, gpointer, i);
5244 result [i] = s ? mono_string_chars (s) : NULL;
5246 /* null terminate the array */
5253 * mono_marshal_set_last_error:
5255 * This function is invoked to set the last error value from a P/Invoke call
5256 * which has SetLastError set.
5259 mono_marshal_set_last_error (void)
5262 TlsSetValue (last_error_tls_id, (gpointer)GetLastError ());
5264 TlsSetValue (last_error_tls_id, (gpointer)errno);
5269 ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArray *src, gint32 start_index,
5270 gpointer dest, gint32 length)
5275 MONO_ARCH_SAVE_REGS;
5277 MONO_CHECK_ARG_NULL (src);
5278 MONO_CHECK_ARG_NULL (dest);
5280 g_assert (src->obj.vtable->klass->rank == 1);
5281 g_assert (start_index >= 0);
5282 g_assert (length >= 0);
5283 g_assert (start_index + length <= mono_array_length (src));
5285 element_size = mono_array_element_size (src->obj.vtable->klass);
5287 source_addr = mono_array_addr_with_size (src, element_size, start_index);
5289 memcpy (dest, source_addr, length * element_size);
5293 ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer src, gint32 start_index,
5294 MonoArray *dest, gint32 length)
5299 MONO_ARCH_SAVE_REGS;
5301 MONO_CHECK_ARG_NULL (src);
5302 MONO_CHECK_ARG_NULL (dest);
5304 g_assert (dest->obj.vtable->klass->rank == 1);
5305 g_assert (start_index >= 0);
5306 g_assert (length >= 0);
5307 g_assert (start_index + length <= mono_array_length (dest));
5309 element_size = mono_array_element_size (dest->obj.vtable->klass);
5311 dest_addr = mono_array_addr_with_size (dest, element_size, start_index);
5313 memcpy (dest_addr, src, length * element_size);
5316 #if NO_UNALIGNED_ACCESS
5317 #define RETURN_UNALIGNED(type, addr) \
5320 memcpy(&val, p + offset, sizeof(val)); \
5323 #define WRITE_UNALIGNED(type, addr, val) \
5324 memcpy(addr, &val, sizeof(type))
5326 #define RETURN_UNALIGNED(type, addr) \
5327 return *(type*)(p + offset);
5328 #define WRITE_UNALIGNED(type, addr, val) \
5329 (*(type *)(addr) = (val))
5333 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr, gint32 offset)
5337 MONO_ARCH_SAVE_REGS;
5339 RETURN_UNALIGNED(gpointer, p + offset);
5343 ves_icall_System_Runtime_InteropServices_Marshal_ReadByte (gpointer ptr, gint32 offset)
5347 MONO_ARCH_SAVE_REGS;
5349 return *(unsigned char*)(p + offset);
5353 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt16 (gpointer ptr, gint32 offset)
5357 MONO_ARCH_SAVE_REGS;
5359 RETURN_UNALIGNED(gint16, p + offset);
5363 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt32 (gpointer ptr, gint32 offset)
5367 MONO_ARCH_SAVE_REGS;
5369 RETURN_UNALIGNED(gint32, p + offset);
5373 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt64 (gpointer ptr, gint32 offset)
5377 MONO_ARCH_SAVE_REGS;
5379 RETURN_UNALIGNED(gint64, p + offset);
5383 ves_icall_System_Runtime_InteropServices_Marshal_WriteByte (gpointer ptr, gint32 offset, unsigned char val)
5387 MONO_ARCH_SAVE_REGS;
5389 *(unsigned char*)(p + offset) = val;
5393 ves_icall_System_Runtime_InteropServices_Marshal_WriteIntPtr (gpointer ptr, gint32 offset, gpointer val)
5397 MONO_ARCH_SAVE_REGS;
5399 WRITE_UNALIGNED(gpointer, p + offset, val);
5403 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt16 (gpointer ptr, gint32 offset, gint16 val)
5407 MONO_ARCH_SAVE_REGS;
5409 WRITE_UNALIGNED(gint16, p + offset, val);
5413 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt32 (gpointer ptr, gint32 offset, gint32 val)
5417 MONO_ARCH_SAVE_REGS;
5419 WRITE_UNALIGNED(gint32, p + offset, val);
5423 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt64 (gpointer ptr, gint32 offset, gint64 val)
5427 MONO_ARCH_SAVE_REGS;
5429 WRITE_UNALIGNED(gint64, p + offset, val);
5433 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (char *ptr)
5435 MONO_ARCH_SAVE_REGS;
5438 return mono_string_new (mono_domain_get (), "");
5440 return mono_string_new (mono_domain_get (), ptr);
5444 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len (char *ptr, gint32 len)
5446 MONO_ARCH_SAVE_REGS;
5449 return mono_string_new (mono_domain_get (), "");
5451 return mono_string_new_len (mono_domain_get (), ptr, len);
5455 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni (guint16 *ptr)
5457 MonoDomain *domain = mono_domain_get ();
5461 MONO_ARCH_SAVE_REGS;
5464 return mono_string_new (mono_domain_get (), "");
5469 return mono_string_new_utf16 (domain, ptr, len);
5473 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len (guint16 *ptr, gint32 len)
5475 MonoDomain *domain = mono_domain_get ();
5477 MONO_ARCH_SAVE_REGS;
5480 return mono_string_new (mono_domain_get (), "");
5482 return mono_string_new_utf16 (domain, ptr, len);
5486 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR (gpointer ptr)
5488 MONO_ARCH_SAVE_REGS;
5490 g_warning ("PtrToStringBSTR not implemented");
5491 g_assert_not_reached ();
5497 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
5499 MONO_ARCH_SAVE_REGS;
5501 return ((guint32)TlsGetValue (last_error_tls_id));
5505 ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype)
5511 MONO_ARCH_SAVE_REGS;
5513 MONO_CHECK_ARG_NULL (rtype);
5516 klass = mono_class_from_mono_type (type);
5517 layout = (klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK);
5519 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
5523 msg = g_strdup_printf ("Type %s cannot be marshaled as an unmanaged structure.", klass->name);
5524 exc = mono_get_exception_argument ("t", msg);
5526 mono_raise_exception (exc);
5530 return mono_class_native_size (klass, NULL);
5534 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old)
5539 MONO_ARCH_SAVE_REGS;
5541 MONO_CHECK_ARG_NULL (obj);
5542 MONO_CHECK_ARG_NULL (dst);
5544 method = mono_marshal_get_struct_to_ptr (obj->vtable->klass);
5548 pa [2] = &delete_old;
5550 mono_runtime_invoke (method, NULL, pa, NULL);
5554 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, MonoObject *dst)
5559 MONO_ARCH_SAVE_REGS;
5561 MONO_CHECK_ARG_NULL (src);
5562 MONO_CHECK_ARG_NULL (dst);
5564 method = mono_marshal_get_ptr_to_struct (dst->vtable->klass);
5569 mono_runtime_invoke (method, NULL, pa, NULL);
5573 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer src, MonoReflectionType *type)
5575 MonoDomain *domain = mono_domain_get ();
5578 MONO_ARCH_SAVE_REGS;
5580 MONO_CHECK_ARG_NULL (src);
5581 MONO_CHECK_ARG_NULL (type);
5583 res = mono_object_new (domain, mono_class_from_mono_type (type->type));
5585 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (src, res);
5591 ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *type, MonoString *field_name)
5593 MonoMarshalType *info;
5596 int i, match_index = -1;
5598 MONO_ARCH_SAVE_REGS;
5600 MONO_CHECK_ARG_NULL (type);
5601 MONO_CHECK_ARG_NULL (field_name);
5603 fname = mono_string_to_utf8 (field_name);
5604 klass = mono_class_from_mono_type (type->type);
5606 while(klass && match_index == -1) {
5607 for (i = 0; i < klass->field.count; ++i) {
5608 if (*fname == *klass->fields [i].name && strcmp (fname, klass->fields [i].name) == 0) {
5614 if(match_index == -1)
5615 klass = klass->parent;
5620 if(match_index == -1) {
5624 /* Get back original class instance */
5625 klass = mono_class_from_mono_type (type->type);
5627 tmp = g_strdup_printf ("Field passed in is not a marshaled member of the type %s", klass->name);
5628 exc = mono_get_exception_argument ("fieldName", tmp);
5631 mono_raise_exception ((MonoException*)exc);
5634 info = mono_marshal_load_type_info (klass);
5635 return info->fields [match_index].offset;
5639 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString *string)
5641 MONO_ARCH_SAVE_REGS;
5643 return mono_string_to_utf8 (string);
5647 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni (MonoString *string)
5649 MONO_ARCH_SAVE_REGS;
5654 return g_memdup (mono_string_chars (string), mono_string_length (string)*2);
5658 mono_struct_delete_old (MonoClass *klass, char *ptr)
5660 MonoMarshalType *info;
5663 info = mono_marshal_load_type_info (klass);
5665 for (i = 0; i < info->num_fields; i++) {
5666 MonoMarshalNative ntype;
5667 MonoMarshalConv conv;
5668 MonoType *ftype = info->fields [i].field->type;
5671 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
5674 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE,
5675 klass->unicode, &conv);
5677 cpos = ptr + info->fields [i].offset;
5680 case MONO_MARSHAL_CONV_NONE:
5681 if (MONO_TYPE_ISSTRUCT (ftype)) {
5682 mono_struct_delete_old (ftype->data.klass, cpos);
5686 case MONO_MARSHAL_CONV_STR_LPWSTR:
5687 case MONO_MARSHAL_CONV_STR_LPSTR:
5688 case MONO_MARSHAL_CONV_STR_LPTSTR:
5689 case MONO_MARSHAL_CONV_STR_BSTR:
5690 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
5691 case MONO_MARSHAL_CONV_STR_TBSTR:
5692 g_free (*(gpointer *)cpos);
5701 ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure (gpointer src, MonoReflectionType *type)
5705 MONO_ARCH_SAVE_REGS;
5707 MONO_CHECK_ARG_NULL (src);
5708 MONO_CHECK_ARG_NULL (type);
5710 klass = mono_class_from_mono_type (type->type);
5712 mono_struct_delete_old (klass, (char *)src);
5716 ves_icall_System_Runtime_InteropServices_Marshal_AllocCoTaskMem (int size)
5718 /* FIXME: Call AllocCoTaskMem under windows */
5719 MONO_ARCH_SAVE_REGS;
5721 return g_try_malloc ((gulong)size);
5725 ves_icall_System_Runtime_InteropServices_Marshal_FreeCoTaskMem (void *ptr)
5727 /* FIXME: Call FreeCoTaskMem under windows */
5728 MONO_ARCH_SAVE_REGS;
5734 ves_icall_System_Runtime_InteropServices_Marshal_UnsafeAddrOfPinnedArrayElement (MonoArray *arrayobj, int index)
5736 return mono_array_addr_with_size (arrayobj, mono_array_element_size (arrayobj->obj.vtable->klass), index);
5740 mono_marshal_load_type_info (MonoClass* klass)
5742 int i, j, count = 0, native_size = 0, min_align = 1;
5743 MonoMarshalType *info;
5746 g_assert (klass != NULL);
5748 if (klass->marshal_info)
5749 return klass->marshal_info;
5752 mono_class_init (klass);
5754 for (i = 0; i < klass->field.count; ++i) {
5755 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
5757 if (mono_field_is_deleted (&klass->fields [i]))
5762 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
5764 klass->marshal_info = info = g_malloc0 (sizeof (MonoMarshalType) + sizeof (MonoMarshalField) * count);
5765 info->num_fields = count;
5767 /* Try to find a size for this type in metadata */
5768 mono_metadata_packing_from_typedef (klass->image, klass->type_token, NULL, &native_size);
5770 if (klass->parent) {
5771 int parent_size = mono_class_native_size (klass->parent, NULL);
5773 /* Add parent size to real size */
5774 native_size += parent_size;
5775 info->native_size = parent_size;
5778 for (j = i = 0; i < klass->field.count; ++i) {
5781 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
5784 if (mono_field_is_deleted (&klass->fields [i]))
5786 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL)
5787 mono_metadata_field_info (klass->image, klass->field.first + i,
5788 NULL, NULL, &info->fields [j].mspec);
5790 info->fields [j].field = &klass->fields [i];
5792 if ((klass->field.count == 1) && (klass->instance_size == sizeof (MonoObject)) &&
5793 (strcmp (klass->fields [i].name, "$PRIVATE$") == 0)) {
5794 /* This field is a hack inserted by MCS to empty structures */
5799 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
5800 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
5801 size = mono_marshal_type_size (klass->fields [i].type, info->fields [j].mspec,
5802 &align, TRUE, klass->unicode);
5803 align = klass->packing_size ? MIN (klass->packing_size, align): align;
5804 min_align = MAX (align, min_align);
5805 info->fields [j].offset = info->native_size;
5806 info->fields [j].offset += align - 1;
5807 info->fields [j].offset &= ~(align - 1);
5808 info->native_size = info->fields [j].offset + size;
5810 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
5811 size = mono_marshal_type_size (klass->fields [i].type, info->fields [j].mspec,
5812 &align, TRUE, klass->unicode);
5813 align = klass->packing_size ? MIN (klass->packing_size, align): align;
5814 min_align = MAX (align, min_align);
5815 info->fields [j].offset = klass->fields [i].offset - sizeof (MonoObject);
5816 info->native_size = MAX (info->native_size, info->fields [j].offset + size);
5822 if(layout != TYPE_ATTRIBUTE_AUTO_LAYOUT) {
5823 info->native_size = MAX (native_size, info->native_size);
5826 if (info->native_size & (min_align - 1)) {
5827 info->native_size += min_align - 1;
5828 info->native_size &= ~(min_align - 1);
5831 /* Update the class's blittable info, if the layouts don't match */
5832 if (info->native_size != mono_class_value_size (klass, NULL))
5833 klass->blittable = FALSE;
5835 /* If this is an array type, ensure that we have element info */
5836 if (klass->element_class) {
5837 mono_marshal_load_type_info (klass->element_class);
5840 return klass->marshal_info;
5844 * mono_class_native_size:
5847 * Returns: the native size of an object instance (when marshaled
5848 * to unmanaged code)
5851 mono_class_native_size (MonoClass *klass, guint32 *align)
5854 if (!klass->marshal_info)
5855 mono_marshal_load_type_info (klass);
5858 *align = klass->min_align;
5860 return klass->marshal_info->native_size;
5864 * mono_type_native_stack_size:
5865 * @t: the type to return the size it uses on the stack
5867 * Returns: the number of bytes required to hold an instance of this
5868 * type on the native stack
5871 mono_type_native_stack_size (MonoType *t, gint *align)
5875 g_assert (t != NULL);
5886 case MONO_TYPE_BOOLEAN:
5887 case MONO_TYPE_CHAR:
5896 case MONO_TYPE_STRING:
5897 case MONO_TYPE_OBJECT:
5898 case MONO_TYPE_CLASS:
5899 case MONO_TYPE_SZARRAY:
5901 case MONO_TYPE_FNPTR:
5902 case MONO_TYPE_ARRAY:
5903 case MONO_TYPE_TYPEDBYREF:
5914 case MONO_TYPE_VALUETYPE: {
5917 if (t->data.klass->enumtype)
5918 return mono_type_native_stack_size (t->data.klass->enum_basetype, align);
5920 size = mono_class_native_size (t->data.klass, align);
5921 *align = *align + 3;
5931 g_error ("type 0x%02x unknown", t->type);
5936 /* __alignof__ returns the preferred alignment of values not the actual alignment used by
5937 the compiler so is wrong e.g. for Linux where doubles are aligned on a 4 byte boundary
5938 but __alignof__ returns 8 - using G_STRUCT_OFFSET works better */
5939 #define ALIGNMENT(type) G_STRUCT_OFFSET(struct { char c; type x; }, x)
5942 mono_marshal_type_size (MonoType *type, MonoMarshalSpec *mspec, gint32 *align,
5943 gboolean as_field, gboolean unicode)
5945 MonoMarshalNative native_type = mono_type_to_unmanaged (type, mspec, as_field, unicode, NULL);
5948 switch (native_type) {
5949 case MONO_NATIVE_BOOLEAN:
5952 case MONO_NATIVE_I1:
5953 case MONO_NATIVE_U1:
5956 case MONO_NATIVE_I2:
5957 case MONO_NATIVE_U2:
5958 case MONO_NATIVE_VARIANTBOOL:
5961 case MONO_NATIVE_I4:
5962 case MONO_NATIVE_U4:
5963 case MONO_NATIVE_ERROR:
5966 case MONO_NATIVE_I8:
5967 case MONO_NATIVE_U8:
5968 *align = ALIGNMENT(guint64);
5970 case MONO_NATIVE_R4:
5973 case MONO_NATIVE_R8:
5974 *align = ALIGNMENT(double);
5976 case MONO_NATIVE_INT:
5977 case MONO_NATIVE_UINT:
5978 case MONO_NATIVE_LPSTR:
5979 case MONO_NATIVE_LPWSTR:
5980 case MONO_NATIVE_LPTSTR:
5981 case MONO_NATIVE_BSTR:
5982 case MONO_NATIVE_ANSIBSTR:
5983 case MONO_NATIVE_TBSTR:
5984 case MONO_NATIVE_LPARRAY:
5985 case MONO_NATIVE_SAFEARRAY:
5986 case MONO_NATIVE_IUNKNOWN:
5987 case MONO_NATIVE_IDISPATCH:
5988 case MONO_NATIVE_INTERFACE:
5989 case MONO_NATIVE_ASANY:
5990 case MONO_NATIVE_FUNC:
5991 case MONO_NATIVE_LPSTRUCT:
5992 *align = ALIGNMENT(gpointer);
5993 return sizeof (gpointer);
5994 case MONO_NATIVE_STRUCT:
5995 klass = mono_class_from_mono_type (type);
5996 return mono_class_native_size (klass, align);
5997 case MONO_NATIVE_BYVALTSTR: {
5998 int esize = unicode ? 2: 1;
6001 return mspec->data.array_data.num_elem * esize;
6003 case MONO_NATIVE_BYVALARRAY: {
6005 klass = mono_class_from_mono_type (type);
6006 esize = mono_class_native_size (klass->element_class, align);
6008 return mspec->data.array_data.num_elem * esize;
6010 case MONO_NATIVE_CUSTOM:
6011 g_assert_not_reached ();
6013 case MONO_NATIVE_CURRENCY:
6014 case MONO_NATIVE_VBBYREFSTR:
6016 g_error ("native type %02x not implemented", native_type);
6019 g_assert_not_reached ();
6024 mono_marshal_asany (MonoObject *o, MonoMarshalNative string_encoding)
6032 t = &o->vtable->klass->byval_arg;
6039 case MONO_TYPE_BOOLEAN:
6042 case MONO_TYPE_CHAR:
6047 return mono_object_unbox (o);
6049 case MONO_TYPE_STRING:
6050 switch (string_encoding) {
6051 case MONO_NATIVE_LPWSTR:
6052 return mono_string_to_utf16 ((MonoString*)o);
6054 case MONO_NATIVE_LPSTR:
6055 return mono_string_to_utf8 ((MonoString*)o);
6058 g_warning ("marshaling conversion %d not implemented", string_encoding);
6059 g_assert_not_reached ();
6062 case MONO_TYPE_CLASS:
6063 case MONO_TYPE_VALUETYPE: {
6067 MonoBoolean delete_old = FALSE;
6069 klass = t->data.klass;
6071 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT)
6074 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
6075 klass->blittable || klass->enumtype)
6076 return mono_object_unbox (o);
6078 res = g_malloc0 (mono_class_native_size (klass, NULL));
6080 method = mono_marshal_get_struct_to_ptr (o->vtable->klass);
6084 pa [2] = &delete_old;
6086 mono_runtime_invoke (method, NULL, pa, NULL);
6092 mono_raise_exception (mono_get_exception_argument ("", "No PInvoke conversion exists for value passed to Object-typed parameter."));
6098 mono_marshal_free_asany (MonoObject *o, gpointer ptr, MonoMarshalNative string_encoding)
6103 /* FIXME: Free embedded data as well */
6108 t = &o->vtable->klass->byval_arg;
6110 case MONO_TYPE_STRING:
6111 switch (string_encoding) {
6112 case MONO_NATIVE_LPWSTR:
6115 case MONO_NATIVE_LPSTR:
6119 g_warning ("marshaling conversion %d not implemented", string_encoding);
6120 g_assert_not_reached ();
6123 case MONO_TYPE_CLASS:
6124 case MONO_TYPE_VALUETYPE: {
6125 klass = t->data.klass;
6127 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
6128 klass->blittable || klass->enumtype)