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 /* FIXME: Call CleanUpNativeData after the call */
2424 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
2425 g_assert (mtype != NULL);
2426 mklass = mono_class_from_mono_type (mtype);
2427 g_assert (mklass != NULL);
2429 marshal_native_to_managed = mono_find_method_by_name (mklass, "MarshalNativeToManaged", 1);
2430 g_assert (marshal_native_to_managed);
2431 get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
2432 g_assert (get_instance);
2435 case MONO_TYPE_CLASS:
2436 case MONO_TYPE_OBJECT:
2437 case MONO_TYPE_STRING:
2438 case MONO_TYPE_ARRAY:
2439 case MONO_TYPE_SZARRAY:
2443 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2445 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
2447 mono_mb_emit_byte (mb, CEE_CALL);
2448 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
2450 mono_mb_emit_ldarg (mb, i);
2452 mono_mb_emit_byte (mb, CEE_CALLVIRT);
2453 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_native_to_managed));
2455 mono_mb_emit_stloc (mb, tmp_locals [i]);
2458 g_warning ("custom marshalling of type %x is currently not supported", t->type);
2459 g_assert_not_reached ();
2466 case MONO_TYPE_CLASS: {
2467 klass = t->data.klass;
2469 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2471 if (klass->delegate) {
2472 g_assert (!t->byref);
2473 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2474 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
2475 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2476 mono_mb_emit_ldarg (mb, i);
2477 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL));
2478 mono_mb_emit_stloc (mb, tmp_locals [i]);
2482 /* FIXME: Raise a MarshalDirectiveException here */
2483 g_assert ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT);
2485 if (t->attrs & PARAM_ATTRIBUTE_OUT) {
2486 mono_mb_emit_byte (mb, CEE_LDNULL);
2487 mono_mb_emit_stloc (mb, tmp_locals [i]);
2492 mono_mb_emit_ldarg (mb, i);
2496 /* Check for NULL and raise an exception */
2497 mono_mb_emit_byte (mb, CEE_BRTRUE);
2499 mono_mb_emit_i4 (mb, 0);
2501 mono_mb_emit_exception (mb, "ArgumentNullException", NULL);
2503 mono_mb_patch_addr (mb, pos2, mb->pos - (pos2 + 4));
2504 mono_mb_emit_ldarg (mb, i);
2505 mono_mb_emit_byte (mb, CEE_LDIND_I);
2508 mono_mb_emit_byte (mb, CEE_STLOC_0);
2510 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
2511 mono_mb_emit_stloc (mb, tmp_locals [i]);
2513 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2514 mono_mb_emit_byte (mb, CEE_BRFALSE);
2516 mono_mb_emit_i4 (mb, 0);
2518 /* Create and set dst */
2519 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2520 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
2521 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2522 mono_mb_emit_stloc (mb, tmp_locals [i]);
2523 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2524 mono_mb_emit_icon (mb, sizeof (MonoObject));
2525 mono_mb_emit_byte (mb, CEE_ADD);
2526 mono_mb_emit_byte (mb, CEE_STLOC_1);
2528 /* emit valuetype conversion code */
2529 emit_struct_conv (mb, klass, TRUE);
2531 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2534 case MONO_TYPE_VALUETYPE:
2536 klass = sig->params [i]->data.klass;
2537 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2538 klass->blittable || klass->enumtype)
2541 tmp_locals [i] = mono_mb_add_local (mb, &klass->byval_arg);
2543 if (t->attrs & PARAM_ATTRIBUTE_OUT)
2547 mono_mb_emit_ldarg (mb, i);
2549 mono_mb_emit_ldarg_addr (mb, i);
2550 mono_mb_emit_byte (mb, CEE_STLOC_0);
2553 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2554 mono_mb_emit_byte (mb, CEE_BRFALSE);
2556 mono_mb_emit_i4 (mb, 0);
2559 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2560 mono_mb_emit_byte (mb, CEE_STLOC_1);
2562 /* emit valuetype conversion code */
2563 emit_struct_conv (mb, klass, TRUE);
2566 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2568 case MONO_TYPE_STRING: {
2569 MonoMarshalNative encoding = mono_marshal_get_string_encoding (NULL, spec);
2574 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2575 csig->params [i] = &mono_defaults.int_class->byval_arg;
2577 mono_mb_emit_ldarg (mb, i);
2580 case MONO_NATIVE_LPWSTR:
2581 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_LPWSTR_STR));
2583 case MONO_NATIVE_LPSTR:
2584 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_LPSTR_STR));
2587 char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding);
2588 MonoException *exc = mono_get_exception_not_implemented (msg);
2591 mono_raise_exception (exc);
2595 mono_mb_emit_stloc (mb, tmp_locals [i]);
2598 case MONO_TYPE_ARRAY:
2599 case MONO_TYPE_SZARRAY:
2603 klass = mono_class_from_mono_type (t);
2605 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2606 csig->params [i] = &mono_defaults.int_class->byval_arg;
2608 g_warning ("array marshaling not implemented");
2609 g_assert_not_reached ();
2614 for (i = 0; i < sig->param_count; i++) {
2615 MonoType *t = sig->params [i];
2618 case MONO_TYPE_BOOLEAN:
2632 mono_mb_emit_ldarg (mb, i);
2634 case MONO_TYPE_STRING:
2636 mono_mb_emit_ldarg (mb, i);
2638 g_assert (tmp_locals [i]);
2639 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2642 case MONO_TYPE_CLASS:
2644 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2646 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2648 case MONO_TYPE_ARRAY:
2649 case MONO_TYPE_SZARRAY:
2650 case MONO_TYPE_OBJECT:
2652 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2654 mono_mb_emit_ldarg (mb, i);
2656 case MONO_TYPE_VALUETYPE:
2657 klass = sig->params [i]->data.klass;
2658 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2659 klass->blittable || klass->enumtype) {
2660 mono_mb_emit_ldarg (mb, i);
2664 g_assert (tmp_locals [i]);
2666 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2668 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2671 g_warning ("type 0x%02x unknown", t->type);
2672 g_assert_not_reached ();
2676 emit_thread_interrupt_checkpoint (mb);
2677 mono_mb_emit_managed_call (mb, method, NULL);
2679 /* Ensure that we have marshalling info for the return */
2680 mono_marshal_load_type_info (mono_class_from_mono_type (sig->ret));
2682 if (!sig->ret->byref) {
2683 switch (sig->ret->type) {
2684 case MONO_TYPE_VOID:
2686 case MONO_TYPE_BOOLEAN:
2700 case MONO_TYPE_OBJECT:
2701 mono_mb_emit_byte (mb, CEE_STLOC_3);
2703 case MONO_TYPE_STRING:
2704 csig->ret = &mono_defaults.int_class->byval_arg;
2706 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_STR_LPSTR));
2707 mono_mb_emit_byte (mb, CEE_STLOC_3);
2709 case MONO_TYPE_VALUETYPE:
2710 klass = sig->ret->data.klass;
2711 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2712 klass->blittable || klass->enumtype)
2715 /* load pointer to returned value type */
2716 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2717 mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
2719 /* store the address of the source into local variable 0 */
2720 mono_mb_emit_byte (mb, CEE_STLOC_0);
2721 /* allocate space for the native struct and
2722 * store the address into dst_ptr */
2723 retobj_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2724 g_assert (retobj_var);
2725 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2726 mono_mb_emit_byte (mb, CEE_CONV_I);
2727 mono_mb_emit_native_call (mb, alloc_sig, mono_marshal_alloc);
2728 emit_thread_interrupt_checkpoint (mb);
2729 mono_mb_emit_byte (mb, CEE_STLOC_1);
2730 mono_mb_emit_byte (mb, CEE_LDLOC_1);
2731 mono_mb_emit_stloc (mb, retobj_var);
2733 /* emit valuetype conversion code */
2734 emit_struct_conv (mb, klass, FALSE);
2736 case MONO_TYPE_CLASS: {
2739 klass = sig->ret->data.klass;
2741 if (klass->delegate) {
2742 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN));
2743 mono_mb_emit_byte (mb, CEE_STLOC_3);
2747 /* FIXME: Raise a MarshalDirectiveException here */
2748 g_assert ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT);
2750 mono_mb_emit_byte (mb, CEE_STLOC_0);
2751 /* Check for null */
2752 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2753 pos = mono_mb_emit_branch (mb, CEE_BRTRUE);
2754 mono_mb_emit_byte (mb, CEE_LDNULL);
2755 mono_mb_emit_byte (mb, CEE_STLOC_3);
2756 pos2 = mono_mb_emit_branch (mb, CEE_BR);
2758 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2761 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2762 mono_mb_emit_icon (mb, sizeof (MonoObject));
2763 mono_mb_emit_byte (mb, CEE_ADD);
2764 mono_mb_emit_byte (mb, CEE_STLOC_0);
2766 /* Allocate and set dest */
2767 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2768 mono_mb_emit_byte (mb, CEE_CONV_I);
2769 mono_mb_emit_native_call (mb, alloc_sig, mono_marshal_alloc);
2770 emit_thread_interrupt_checkpoint (mb);
2771 mono_mb_emit_byte (mb, CEE_DUP);
2772 mono_mb_emit_byte (mb, CEE_STLOC_1);
2773 mono_mb_emit_byte (mb, CEE_STLOC_3);
2775 emit_struct_conv (mb, klass, FALSE);
2777 mono_mb_patch_addr (mb, pos2, mb->pos - (pos2 + 4));
2781 g_warning ("return type 0x%02x unknown", sig->ret->type);
2782 g_assert_not_reached ();
2785 mono_mb_emit_byte (mb, CEE_STLOC_3);
2788 /* Convert byref arguments back */
2789 for (i = 0; i < sig->param_count; i ++) {
2790 MonoType *t = sig->params [i];
2796 case MONO_TYPE_CLASS: {
2799 klass = t->data.klass;
2801 /* Check for null */
2802 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2803 pos = mono_mb_emit_branch (mb, CEE_BRTRUE);
2804 mono_mb_emit_ldarg (mb, i);
2805 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
2806 mono_mb_emit_byte (mb, CEE_STIND_I);
2807 pos2 = mono_mb_emit_branch (mb, CEE_BR);
2809 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2812 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2813 mono_mb_emit_icon (mb, sizeof (MonoObject));
2814 mono_mb_emit_byte (mb, CEE_ADD);
2815 mono_mb_emit_byte (mb, CEE_STLOC_0);
2817 /* Allocate and set dest */
2818 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2819 mono_mb_emit_byte (mb, CEE_CONV_I);
2820 mono_mb_emit_native_call (mb, alloc_sig, mono_marshal_alloc);
2821 emit_thread_interrupt_checkpoint (mb);
2822 mono_mb_emit_byte (mb, CEE_STLOC_1);
2824 /* Update argument pointer */
2825 mono_mb_emit_ldarg (mb, i);
2826 mono_mb_emit_byte (mb, CEE_LDLOC_1);
2827 mono_mb_emit_byte (mb, CEE_STIND_I);
2829 /* emit valuetype conversion code */
2830 emit_struct_conv (mb, klass, FALSE);
2832 mono_mb_patch_addr (mb, pos2, mb->pos - (pos2 + 4));
2835 case MONO_TYPE_VALUETYPE: {
2838 klass = t->data.klass;
2840 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2841 klass->blittable || klass->enumtype) {
2845 /* Check for null */
2846 mono_mb_emit_ldarg (mb, i);
2847 pos2 = mono_mb_emit_branch (mb, CEE_BRFALSE);
2850 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2851 mono_mb_emit_byte (mb, CEE_STLOC_0);
2854 mono_mb_emit_ldarg (mb, i);
2855 mono_mb_emit_byte (mb, CEE_STLOC_1);
2857 /* emit valuetype conversion code */
2858 emit_struct_conv (mb, klass, FALSE);
2860 mono_mb_patch_addr (mb, pos2, mb->pos - (pos2 + 4));
2867 mono_mb_emit_ldloc (mb, retobj_var);
2868 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2869 mono_mb_emit_byte (mb, CEE_MONO_RETOBJ);
2870 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2873 if (!MONO_TYPE_IS_VOID(sig->ret))
2874 mono_mb_emit_byte (mb, CEE_LDLOC_3);
2875 mono_mb_emit_byte (mb, CEE_RET);
2879 res = mono_mb_create_and_cache (cache, method,
2880 mb, csig, sig->param_count + 16);
2882 res = mono_mb_create_method (mb, csig, sig->param_count + 16);
2885 /* 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)); */
2891 * mono_marshal_get_ldfld_wrapper:
2892 * @type: the type of the field
2894 * This method generates a function which can be use to load a field with type
2895 * @type from an object. The generated function has the following signature:
2896 * <@type> ldfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset)
2899 mono_marshal_get_ldfld_wrapper (MonoType *type)
2901 MonoMethodSignature *sig, *csig;
2902 MonoMethodBuilder *mb;
2905 static GHashTable *ldfld_hash = NULL;
2907 int t, pos0, pos1 = 0;
2912 if (type->type == MONO_TYPE_SZARRAY) {
2913 klass = mono_defaults.array_class;
2914 } else if (type->type == MONO_TYPE_VALUETYPE) {
2915 klass = type->data.klass;
2916 if (klass->enumtype) {
2917 t = klass->enum_basetype->type;
2918 klass = mono_class_from_mono_type (klass->enum_basetype);
2920 } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
2921 t == MONO_TYPE_CLASS) {
2922 klass = mono_defaults.object_class;
2923 } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
2924 klass = mono_defaults.int_class;
2926 klass = mono_class_from_mono_type (type);
2929 klass = mono_defaults.int_class;
2932 EnterCriticalSection (&marshal_mutex);
2934 ldfld_hash = g_hash_table_new (NULL, NULL);
2935 res = g_hash_table_lookup (ldfld_hash, klass);
2936 LeaveCriticalSection (&marshal_mutex);
2940 name = g_strdup_printf ("__ldfld_wrapper_%s.%s", klass->name_space, klass->name);
2941 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_LDFLD);
2944 mb->method->save_lmf = 1;
2946 sig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
2947 sig->params [0] = &mono_defaults.object_class->byval_arg;
2948 sig->params [1] = &mono_defaults.int_class->byval_arg;
2949 sig->params [2] = &mono_defaults.int_class->byval_arg;
2950 sig->params [3] = &mono_defaults.int_class->byval_arg;
2951 sig->ret = &klass->byval_arg;
2953 mono_mb_emit_ldarg (mb, 0);
2954 pos0 = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
2956 mono_mb_emit_ldarg (mb, 0);
2957 mono_mb_emit_ldarg (mb, 1);
2958 mono_mb_emit_ldarg (mb, 2);
2960 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
2961 csig->params [0] = &mono_defaults.object_class->byval_arg;
2962 csig->params [1] = &mono_defaults.int_class->byval_arg;
2963 csig->params [2] = &mono_defaults.int_class->byval_arg;
2964 csig->ret = &klass->this_arg;
2967 mono_mb_emit_native_call (mb, csig, mono_load_remote_field_new);
2968 emit_thread_interrupt_checkpoint (mb);
2970 if (klass->valuetype) {
2971 mono_mb_emit_byte (mb, CEE_UNBOX);
2972 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2973 mono_mb_emit_byte (mb, CEE_BR);
2975 mono_mb_emit_i4 (mb, 0);
2977 mono_mb_emit_byte (mb, CEE_RET);
2981 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
2983 mono_mb_emit_ldarg (mb, 0);
2984 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2985 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2986 mono_mb_emit_ldarg (mb, 3);
2987 mono_mb_emit_byte (mb, CEE_ADD);
2989 if (klass->valuetype)
2990 mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
2995 case MONO_TYPE_BOOLEAN:
2996 mono_mb_emit_byte (mb, CEE_LDIND_I1);
2998 case MONO_TYPE_CHAR:
3001 mono_mb_emit_byte (mb, CEE_LDIND_I2);
3005 mono_mb_emit_byte (mb, CEE_LDIND_I4);
3009 mono_mb_emit_byte (mb, CEE_LDIND_I8);
3012 mono_mb_emit_byte (mb, CEE_LDIND_R4);
3015 mono_mb_emit_byte (mb, CEE_LDIND_R8);
3017 case MONO_TYPE_ARRAY:
3019 case MONO_TYPE_FNPTR:
3020 case MONO_TYPE_SZARRAY:
3021 case MONO_TYPE_OBJECT:
3022 case MONO_TYPE_CLASS:
3023 case MONO_TYPE_STRING:
3026 mono_mb_emit_byte (mb, CEE_LDIND_I);
3028 case MONO_TYPE_VALUETYPE:
3029 g_assert (!klass->enumtype);
3030 mono_mb_emit_byte (mb, CEE_LDOBJ);
3031 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3034 g_warning ("type %x not implemented", type->type);
3035 g_assert_not_reached ();
3038 mono_mb_emit_byte (mb, CEE_RET);
3040 res = mono_mb_create_and_cache (ldfld_hash, klass,
3041 mb, sig, sig->param_count + 16);
3048 * mono_marshal_get_stfld_wrapper:
3049 * @type: the type of the field
3051 * This method generates a function which can be use to store a field with type
3052 * @type. The generated function has the following signature:
3053 * void stfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset, <@type> val)
3056 mono_marshal_get_stfld_wrapper (MonoType *type)
3058 MonoMethodSignature *sig, *csig;
3059 MonoMethodBuilder *mb;
3062 static GHashTable *stfld_hash = NULL;
3069 if (type->type == MONO_TYPE_SZARRAY) {
3070 klass = mono_defaults.array_class;
3071 } else if (type->type == MONO_TYPE_VALUETYPE) {
3072 klass = type->data.klass;
3073 if (klass->enumtype) {
3074 t = klass->enum_basetype->type;
3075 klass = mono_class_from_mono_type (klass->enum_basetype);
3077 } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
3078 t == MONO_TYPE_CLASS) {
3079 klass = mono_defaults.object_class;
3080 } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
3081 klass = mono_defaults.int_class;
3083 klass = mono_class_from_mono_type (type);
3086 klass = mono_defaults.int_class;
3089 EnterCriticalSection (&marshal_mutex);
3091 stfld_hash = g_hash_table_new (NULL, NULL);
3092 res = g_hash_table_lookup (stfld_hash, klass);
3093 LeaveCriticalSection (&marshal_mutex);
3097 name = g_strdup_printf ("__stfld_wrapper_%s.%s", klass->name_space, klass->name);
3098 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_STFLD);
3101 mb->method->save_lmf = 1;
3103 sig = mono_metadata_signature_alloc (mono_defaults.corlib, 5);
3104 sig->params [0] = &mono_defaults.object_class->byval_arg;
3105 sig->params [1] = &mono_defaults.int_class->byval_arg;
3106 sig->params [2] = &mono_defaults.int_class->byval_arg;
3107 sig->params [3] = &mono_defaults.int_class->byval_arg;
3108 sig->params [4] = &klass->byval_arg;
3109 sig->ret = &mono_defaults.void_class->byval_arg;
3111 mono_mb_emit_ldarg (mb, 0);
3112 pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
3114 mono_mb_emit_ldarg (mb, 0);
3115 mono_mb_emit_ldarg (mb, 1);
3116 mono_mb_emit_ldarg (mb, 2);
3117 mono_mb_emit_ldarg (mb, 4);
3119 if (klass->valuetype) {
3120 mono_mb_emit_byte (mb, CEE_BOX);
3121 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3124 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
3125 csig->params [0] = &mono_defaults.object_class->byval_arg;
3126 csig->params [1] = &mono_defaults.int_class->byval_arg;
3127 csig->params [2] = &mono_defaults.int_class->byval_arg;
3128 csig->params [3] = &klass->this_arg;
3129 csig->ret = &mono_defaults.void_class->byval_arg;
3132 mono_mb_emit_native_call (mb, csig, mono_store_remote_field_new);
3133 emit_thread_interrupt_checkpoint (mb);
3135 mono_mb_emit_byte (mb, CEE_RET);
3137 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3139 mono_mb_emit_ldarg (mb, 0);
3140 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3141 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
3142 mono_mb_emit_ldarg (mb, 3);
3143 mono_mb_emit_byte (mb, CEE_ADD);
3144 mono_mb_emit_ldarg (mb, 4);
3149 case MONO_TYPE_BOOLEAN:
3150 mono_mb_emit_byte (mb, CEE_STIND_I1);
3152 case MONO_TYPE_CHAR:
3155 mono_mb_emit_byte (mb, CEE_STIND_I2);
3159 mono_mb_emit_byte (mb, CEE_STIND_I4);
3163 mono_mb_emit_byte (mb, CEE_STIND_I8);
3166 mono_mb_emit_byte (mb, CEE_STIND_R4);
3169 mono_mb_emit_byte (mb, CEE_STIND_R8);
3171 case MONO_TYPE_ARRAY:
3173 case MONO_TYPE_FNPTR:
3174 case MONO_TYPE_SZARRAY:
3175 case MONO_TYPE_OBJECT:
3176 case MONO_TYPE_CLASS:
3177 case MONO_TYPE_STRING:
3180 mono_mb_emit_byte (mb, CEE_STIND_I);
3182 case MONO_TYPE_VALUETYPE:
3183 g_assert (!klass->enumtype);
3184 mono_mb_emit_byte (mb, CEE_STOBJ);
3185 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3188 g_warning ("type %x not implemented", type->type);
3189 g_assert_not_reached ();
3192 mono_mb_emit_byte (mb, CEE_RET);
3194 res = mono_mb_create_and_cache (stfld_hash, klass,
3195 mb, sig, sig->param_count + 16);
3202 * generates IL code for the icall wrapper (the generated method
3203 * calls the unmanaged code in func)
3206 mono_marshal_get_icall_wrapper (MonoMethodSignature *sig, const char *name, gconstpointer func)
3208 MonoMethodSignature *csig;
3209 MonoMethodBuilder *mb;
3213 g_assert (sig->pinvoke);
3215 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_MANAGED_TO_NATIVE);
3217 mb->method->save_lmf = 1;
3219 /* we copy the signature, so that we can modify it */
3222 mono_mb_emit_byte (mb, CEE_LDARG_0);
3224 for (i = 0; i < sig->param_count; i++)
3225 mono_mb_emit_ldarg (mb, i + sig->hasthis);
3227 mono_mb_emit_native_call (mb, sig, (gpointer) func);
3228 emit_thread_interrupt_checkpoint (mb);
3229 mono_mb_emit_byte (mb, CEE_RET);
3231 csig = mono_metadata_signature_dup (sig);
3233 if (csig->call_convention == MONO_CALL_VARARG)
3234 csig->call_convention = 0;
3236 res = mono_mb_create_method (mb, csig, csig->param_count + 16);
3243 * mono_marshal_get_native_wrapper:
3244 * @method: The MonoMethod to wrap.
3246 * generates IL code for the pinvoke wrapper (the generated method
3247 * calls the unmanaged code in method->addr)
3250 mono_marshal_get_native_wrapper (MonoMethod *method)
3252 MonoMethodSignature *sig, *csig;
3253 MonoMethodPInvoke *piinfo;
3254 MonoMethodBuilder *mb;
3255 MonoMarshalSpec **mspecs;
3259 gboolean pinvoke = FALSE;
3260 int i, pos, argnum, *tmp_locals;
3262 const char *exc_class = "MissingMethodException";
3263 const char *exc_arg = NULL;
3265 g_assert (method != NULL);
3266 g_assert (method->signature->pinvoke);
3268 cache = method->klass->image->native_wrapper_cache;
3269 if ((res = mono_marshal_find_in_cache (cache, method)))
3272 sig = method->signature;
3274 if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
3275 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
3278 if (!method->addr) {
3280 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
3282 method->addr = mono_lookup_internal_call (method);
3285 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_MANAGED_TO_NATIVE);
3287 mb->method->save_lmf = 1;
3289 piinfo = (MonoMethodPInvoke *)method;
3291 if (!method->addr) {
3292 mono_mb_emit_exception (mb, exc_class, exc_arg);
3293 csig = mono_metadata_signature_dup (sig);
3295 res = mono_mb_create_and_cache (cache, method,
3296 mb, csig, csig->param_count + 16);
3301 /* internal calls: we simply push all arguments and call the method (no conversions) */
3302 if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
3304 /* hack - string constructors returns a value */
3305 if (method->string_ctor) {
3306 csig = mono_metadata_signature_dup (sig);
3307 csig->ret = &mono_defaults.string_class->byval_arg;
3312 mono_mb_emit_byte (mb, CEE_LDARG_0);
3314 for (i = 0; i < sig->param_count; i++)
3315 mono_mb_emit_ldarg (mb, i + sig->hasthis);
3317 g_assert (method->addr);
3318 mono_mb_emit_native_call (mb, csig, method->addr);
3319 emit_thread_interrupt_checkpoint (mb);
3320 mono_mb_emit_byte (mb, CEE_RET);
3322 csig = mono_metadata_signature_dup (csig);
3324 res = mono_mb_create_and_cache (cache, method,
3325 mb, csig, csig->param_count + 16);
3332 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
3333 mono_method_get_marshal_info (method, mspecs);
3335 /* pinvoke: we need to convert the arguments if necessary */
3337 /* we copy the signature, so that we can set pinvoke to 0 */
3338 csig = mono_metadata_signature_dup (sig);
3341 /* we allocate local for use with emit_struct_conv() */
3342 /* allocate local 0 (pointer) src_ptr */
3343 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3344 /* allocate local 1 (pointer) dst_ptr */
3345 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3346 /* allocate local 2 (boolean) delete_old */
3347 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
3349 /* delete_old = FALSE */
3350 mono_mb_emit_icon (mb, 0);
3351 mono_mb_emit_byte (mb, CEE_STLOC_2);
3353 if (!MONO_TYPE_IS_VOID(sig->ret)) {
3354 /* allocate local 3 to store the return value */
3355 mono_mb_add_local (mb, sig->ret);
3358 if (mspecs [0] && mspecs [0]->native == MONO_NATIVE_CUSTOM) {
3359 /* Return type custom marshaling */
3361 * Since we can't determine the return type of the unmanaged function,
3362 * we assume it returns a pointer, and pass that pointer to
3363 * MarshalNativeToManaged.
3365 csig->ret = &mono_defaults.int_class->byval_arg;
3368 /* we first do all conversions */
3369 tmp_locals = alloca (sizeof (int) * sig->param_count);
3371 for (i = 0; i < sig->param_count; i ++) {
3372 MonoType *t = sig->params [i];
3373 MonoMarshalSpec *spec = mspecs [i + 1];
3375 argnum = i + sig->hasthis;
3378 /* Ensure that we have marshalling info for this param */
3379 mono_marshal_load_type_info (mono_class_from_mono_type (t));
3381 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
3384 MonoMethod *marshal_managed_to_native;
3385 MonoMethod *get_instance;
3387 /* FIXME: Call CleanUpNativeData after the call */
3389 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
3390 g_assert (mtype != NULL);
3391 mklass = mono_class_from_mono_type (mtype);
3392 g_assert (mklass != NULL);
3394 marshal_managed_to_native = mono_find_method_by_name (mklass, "MarshalManagedToNative", 1);
3395 g_assert (marshal_managed_to_native);
3396 get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
3397 g_assert (get_instance);
3400 case MONO_TYPE_CLASS:
3401 case MONO_TYPE_OBJECT:
3402 case MONO_TYPE_STRING:
3403 case MONO_TYPE_ARRAY:
3404 case MONO_TYPE_SZARRAY:
3405 case MONO_TYPE_VALUETYPE:
3409 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3411 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
3413 mono_mb_emit_byte (mb, CEE_CALL);
3414 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
3416 mono_mb_emit_ldarg (mb, argnum);
3418 if (t->type == MONO_TYPE_VALUETYPE) {
3420 * Since we can't determine the type of the argument, we
3421 * will assume the unmanaged function takes a pointer.
3423 csig->params [i] = &mono_defaults.int_class->byval_arg;
3425 mono_mb_emit_byte (mb, CEE_BOX);
3426 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (t)));
3429 mono_mb_emit_byte (mb, CEE_CALLVIRT);
3430 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_managed_to_native));
3432 mono_mb_emit_stloc (mb, tmp_locals [i]);
3436 g_warning ("custom marshalling of type %x is currently not supported", t->type);
3437 g_assert_not_reached ();
3443 if (spec && spec->native == MONO_NATIVE_ASANY) {
3444 MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, NULL);
3446 g_assert (t->type == MONO_TYPE_OBJECT);
3447 g_assert (!t->byref);
3449 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3450 mono_mb_emit_ldarg (mb, argnum);
3451 mono_mb_emit_icon (mb, encoding);
3452 mono_mb_emit_icall (mb, mono_marshal_asany);
3453 mono_mb_emit_stloc (mb, tmp_locals [i]);
3458 case MONO_TYPE_VALUETYPE:
3459 klass = t->data.klass;
3461 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3462 klass->blittable || klass->enumtype)
3465 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3467 /* store the address of the source into local variable 0 */
3469 mono_mb_emit_ldarg (mb, argnum);
3471 mono_mb_emit_ldarg_addr (mb, argnum);
3473 mono_mb_emit_byte (mb, CEE_STLOC_0);
3475 /* allocate space for the native struct and
3476 * store the address into local variable 1 (dest) */
3477 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
3478 mono_mb_emit_byte (mb, CEE_PREFIX1);
3479 mono_mb_emit_byte (mb, CEE_LOCALLOC);
3480 mono_mb_emit_stloc (mb, tmp_locals [i]);
3483 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3484 mono_mb_emit_byte (mb, CEE_BRFALSE);
3486 mono_mb_emit_i4 (mb, 0);
3490 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3491 mono_mb_emit_byte (mb, CEE_STLOC_1);
3493 /* emit valuetype conversion code */
3494 emit_struct_conv (mb, klass, FALSE);
3497 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3499 case MONO_TYPE_STRING: {
3500 MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, spec);
3502 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3503 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3506 if (t->attrs & PARAM_ATTRIBUTE_OUT)
3509 mono_mb_emit_ldarg (mb, argnum);
3510 mono_mb_emit_byte (mb, CEE_LDIND_I);
3512 mono_mb_emit_ldarg (mb, argnum);
3516 case MONO_NATIVE_LPWSTR:
3517 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_STR_LPWSTR));
3519 case MONO_NATIVE_LPSTR:
3520 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_STR_LPSTR));
3522 case MONO_NATIVE_LPTSTR:
3523 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_STR_LPTSTR));
3526 char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding);
3527 MonoException *exc = mono_get_exception_not_implemented (msg);
3530 mono_raise_exception (exc);
3534 mono_mb_emit_stloc (mb, tmp_locals [i]);
3537 case MONO_TYPE_CLASS:
3538 case MONO_TYPE_OBJECT:
3539 klass = t->data.klass;
3541 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3542 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3544 if (klass->delegate) {
3545 g_assert (!t->byref);
3546 mono_mb_emit_ldarg (mb, argnum);
3547 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN));
3548 mono_mb_emit_stloc (mb, tmp_locals [i]);
3549 } else if (klass == mono_defaults.stringbuilder_class) {
3550 MonoMarshalNative encoding = mono_marshal_get_stringbuilder_to_ptr_encoding (piinfo, spec);
3552 g_assert (!t->byref);
3553 mono_mb_emit_ldarg (mb, argnum);
3556 mono_mb_emit_icall (mb, conv_to_icall (encoding));
3558 char *msg = g_strdup_printf ("stringbuilder marshalling conversion %d not implemented", encoding);
3559 MonoException *exc = mono_get_exception_not_implemented (msg);
3562 mono_raise_exception (exc);
3565 mono_mb_emit_stloc (mb, tmp_locals [i]);
3567 mono_mb_emit_byte (mb, CEE_LDNULL);
3568 mono_mb_emit_stloc (mb, tmp_locals [i]);
3571 /* we dont need any conversions for out parameters */
3572 if (t->attrs & PARAM_ATTRIBUTE_OUT)
3575 mono_mb_emit_ldarg (mb, argnum);
3576 mono_mb_emit_byte (mb, CEE_LDIND_I);
3579 mono_mb_emit_ldarg (mb, argnum);
3580 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3581 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
3584 /* store the address of the source into local variable 0 */
3585 mono_mb_emit_byte (mb, CEE_STLOC_0);
3586 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3587 mono_mb_emit_byte (mb, CEE_BRFALSE);
3589 mono_mb_emit_i4 (mb, 0);
3591 /* allocate space for the native struct and store the address */
3592 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
3593 mono_mb_emit_byte (mb, CEE_PREFIX1);
3594 mono_mb_emit_byte (mb, CEE_LOCALLOC);
3595 mono_mb_emit_stloc (mb, tmp_locals [i]);
3597 /* set the src_ptr */
3598 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3599 mono_mb_emit_icon (mb, sizeof (MonoObject));
3600 mono_mb_emit_byte (mb, CEE_ADD);
3601 mono_mb_emit_byte (mb, CEE_STLOC_0);
3604 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3605 mono_mb_emit_byte (mb, CEE_STLOC_1);
3607 /* emit valuetype conversion code */
3608 emit_struct_conv (mb, klass, FALSE);
3610 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3614 case MONO_TYPE_ARRAY:
3615 case MONO_TYPE_SZARRAY:
3619 klass = mono_class_from_mono_type (t);
3621 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3622 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3624 if (klass->element_class == mono_defaults.string_class) {
3625 MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, spec);
3627 mono_mb_emit_ldarg (mb, argnum);
3630 case MONO_NATIVE_LPSTR:
3631 mono_mb_emit_icall (mb, mono_marshal_string_array);
3633 case MONO_NATIVE_LPWSTR:
3634 mono_mb_emit_icall (mb, mono_marshal_string_array_to_unicode);
3637 char *msg = g_strdup_printf ("string array marshalling conversion %d not implemented", encoding);
3638 MonoException *exc = mono_get_exception_not_implemented (msg);
3641 mono_raise_exception (exc);
3644 mono_mb_emit_stloc (mb, tmp_locals [i]);
3646 else if (klass->element_class->blittable) {
3647 mono_mb_emit_ldarg (mb, argnum);
3648 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_ARRAY_LPARRAY));
3649 mono_mb_emit_stloc (mb, tmp_locals [i]);
3653 guint32 label1, label2, label3;
3654 int index_var, dest_ptr, esize;
3655 MonoMarshalNative encoding = mono_marshal_get_stringbuilder_to_ptr_encoding (piinfo, spec);
3657 dest_ptr = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3659 eklass = klass->element_class;
3662 mono_mb_emit_ldarg (mb, argnum);
3663 mono_mb_emit_stloc (mb, tmp_locals [i]);
3664 mono_mb_emit_ldarg (mb, argnum);
3665 mono_mb_emit_byte (mb, CEE_BRFALSE);
3667 mono_mb_emit_i4 (mb, 0);
3669 if (eklass == mono_defaults.stringbuilder_class) {
3670 if (encoding == -1) {
3671 char *msg = g_strdup_printf ("stringbuilder marshalling conversion %d not implemented", encoding);
3672 MonoException *exc = mono_get_exception_not_implemented (msg);
3675 mono_raise_exception (exc);
3679 if (eklass == mono_defaults.stringbuilder_class)
3680 esize = sizeof (gpointer);
3682 esize = mono_class_native_size (eklass, NULL);
3684 /* allocate space for the native struct and store the address */
3685 mono_mb_emit_icon (mb, esize);
3686 mono_mb_emit_ldarg (mb, argnum);
3687 mono_mb_emit_byte (mb, CEE_LDLEN);
3688 mono_mb_emit_byte (mb, CEE_MUL);
3689 mono_mb_emit_byte (mb, CEE_PREFIX1);
3690 mono_mb_emit_byte (mb, CEE_LOCALLOC);
3691 mono_mb_emit_stloc (mb, tmp_locals [i]);
3693 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3694 mono_mb_emit_stloc (mb, dest_ptr);
3696 /* Emit marshalling loop */
3697 index_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3698 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
3699 mono_mb_emit_stloc (mb, index_var);
3701 mono_mb_emit_ldloc (mb, index_var);
3702 mono_mb_emit_ldarg (mb, argnum);
3703 mono_mb_emit_byte (mb, CEE_LDLEN);
3704 mono_mb_emit_byte (mb, CEE_BGE);
3706 mono_mb_emit_i4 (mb, 0);
3708 /* Emit marshalling code */
3710 if (eklass == mono_defaults.stringbuilder_class) {
3711 mono_mb_emit_ldloc (mb, dest_ptr);
3712 mono_mb_emit_ldarg (mb, argnum);
3713 mono_mb_emit_ldloc (mb, index_var);
3714 mono_mb_emit_byte (mb, CEE_LDELEM_REF);
3715 mono_mb_emit_icall (mb, conv_to_icall (encoding));
3716 mono_mb_emit_byte (mb, CEE_STIND_I);
3719 /* set the src_ptr */
3720 mono_mb_emit_ldarg (mb, argnum);
3721 mono_mb_emit_ldloc (mb, index_var);
3722 mono_mb_emit_byte (mb, CEE_LDELEMA);
3723 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eklass));
3724 mono_mb_emit_byte (mb, CEE_STLOC_0);
3727 mono_mb_emit_ldloc (mb, dest_ptr);
3728 mono_mb_emit_byte (mb, CEE_STLOC_1);
3730 /* emit valuetype conversion code */
3731 emit_struct_conv (mb, eklass, FALSE);
3734 mono_mb_emit_add_to_local (mb, index_var, 1);
3735 mono_mb_emit_add_to_local (mb, dest_ptr, esize);
3737 mono_mb_emit_byte (mb, CEE_BR);
3738 mono_mb_emit_i4 (mb, label2 - (mb->pos + 4));
3740 mono_mb_patch_addr (mb, label1, mb->pos - (label1 + 4));
3741 mono_mb_patch_addr (mb, label3, mb->pos - (label3 + 4));
3745 case MONO_TYPE_BOOLEAN: {
3746 MonoType *local_type;
3747 int variant_bool = 0;
3751 local_type = &mono_defaults.int32_class->byval_arg;
3753 switch (spec->native) {
3754 case MONO_NATIVE_I1:
3755 local_type = &mono_defaults.byte_class->byval_arg;
3757 case MONO_NATIVE_VARIANTBOOL:
3758 local_type = &mono_defaults.int16_class->byval_arg;
3762 g_warning ("marshalling bool as native type %x is currently not supported", spec->native);
3766 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3767 tmp_locals [i] = mono_mb_add_local (mb, local_type);
3768 mono_mb_emit_ldarg (mb, argnum);
3769 mono_mb_emit_byte (mb, CEE_LDIND_I1);
3771 mono_mb_emit_byte (mb, CEE_NEG);
3772 mono_mb_emit_stloc (mb, tmp_locals [i]);
3778 /* push all arguments */
3781 mono_mb_emit_byte (mb, CEE_LDARG_0);
3783 for (i = 0; i < sig->param_count; i++) {
3784 MonoType *t = sig->params [i];
3785 MonoMarshalSpec *spec = mspecs [i + 1];
3787 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
3788 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3791 if (spec && spec->native == MONO_NATIVE_ASANY) {
3792 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3795 argnum = i + sig->hasthis;
3798 case MONO_TYPE_BOOLEAN:
3800 g_assert (tmp_locals [i]);
3801 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
3803 mono_mb_emit_ldarg (mb, argnum);
3818 mono_mb_emit_ldarg (mb, argnum);
3820 case MONO_TYPE_VALUETYPE:
3821 klass = sig->params [i]->data.klass;
3822 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3823 klass->blittable || klass->enumtype) {
3824 mono_mb_emit_ldarg (mb, argnum);
3827 g_assert (tmp_locals [i]);
3828 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3830 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3831 mono_mb_emit_byte (mb, CEE_MONO_LDNATIVEOBJ);
3832 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3835 case MONO_TYPE_STRING:
3836 case MONO_TYPE_CLASS:
3837 case MONO_TYPE_OBJECT:
3838 g_assert (tmp_locals [i]);
3840 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
3842 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3844 case MONO_TYPE_CHAR:
3845 /* fixme: dont know how to marshal that. We cant simply
3846 * convert it to a one byte UTF8 character, because an
3847 * unicode character may need more that one byte in UTF8 */
3848 mono_mb_emit_ldarg (mb, argnum);
3850 case MONO_TYPE_ARRAY:
3851 case MONO_TYPE_SZARRAY:
3853 mono_mb_emit_ldarg (mb, argnum);
3855 g_assert (tmp_locals [i]);
3856 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3859 case MONO_TYPE_TYPEDBYREF:
3860 case MONO_TYPE_FNPTR:
3862 g_warning ("type 0x%02x unknown", t->type);
3863 g_assert_not_reached ();
3868 /* call the native method */
3869 mono_mb_emit_native_call (mb, csig, method->addr);
3871 /* Set LastError if needed */
3872 if (piinfo->piflags & PINVOKE_ATTRIBUTE_SUPPORTS_LAST_ERROR) {
3873 MonoMethodSignature *lasterr_sig;
3875 lasterr_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
3876 lasterr_sig->ret = &mono_defaults.void_class->byval_arg;
3877 lasterr_sig->pinvoke = 1;
3879 mono_mb_emit_native_call (mb, lasterr_sig, mono_marshal_set_last_error);
3882 /* Ensure that we have marshalling info for the return */
3883 mono_marshal_load_type_info (mono_class_from_mono_type (sig->ret));
3885 /* convert the result */
3886 if (!sig->ret->byref) {
3887 MonoMarshalSpec *spec = mspecs [0];
3888 type = sig->ret->type;
3890 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
3893 MonoMethod *marshal_native_to_managed;
3894 MonoMethod *get_instance;
3896 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
3897 g_assert (mtype != NULL);
3898 mklass = mono_class_from_mono_type (mtype);
3899 g_assert (mklass != NULL);
3901 marshal_native_to_managed = mono_find_method_by_name (mklass, "MarshalNativeToManaged", 1);
3902 g_assert (marshal_native_to_managed);
3903 get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
3904 g_assert (get_instance);
3907 case MONO_TYPE_CLASS:
3908 case MONO_TYPE_OBJECT:
3909 case MONO_TYPE_STRING:
3910 case MONO_TYPE_ARRAY:
3911 case MONO_TYPE_SZARRAY:
3912 case MONO_TYPE_VALUETYPE:
3913 if (type == MONO_TYPE_VALUETYPE) {
3914 /* local 3 can't hold a pointer */
3915 mono_mb_emit_byte (mb, CEE_STLOC_0);
3918 mono_mb_emit_byte (mb, CEE_STLOC_3);
3920 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
3922 mono_mb_emit_byte (mb, CEE_CALL);
3923 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
3925 if (type == MONO_TYPE_VALUETYPE)
3926 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3928 mono_mb_emit_byte (mb, CEE_LDLOC_3);
3930 mono_mb_emit_byte (mb, CEE_CALLVIRT);
3931 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_native_to_managed));
3933 if (type == MONO_TYPE_VALUETYPE) {
3934 mono_mb_emit_byte (mb, CEE_UNBOX);
3935 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (sig->ret)));
3937 mono_mb_emit_byte (mb, CEE_STLOC_3);
3940 g_warning ("custom marshalling of type %x is currently not supported", type);
3941 g_assert_not_reached ();
3948 case MONO_TYPE_VOID:
3963 /* no conversions necessary */
3964 mono_mb_emit_byte (mb, CEE_STLOC_3);
3966 case MONO_TYPE_BOOLEAN:
3967 /* maybe we need to make sure that it fits within 8 bits */
3968 mono_mb_emit_byte (mb, CEE_STLOC_3);
3970 case MONO_TYPE_VALUETYPE:
3971 klass = sig->ret->data.klass;
3972 if (klass->enumtype) {
3973 type = sig->ret->data.klass->enum_basetype->type;
3977 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3979 mono_mb_emit_byte (mb, CEE_STLOC_3);
3982 /* load pointer to returned value type */
3983 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3984 mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
3985 /* store the address of the source into local variable 0 */
3986 mono_mb_emit_byte (mb, CEE_STLOC_0);
3988 mono_mb_emit_ldloc_addr (mb, 3);
3989 mono_mb_emit_byte (mb, CEE_STLOC_1);
3991 /* emit valuetype conversion code */
3992 emit_struct_conv (mb, sig->ret->data.klass, TRUE);
3994 case MONO_TYPE_STRING:
3995 mono_mb_emit_byte (mb, CEE_STLOC_0);
3996 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3999 switch (spec->native) {
4000 case MONO_NATIVE_LPWSTR:
4001 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_LPWSTR_STR));
4004 g_warning ("marshalling conversion not implemented");
4005 g_assert_not_reached ();
4008 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_LPSTR_STR));
4010 mono_mb_emit_byte (mb, CEE_STLOC_3);
4012 /* free the string */
4013 mono_mb_emit_byte (mb, CEE_LDLOC_0);
4014 mono_mb_emit_icall (mb, g_free);
4016 case MONO_TYPE_CLASS:
4017 case MONO_TYPE_OBJECT:
4018 klass = sig->ret->data.klass;
4021 mono_mb_emit_byte (mb, CEE_STLOC_0);
4023 mono_mb_emit_byte (mb, CEE_LDNULL);
4024 mono_mb_emit_byte (mb, CEE_STLOC_3);
4027 mono_mb_emit_byte (mb, CEE_LDLOC_0);
4028 mono_mb_emit_byte (mb, CEE_BRFALSE);
4030 mono_mb_emit_i4 (mb, 0);
4032 /* allocate result object */
4034 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4035 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
4036 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
4037 mono_mb_emit_byte (mb, CEE_STLOC_3);
4041 mono_mb_emit_byte (mb, CEE_LDLOC_3);
4042 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4043 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
4044 mono_mb_emit_icon (mb, sizeof (MonoObject));
4045 mono_mb_emit_byte (mb, CEE_ADD);
4046 mono_mb_emit_byte (mb, CEE_STLOC_1);
4048 /* emit conversion code */
4049 emit_struct_conv (mb, klass, TRUE);
4051 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
4053 case MONO_TYPE_ARRAY:
4054 case MONO_TYPE_SZARRAY:
4055 /* fixme: we need conversions here */
4056 mono_mb_emit_byte (mb, CEE_STLOC_3);
4058 case MONO_TYPE_CHAR:
4059 /* fixme: we need conversions here */
4060 mono_mb_emit_byte (mb, CEE_STLOC_3);
4062 case MONO_TYPE_TYPEDBYREF:
4063 case MONO_TYPE_FNPTR:
4065 g_warning ("return type 0x%02x unknown", sig->ret->type);
4066 g_assert_not_reached ();
4070 mono_mb_emit_byte (mb, CEE_STLOC_3);
4074 * Need to call this after converting the result since MONO_VTADDR needs
4075 * to be adjacent to the call instruction.
4077 emit_thread_interrupt_checkpoint (mb);
4079 /* we need to convert byref arguments back and free string arrays */
4080 for (i = 0; i < sig->param_count; i++) {
4081 MonoType *t = sig->params [i];
4082 MonoMarshalSpec *spec = mspecs [i + 1];
4084 argnum = i + sig->hasthis;
4086 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
4089 MonoMethod *get_instance;
4090 MonoMethod *cleanup_native;
4092 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
4093 g_assert (mtype != NULL);
4094 mklass = mono_class_from_mono_type (mtype);
4095 g_assert (mklass != NULL);
4097 get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
4098 g_assert (get_instance);
4099 cleanup_native = mono_find_method_by_name (mklass, "CleanUpNativeData", 1);
4100 g_assert (get_instance);
4103 case MONO_TYPE_CLASS:
4104 case MONO_TYPE_OBJECT:
4105 case MONO_TYPE_STRING:
4106 case MONO_TYPE_ARRAY:
4107 case MONO_TYPE_SZARRAY:
4108 case MONO_TYPE_VALUETYPE:
4109 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
4111 mono_mb_emit_byte (mb, CEE_CALL);
4112 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
4114 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4116 mono_mb_emit_byte (mb, CEE_CALLVIRT);
4117 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, cleanup_native));
4122 g_warning ("custom marshalling of type %x is currently not supported", t->type);
4123 g_assert_not_reached ();
4129 if (spec && spec->native == MONO_NATIVE_ASANY) {
4130 MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, NULL);
4132 mono_mb_emit_ldarg (mb, argnum);
4133 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4134 mono_mb_emit_icon (mb, encoding);
4135 mono_mb_emit_icall (mb, mono_marshal_free_asany);
4140 case MONO_TYPE_STRING:
4141 if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT)) {
4142 mono_mb_emit_ldarg (mb, argnum);
4143 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4144 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_LPSTR_STR));
4145 mono_mb_emit_byte (mb, CEE_STIND_I);
4147 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4148 mono_mb_emit_icall (mb, g_free);
4151 case MONO_TYPE_CLASS:
4152 case MONO_TYPE_OBJECT:
4153 if (t->data.klass == mono_defaults.stringbuilder_class) {
4155 MonoMarshalNative encoding;
4157 encoding = mono_marshal_get_ptr_to_stringbuilder_encoding (piinfo, spec, &need_free);
4159 g_assert (!t->byref);
4160 g_assert (encoding != -1);
4162 mono_mb_emit_ldarg (mb, argnum);
4163 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4165 mono_mb_emit_icall (mb, conv_to_icall (encoding));
4168 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4169 mono_mb_emit_icall (mb, g_free);
4174 if (!(t->byref || (t->attrs & PARAM_ATTRIBUTE_OUT)))
4177 if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT)) {
4178 /* allocate a new object new object */
4179 mono_mb_emit_ldarg (mb, argnum);
4180 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4181 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
4182 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
4183 mono_mb_emit_byte (mb, CEE_STIND_I);
4186 /* dst = *argument */
4187 mono_mb_emit_ldarg (mb, argnum);
4190 mono_mb_emit_byte (mb, CEE_LDIND_I);
4192 mono_mb_emit_byte (mb, CEE_STLOC_1);
4194 mono_mb_emit_byte (mb, CEE_LDLOC_1);
4195 mono_mb_emit_byte (mb, CEE_BRFALSE);
4197 mono_mb_emit_i4 (mb, 0);
4199 mono_mb_emit_byte (mb, CEE_LDLOC_1);
4200 mono_mb_emit_icon (mb, sizeof (MonoObject));
4201 mono_mb_emit_byte (mb, CEE_ADD);
4202 mono_mb_emit_byte (mb, CEE_STLOC_1);
4204 /* src = tmp_locals [i] */
4205 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4206 mono_mb_emit_byte (mb, CEE_STLOC_0);
4208 /* emit valuetype conversion code */
4209 emit_struct_conv (mb, klass, TRUE);
4211 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
4213 case MONO_TYPE_VALUETYPE:
4217 klass = t->data.klass;
4218 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
4219 klass->blittable || klass->enumtype)
4222 /* dst = argument */
4223 mono_mb_emit_ldarg (mb, argnum);
4224 mono_mb_emit_byte (mb, CEE_STLOC_1);
4226 mono_mb_emit_byte (mb, CEE_LDLOC_1);
4227 mono_mb_emit_byte (mb, CEE_BRFALSE);
4229 mono_mb_emit_i4 (mb, 0);
4231 /* src = tmp_locals [i] */
4232 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4233 mono_mb_emit_byte (mb, CEE_STLOC_0);
4235 /* emit valuetype conversion code */
4236 emit_struct_conv (mb, klass, TRUE);
4238 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
4240 case MONO_TYPE_SZARRAY:
4244 klass = mono_class_from_mono_type (t);
4246 if (klass->element_class == mono_defaults.string_class) {
4247 MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, spec);
4248 g_assert (tmp_locals [i]);
4250 mono_mb_emit_ldarg (mb, argnum);
4251 mono_mb_emit_byte (mb, CEE_BRFALSE);
4253 mono_mb_emit_i4 (mb, 0);
4255 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4258 case MONO_NATIVE_LPWSTR:
4260 * The array elements point to the managed string data so
4261 * they don't need to be freed.
4263 mono_mb_emit_icall (mb, g_free);
4266 mono_mb_emit_ldarg (mb, argnum);
4267 mono_mb_emit_byte (mb, CEE_LDLEN);
4268 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_FREE_ARRAY));
4272 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
4275 /* Character arrays are implicitly marshalled as [Out] */
4276 if ((klass->element_class == mono_defaults.char_class) || (klass->element_class == mono_defaults.stringbuilder_class) || (t->attrs & PARAM_ATTRIBUTE_OUT)) {
4277 /* FIXME: Optimize blittable case */
4279 guint32 label1, label2, label3;
4280 int index_var, src_ptr, esize;
4282 eklass = klass->element_class;
4283 if (eklass == mono_defaults.stringbuilder_class)
4284 esize = sizeof (gpointer);
4286 esize = mono_class_native_size (eklass, NULL);
4287 src_ptr = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
4290 mono_mb_emit_ldarg (mb, argnum);
4291 mono_mb_emit_byte (mb, CEE_BRFALSE);
4293 mono_mb_emit_i4 (mb, 0);
4295 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4296 mono_mb_emit_stloc (mb, src_ptr);
4298 /* Emit marshalling loop */
4299 index_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
4300 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
4301 mono_mb_emit_stloc (mb, index_var);
4303 mono_mb_emit_ldloc (mb, index_var);
4304 mono_mb_emit_ldarg (mb, argnum);
4305 mono_mb_emit_byte (mb, CEE_LDLEN);
4306 mono_mb_emit_byte (mb, CEE_BGE);
4308 mono_mb_emit_i4 (mb, 0);
4310 /* Emit marshalling code */
4312 if (eklass == mono_defaults.stringbuilder_class) {
4314 MonoMarshalNative encoding = mono_marshal_get_ptr_to_stringbuilder_encoding (piinfo, spec, &need_free);
4316 g_assert (encoding != -1);
4319 mono_mb_emit_ldarg (mb, argnum);
4320 mono_mb_emit_ldloc (mb, index_var);
4321 mono_mb_emit_byte (mb, CEE_LDELEM_REF);
4324 mono_mb_emit_ldloc (mb, src_ptr);
4325 mono_mb_emit_byte (mb, CEE_LDIND_I);
4327 mono_mb_emit_icall (mb, conv_to_icall (encoding));
4331 mono_mb_emit_ldloc (mb, src_ptr);
4332 mono_mb_emit_byte (mb, CEE_LDIND_I);
4334 mono_mb_emit_icall (mb, g_free);
4338 /* set the src_ptr */
4339 mono_mb_emit_ldloc (mb, src_ptr);
4340 mono_mb_emit_byte (mb, CEE_STLOC_0);
4343 mono_mb_emit_ldarg (mb, argnum);
4344 mono_mb_emit_ldloc (mb, index_var);
4345 mono_mb_emit_byte (mb, CEE_LDELEMA);
4346 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eklass));
4347 mono_mb_emit_byte (mb, CEE_STLOC_1);
4349 /* emit valuetype conversion code */
4350 emit_struct_conv (mb, eklass, TRUE);
4353 mono_mb_emit_add_to_local (mb, index_var, 1);
4354 mono_mb_emit_add_to_local (mb, src_ptr, esize);
4356 mono_mb_emit_byte (mb, CEE_BR);
4357 mono_mb_emit_i4 (mb, label2 - (mb->pos + 4));
4359 mono_mb_patch_addr (mb, label1, mb->pos - (label1 + 4));
4360 mono_mb_patch_addr (mb, label3, mb->pos - (label3 + 4));
4363 case MONO_TYPE_BOOLEAN:
4366 mono_mb_emit_ldarg (mb, argnum);
4367 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4368 if (mspecs [i + 1] != NULL && mspecs [i + 1]->native == MONO_NATIVE_VARIANTBOOL)
4369 mono_mb_emit_byte (mb, CEE_NEG);
4370 mono_mb_emit_byte (mb, CEE_STIND_I1);
4374 if (!MONO_TYPE_IS_VOID(sig->ret))
4375 mono_mb_emit_byte (mb, CEE_LDLOC_3);
4377 mono_mb_emit_byte (mb, CEE_RET);
4379 csig = mono_metadata_signature_dup (sig);
4381 res = mono_mb_create_and_cache (cache, method,
4382 mb, csig, csig->param_count + 16);
4385 for (i = sig->param_count; i >= 0; i--)
4386 g_free (mspecs [i]);
4389 /* 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)); */
4395 mono_upgrade_remote_class_wrapper (MonoReflectionType *rtype, MonoTransparentProxy *tproxy);
4397 static MonoReflectionType *
4398 type_from_handle (MonoType *handle)
4400 MonoDomain *domain = mono_domain_get ();
4401 MonoClass *klass = mono_class_from_mono_type (handle);
4403 MONO_ARCH_SAVE_REGS;
4405 mono_class_init (klass);
4406 return mono_type_get_object (domain, handle);
4410 * mono_marshal_get_isinst:
4411 * @klass: the type of the field
4413 * This method generates a function which can be used to check if an object is
4414 * an instance of the given type, icluding the case where the object is a proxy.
4415 * The generated function has the following signature:
4416 * MonoObject* __isinst_wrapper_ (MonoObject *obj)
4419 mono_marshal_get_isinst (MonoClass *klass)
4421 static MonoMethodSignature *isint_sig = NULL;
4422 static GHashTable *isinst_hash = NULL;
4424 int pos_was_ok, pos_failed, pos_end, pos_end2;
4426 MonoMethodBuilder *mb;
4428 EnterCriticalSection (&marshal_mutex);
4430 isinst_hash = g_hash_table_new (NULL, NULL);
4432 res = g_hash_table_lookup (isinst_hash, klass);
4433 LeaveCriticalSection (&marshal_mutex);
4438 isint_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
4439 isint_sig->params [0] = &mono_defaults.object_class->byval_arg;
4440 isint_sig->ret = &mono_defaults.object_class->byval_arg;
4441 isint_sig->pinvoke = 0;
4444 name = g_strdup_printf ("__isinst_wrapper_%s", klass->name);
4445 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_ISINST);
4448 mb->method->save_lmf = 1;
4450 /* check if the object is a proxy that needs special cast */
4451 mono_mb_emit_ldarg (mb, 0);
4452 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4453 mono_mb_emit_byte (mb, CEE_MONO_CISINST);
4454 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
4456 /* The result of MONO_ISINST can be:
4457 0) the type check succeeded
4458 1) the type check did not succeed
4459 2) a CanCastTo call is needed */
4461 mono_mb_emit_byte (mb, CEE_DUP);
4462 pos_was_ok = mono_mb_emit_branch (mb, CEE_BRFALSE);
4464 mono_mb_emit_byte (mb, CEE_LDC_I4_2);
4465 pos_failed = mono_mb_emit_branch (mb, CEE_BNE_UN);
4467 /* get the real proxy from the transparent proxy*/
4469 mono_mb_emit_ldarg (mb, 0);
4470 mono_mb_emit_managed_call (mb, mono_marshal_get_proxy_cancast (klass), NULL);
4471 pos_end = mono_mb_emit_branch (mb, CEE_BR);
4475 mono_mb_patch_addr (mb, pos_failed, mb->pos - (pos_failed + 4));
4476 mono_mb_emit_byte (mb, CEE_LDNULL);
4477 pos_end2 = mono_mb_emit_branch (mb, CEE_BR);
4481 mono_mb_patch_addr (mb, pos_was_ok, mb->pos - (pos_was_ok + 4));
4482 mono_mb_emit_byte (mb, CEE_POP);
4483 mono_mb_emit_ldarg (mb, 0);
4487 mono_mb_patch_addr (mb, pos_end, mb->pos - (pos_end + 4));
4488 mono_mb_patch_addr (mb, pos_end2, mb->pos - (pos_end2 + 4));
4489 mono_mb_emit_byte (mb, CEE_RET);
4491 res = mono_mb_create_and_cache (isinst_hash, klass, mb, isint_sig, isint_sig->param_count + 16);
4498 * mono_marshal_get_castclass:
4499 * @klass: the type of the field
4501 * This method generates a function which can be used to cast an object to
4502 * an instance of the given type, icluding the case where the object is a proxy.
4503 * The generated function has the following signature:
4504 * MonoObject* __castclass_wrapper_ (MonoObject *obj)
4507 mono_marshal_get_castclass (MonoClass *klass)
4509 static MonoMethodSignature *castclass_sig = NULL;
4510 static GHashTable *castclass_hash = NULL;
4512 int pos_was_ok, pos_was_ok2;
4514 MonoMethodBuilder *mb;
4516 EnterCriticalSection (&marshal_mutex);
4517 if (!castclass_hash)
4518 castclass_hash = g_hash_table_new (NULL, NULL);
4520 res = g_hash_table_lookup (castclass_hash, klass);
4521 LeaveCriticalSection (&marshal_mutex);
4525 if (!castclass_sig) {
4526 castclass_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
4527 castclass_sig->params [0] = &mono_defaults.object_class->byval_arg;
4528 castclass_sig->ret = &mono_defaults.object_class->byval_arg;
4529 castclass_sig->pinvoke = 0;
4532 name = g_strdup_printf ("__castclass_wrapper_%s", klass->name);
4533 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_CASTCLASS);
4536 mb->method->save_lmf = 1;
4538 /* check if the object is a proxy that needs special cast */
4539 mono_mb_emit_ldarg (mb, 0);
4540 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4541 mono_mb_emit_byte (mb, CEE_MONO_CCASTCLASS);
4542 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
4544 /* The result of MONO_ISINST can be:
4545 0) the cast is valid
4546 1) cast of unknown proxy type
4547 or an exception if the cast is is invalid
4550 pos_was_ok = mono_mb_emit_branch (mb, CEE_BRFALSE);
4552 /* get the real proxy from the transparent proxy*/
4554 mono_mb_emit_ldarg (mb, 0);
4555 mono_mb_emit_managed_call (mb, mono_marshal_get_proxy_cancast (klass), NULL);
4556 pos_was_ok2 = mono_mb_emit_branch (mb, CEE_BRTRUE);
4559 mono_mb_emit_exception (mb, "InvalidCastException", NULL);
4562 mono_mb_patch_addr (mb, pos_was_ok, mb->pos - (pos_was_ok + 4));
4563 mono_mb_patch_addr (mb, pos_was_ok2, mb->pos - (pos_was_ok2 + 4));
4564 mono_mb_emit_ldarg (mb, 0);
4567 mono_mb_emit_byte (mb, CEE_RET);
4569 res = mono_mb_create_and_cache (castclass_hash, klass, mb, castclass_sig, castclass_sig->param_count + 16);
4576 mono_marshal_get_proxy_cancast (MonoClass *klass)
4578 static MonoMethodSignature *from_handle_sig = NULL;
4579 static MonoMethodSignature *upgrade_proxy_sig = NULL;
4580 static MonoMethodSignature *isint_sig = NULL;
4581 static GHashTable *proxy_isinst_hash = NULL;
4583 int pos_failed, pos_end;
4585 MonoMethod *can_cast_to;
4586 MonoMethodDesc *desc;
4587 MonoMethodBuilder *mb;
4589 EnterCriticalSection (&marshal_mutex);
4590 if (!proxy_isinst_hash)
4591 proxy_isinst_hash = g_hash_table_new (NULL, NULL);
4593 res = g_hash_table_lookup (proxy_isinst_hash, klass);
4594 LeaveCriticalSection (&marshal_mutex);
4599 upgrade_proxy_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
4600 upgrade_proxy_sig->params [0] = &mono_defaults.object_class->byval_arg;
4601 upgrade_proxy_sig->params [1] = &mono_defaults.object_class->byval_arg;
4602 upgrade_proxy_sig->ret = &mono_defaults.void_class->byval_arg;
4603 upgrade_proxy_sig->pinvoke = 1;
4605 from_handle_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
4606 from_handle_sig->params [0] = &mono_defaults.object_class->byval_arg;
4607 from_handle_sig->ret = &mono_defaults.object_class->byval_arg;
4609 isint_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
4610 isint_sig->params [0] = &mono_defaults.object_class->byval_arg;
4611 isint_sig->ret = &mono_defaults.object_class->byval_arg;
4612 isint_sig->pinvoke = 0;
4615 name = g_strdup_printf ("__proxy_isinst_wrapper_%s", klass->name);
4616 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_PROXY_ISINST);
4619 mb->method->save_lmf = 1;
4621 /* get the real proxy from the transparent proxy*/
4622 mono_mb_emit_ldarg (mb, 0);
4623 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoTransparentProxy, rp));
4624 mono_mb_emit_byte (mb, CEE_LDIND_I);
4626 /* get the refletion type from the type handle */
4627 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4628 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
4629 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, &klass->byval_arg));
4630 mono_mb_emit_native_call (mb, from_handle_sig, type_from_handle);
4632 mono_mb_emit_ldarg (mb, 0);
4634 /* make the call to CanCastTo (type, ob) */
4635 desc = mono_method_desc_new ("IRemotingTypeInfo:CanCastTo", FALSE);
4636 can_cast_to = mono_method_desc_search_in_class (desc, mono_defaults.iremotingtypeinfo_class);
4637 g_assert (can_cast_to);
4638 mono_method_desc_free (desc);
4639 mono_mb_emit_byte (mb, CEE_CALLVIRT);
4640 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, can_cast_to));
4643 pos_failed = mono_mb_emit_branch (mb, CEE_BRFALSE);
4645 /* Upgrade the proxy vtable by calling: mono_upgrade_remote_class_wrapper (type, ob)*/
4646 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4647 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
4648 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, &klass->byval_arg));
4649 mono_mb_emit_native_call (mb, from_handle_sig, type_from_handle);
4650 mono_mb_emit_ldarg (mb, 0);
4652 mono_mb_emit_native_call (mb, upgrade_proxy_sig, mono_upgrade_remote_class_wrapper);
4653 emit_thread_interrupt_checkpoint (mb);
4655 mono_mb_emit_ldarg (mb, 0);
4656 pos_end = mono_mb_emit_branch (mb, CEE_BR);
4660 mono_mb_patch_addr (mb, pos_failed, mb->pos - (pos_failed + 4));
4661 mono_mb_emit_byte (mb, CEE_LDNULL);
4665 mono_mb_patch_addr (mb, pos_end, mb->pos - (pos_end + 4));
4666 mono_mb_emit_byte (mb, CEE_RET);
4668 res = mono_mb_create_and_cache (proxy_isinst_hash, klass, mb, isint_sig, isint_sig->param_count + 16);
4675 mono_upgrade_remote_class_wrapper (MonoReflectionType *rtype, MonoTransparentProxy *tproxy)
4678 klass = mono_class_from_mono_type (rtype->type);
4679 mono_upgrade_remote_class (((MonoObject*)tproxy)->vtable->domain, tproxy->remote_class, klass);
4680 ((MonoObject*)tproxy)->vtable = tproxy->remote_class->vtable;
4684 * mono_marshal_get_struct_to_ptr:
4687 * generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld)
4690 mono_marshal_get_struct_to_ptr (MonoClass *klass)
4692 MonoMethodBuilder *mb;
4693 static MonoMethod *stoptr = NULL;
4696 g_assert (klass != NULL);
4698 if (klass->str_to_ptr)
4699 return klass->str_to_ptr;
4702 stoptr = mono_find_method_by_name (mono_defaults.marshal_class, "StructureToPtr", 3);
4705 mb = mono_mb_new (klass, stoptr->name, MONO_WRAPPER_UNKNOWN);
4707 if (klass->blittable) {
4708 mono_mb_emit_byte (mb, CEE_LDARG_1);
4709 mono_mb_emit_byte (mb, CEE_LDARG_0);
4710 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
4711 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
4712 mono_mb_emit_byte (mb, CEE_PREFIX1);
4713 mono_mb_emit_byte (mb, CEE_CPBLK);
4716 /* allocate local 0 (pointer) src_ptr */
4717 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
4718 /* allocate local 1 (pointer) dst_ptr */
4719 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
4720 /* allocate local 2 (boolean) delete_old */
4721 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
4722 mono_mb_emit_byte (mb, CEE_LDARG_2);
4723 mono_mb_emit_byte (mb, CEE_STLOC_2);
4725 /* initialize src_ptr to point to the start of object data */
4726 mono_mb_emit_byte (mb, CEE_LDARG_0);
4727 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
4728 mono_mb_emit_byte (mb, CEE_STLOC_0);
4730 /* initialize dst_ptr */
4731 mono_mb_emit_byte (mb, CEE_LDARG_1);
4732 mono_mb_emit_byte (mb, CEE_STLOC_1);
4734 emit_struct_conv (mb, klass, FALSE);
4737 mono_mb_emit_byte (mb, CEE_RET);
4739 res = mono_mb_create_method (mb, stoptr->signature, 0);
4742 klass->str_to_ptr = res;
4747 * mono_marshal_get_ptr_to_struct:
4750 * generates IL code for PtrToStructure (IntPtr src, object structure)
4753 mono_marshal_get_ptr_to_struct (MonoClass *klass)
4755 MonoMethodBuilder *mb;
4756 static MonoMethod *ptostr = NULL;
4759 g_assert (klass != NULL);
4761 if (klass->ptr_to_str)
4762 return klass->ptr_to_str;
4765 ptostr = mono_find_method_by_name (mono_defaults.marshal_class, "PtrToStructure", 2);
4768 mb = mono_mb_new (klass, ptostr->name, MONO_WRAPPER_UNKNOWN);
4770 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable) {
4771 mono_mb_emit_byte (mb, CEE_LDARG_1);
4772 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
4773 mono_mb_emit_byte (mb, CEE_LDARG_0);
4774 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
4775 mono_mb_emit_byte (mb, CEE_PREFIX1);
4776 mono_mb_emit_byte (mb, CEE_CPBLK);
4779 /* allocate local 0 (pointer) src_ptr */
4780 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
4781 /* allocate local 1 (pointer) dst_ptr */
4782 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
4784 /* initialize src_ptr to point to the start of object data */
4785 mono_mb_emit_byte (mb, CEE_LDARG_0);
4786 mono_mb_emit_byte (mb, CEE_STLOC_0);
4788 /* initialize dst_ptr */
4789 mono_mb_emit_byte (mb, CEE_LDARG_1);
4790 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
4791 mono_mb_emit_byte (mb, CEE_STLOC_1);
4793 emit_struct_conv (mb, klass, TRUE);
4796 mono_mb_emit_byte (mb, CEE_RET);
4798 res = mono_mb_create_method (mb, ptostr->signature, 0);
4801 klass->ptr_to_str = res;
4806 * generates IL code for the synchronized wrapper: the generated method
4807 * calls METHOD while locking 'this' or the parent type.
4810 mono_marshal_get_synchronized_wrapper (MonoMethod *method)
4812 static MonoMethodSignature *from_handle_sig = NULL;
4813 static MonoMethod *enter_method, *exit_method;
4814 MonoMethodSignature *sig;
4815 MonoExceptionClause *clause;
4816 MonoMethodHeader *header;
4817 MonoMethodBuilder *mb;
4820 int i, pos, this_local, ret_local;
4824 if (method->wrapper_type == MONO_WRAPPER_SYNCHRONIZED)
4827 cache = method->klass->image->synchronized_cache;
4828 if ((res = mono_marshal_find_in_cache (cache, method)))
4831 sig = method->signature;
4833 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_SYNCHRONIZED);
4836 if (!MONO_TYPE_IS_VOID (sig->ret))
4837 ret_local = mono_mb_add_local (mb, sig->ret);
4840 this_local = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
4842 clause = g_new0 (MonoExceptionClause, 1);
4843 clause->flags = MONO_EXCEPTION_CLAUSE_FINALLY;
4845 if (!enter_method) {
4846 MonoMethodDesc *desc;
4848 desc = mono_method_desc_new ("Monitor:Enter", FALSE);
4849 enter_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
4850 g_assert (enter_method);
4851 mono_method_desc_free (desc);
4852 desc = mono_method_desc_new ("Monitor:Exit", FALSE);
4853 exit_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
4854 g_assert (exit_method);
4855 mono_method_desc_free (desc);
4858 * GetTypeFromHandle isn't called as a managed method because it has
4859 * a funky calling sequence, e.g. ldtoken+GetTypeFromHandle gets
4860 * transformed into something else by the JIT.
4862 from_handle_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
4863 from_handle_sig->params [0] = &mono_defaults.object_class->byval_arg;
4864 from_handle_sig->ret = &mono_defaults.object_class->byval_arg;
4867 /* Push this or the type object */
4868 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4869 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4870 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
4871 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, &method->klass->byval_arg));
4872 mono_mb_emit_native_call (mb, from_handle_sig, type_from_handle);
4875 mono_mb_emit_ldarg (mb, 0);
4876 mono_mb_emit_stloc (mb, this_local);
4878 /* Call Monitor::Enter() */
4879 mono_mb_emit_ldloc (mb, this_local);
4880 mono_mb_emit_managed_call (mb, enter_method, NULL);
4882 clause->try_offset = mb->pos;
4884 /* Call the method */
4886 mono_mb_emit_ldarg (mb, 0);
4887 for (i = 0; i < sig->param_count; i++)
4888 mono_mb_emit_ldarg (mb, i + (sig->hasthis == TRUE));
4889 mono_mb_emit_managed_call (mb, method, method->signature);
4890 if (!MONO_TYPE_IS_VOID (sig->ret))
4891 mono_mb_emit_stloc (mb, ret_local);
4893 mono_mb_emit_byte (mb, CEE_LEAVE);
4895 mono_mb_emit_i4 (mb, 0);
4897 clause->try_len = mb->pos - clause->try_offset;
4898 clause->handler_offset = mb->pos;
4900 /* Call Monitor::Exit() */
4901 mono_mb_emit_ldloc (mb, this_local);
4902 /* mono_mb_emit_native_call (mb, exit_sig, mono_monitor_exit); */
4903 mono_mb_emit_managed_call (mb, exit_method, NULL);
4904 mono_mb_emit_byte (mb, CEE_ENDFINALLY);
4906 clause->handler_len = mb->pos - clause->handler_offset;
4908 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
4909 if (!MONO_TYPE_IS_VOID (sig->ret))
4910 mono_mb_emit_ldloc (mb, ret_local);
4911 mono_mb_emit_byte (mb, CEE_RET);
4913 res = mono_mb_create_and_cache (cache, method,
4914 mb, sig, sig->param_count + 16);
4917 header = ((MonoMethodNormal *)res)->header;
4918 header->num_clauses = 1;
4919 header->clauses = clause;
4925 mono_marshal_get_stelemref ()
4927 static MonoMethod* ret = NULL;
4928 MonoMethodSignature *sig;
4929 MonoMethodBuilder *mb;
4931 guint32 b1, b2, b3, b4;
4938 mb = mono_mb_new (mono_defaults.object_class, "stelemref", MONO_WRAPPER_STELEMREF);
4941 sig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
4943 /* void stelemref (void* array, int idx, void* value) */
4944 sig->ret = &mono_defaults.void_class->byval_arg;
4945 sig->params [0] = &mono_defaults.int_class->byval_arg;
4946 sig->params [1] = &mono_defaults.int_class->byval_arg; /* this is a natural sized int */
4947 sig->params [2] = &mono_defaults.int_class->byval_arg;
4949 aklass = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
4950 vklass = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
4958 aklass = array->vtable->klass->element_class;
4959 vklass = value->vtable->klass;
4961 if (vklass->idepth < aklass->idepth)
4964 if (vklass->supertypes [aklass->idepth - 1] != aklass)
4968 array [idx] = value;
4972 if (mono_object_isinst (value, aklass))
4975 throw new ArrayTypeMismatchException ();
4979 mono_mb_emit_ldarg (mb, 0);
4980 mono_mb_emit_ldarg (mb, 1);
4981 mono_mb_emit_byte (mb, CEE_LDELEMA);
4982 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_defaults.int_class));
4983 mono_mb_emit_byte (mb, CEE_POP);
4985 /* if (!value) goto do_store */
4986 mono_mb_emit_ldarg (mb, 2);
4987 b1 = mono_mb_emit_branch (mb, CEE_BRFALSE);
4989 /* aklass = array->vtable->klass->element_class */
4990 mono_mb_emit_ldarg (mb, 0);
4991 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoObject, vtable));
4992 mono_mb_emit_byte (mb, CEE_LDIND_I);
4993 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoVTable, klass));
4994 mono_mb_emit_byte (mb, CEE_LDIND_I);
4995 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoClass, element_class));
4996 mono_mb_emit_byte (mb, CEE_LDIND_I);
4997 mono_mb_emit_stloc (mb, aklass);
4999 /* vklass = value->vtable->klass */
5000 mono_mb_emit_ldarg (mb, 2);
5001 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoObject, vtable));
5002 mono_mb_emit_byte (mb, CEE_LDIND_I);
5003 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoVTable, klass));
5004 mono_mb_emit_byte (mb, CEE_LDIND_I);
5005 mono_mb_emit_stloc (mb, vklass);
5007 /* if (vklass->idepth < aklass->idepth) goto failue */
5008 mono_mb_emit_ldloc (mb, vklass);
5009 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoClass, idepth));
5010 mono_mb_emit_byte (mb, CEE_LDIND_I4);
5012 mono_mb_emit_ldloc (mb, aklass);
5013 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoClass, idepth));
5014 mono_mb_emit_byte (mb, CEE_LDIND_I4);
5016 b2 = mono_mb_emit_branch (mb, CEE_BLT_UN);
5018 /* if (vklass->supertypes [aklass->idepth - 1] != aklass) goto failure */
5019 mono_mb_emit_ldloc (mb, vklass);
5020 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoClass, supertypes));
5021 mono_mb_emit_byte (mb, CEE_LDIND_I);
5023 mono_mb_emit_ldloc (mb, aklass);
5024 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoClass, idepth));
5025 mono_mb_emit_byte (mb, CEE_LDIND_I4);
5026 mono_mb_emit_icon (mb, 1);
5027 mono_mb_emit_byte (mb, CEE_SUB);
5028 mono_mb_emit_icon (mb, sizeof (void*));
5029 mono_mb_emit_byte (mb, CEE_MUL);
5030 mono_mb_emit_byte (mb, CEE_ADD);
5031 mono_mb_emit_byte (mb, CEE_LDIND_I);
5033 mono_mb_emit_ldloc (mb, aklass);
5035 b3 = mono_mb_emit_branch (mb, CEE_BNE_UN);
5039 mono_mb_patch_addr (mb, b1, mb->pos - (b1 + 4));
5040 mono_mb_emit_ldarg (mb, 0);
5041 mono_mb_emit_ldarg (mb, 1);
5042 mono_mb_emit_ldarg (mb, 2);
5043 mono_mb_emit_byte (mb, CEE_STELEM_I);
5045 mono_mb_emit_byte (mb, CEE_RET);
5048 mono_mb_patch_addr (mb, b2, mb->pos - (b2 + 4));
5049 mono_mb_patch_addr (mb, b3, mb->pos - (b3 + 4));
5051 mono_mb_emit_ldarg (mb, 2);
5052 mono_mb_emit_ldloc (mb, aklass);
5053 mono_mb_emit_icall (mb, mono_object_isinst);
5055 b4 = mono_mb_emit_branch (mb, CEE_BRTRUE);
5056 mono_mb_patch_addr (mb, b4, copy_pos - (b4 + 4));
5057 mono_mb_emit_exception (mb, "ArrayTypeMismatchException", NULL);
5059 mono_mb_emit_byte (mb, CEE_RET);
5060 ret = mono_mb_create_method (mb, sig, 4);
5064 /* FIXME: on win32 we should probably use GlobalAlloc(). */
5066 mono_marshal_alloc (gpointer size)
5068 MONO_ARCH_SAVE_REGS;
5070 return g_try_malloc ((gulong)size);
5074 mono_marshal_free (gpointer ptr)
5076 MONO_ARCH_SAVE_REGS;
5082 mono_marshal_free_array (gpointer *ptr, int size)
5089 for (i = 0; i < size; i++)
5095 mono_marshal_realloc (gpointer ptr, gpointer size)
5097 MONO_ARCH_SAVE_REGS;
5099 return g_try_realloc (ptr, (gulong)size);
5103 mono_marshal_string_array (MonoArray *array)
5111 len = mono_array_length (array);
5113 result = g_malloc (sizeof (char *) * (len + 1));
5114 for (i = 0; i < len; ++i) {
5115 MonoString *s = (MonoString *)mono_array_get (array, gpointer, i);
5116 result [i] = s ? mono_string_to_utf8 (s): NULL;
5118 /* null terminate the array */
5125 mono_marshal_string_array_to_unicode (MonoArray *array)
5133 len = mono_array_length (array);
5135 result = g_malloc (sizeof (gunichar2 *) * (len + 1));
5136 for (i = 0; i < len; ++i) {
5137 MonoString *s = (MonoString *)mono_array_get (array, gpointer, i);
5138 result [i] = s ? mono_string_chars (s) : NULL;
5140 /* null terminate the array */
5147 * mono_marshal_set_last_error:
5149 * This function is invoked to set the last error value from a P/Invoke call
5150 * which has SetLastError set.
5153 mono_marshal_set_last_error (void)
5156 TlsSetValue (last_error_tls_id, (gpointer)GetLastError ());
5158 TlsSetValue (last_error_tls_id, (gpointer)errno);
5163 ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArray *src, gint32 start_index,
5164 gpointer dest, gint32 length)
5169 MONO_ARCH_SAVE_REGS;
5171 MONO_CHECK_ARG_NULL (src);
5172 MONO_CHECK_ARG_NULL (dest);
5174 g_assert (src->obj.vtable->klass->rank == 1);
5175 g_assert (start_index >= 0);
5176 g_assert (length >= 0);
5177 g_assert (start_index + length <= mono_array_length (src));
5179 element_size = mono_array_element_size (src->obj.vtable->klass);
5181 source_addr = mono_array_addr_with_size (src, element_size, start_index);
5183 memcpy (dest, source_addr, length * element_size);
5187 ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer src, gint32 start_index,
5188 MonoArray *dest, gint32 length)
5193 MONO_ARCH_SAVE_REGS;
5195 MONO_CHECK_ARG_NULL (src);
5196 MONO_CHECK_ARG_NULL (dest);
5198 g_assert (dest->obj.vtable->klass->rank == 1);
5199 g_assert (start_index >= 0);
5200 g_assert (length >= 0);
5201 g_assert (start_index + length <= mono_array_length (dest));
5203 element_size = mono_array_element_size (dest->obj.vtable->klass);
5205 dest_addr = mono_array_addr_with_size (dest, element_size, start_index);
5207 memcpy (dest_addr, src, length * element_size);
5210 #if NO_UNALIGNED_ACCESS
5211 #define RETURN_UNALIGNED(type, addr) \
5214 memcpy(&val, p + offset, sizeof(val)); \
5217 #define WRITE_UNALIGNED(type, addr, val) \
5218 memcpy(addr, &val, sizeof(type))
5220 #define RETURN_UNALIGNED(type, addr) \
5221 return *(type*)(p + offset);
5222 #define WRITE_UNALIGNED(type, addr, val) \
5223 (*(type *)(addr) = (val))
5227 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr, gint32 offset)
5231 MONO_ARCH_SAVE_REGS;
5233 RETURN_UNALIGNED(gpointer, p + offset);
5237 ves_icall_System_Runtime_InteropServices_Marshal_ReadByte (gpointer ptr, gint32 offset)
5241 MONO_ARCH_SAVE_REGS;
5243 return *(unsigned char*)(p + offset);
5247 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt16 (gpointer ptr, gint32 offset)
5251 MONO_ARCH_SAVE_REGS;
5253 RETURN_UNALIGNED(gint16, p + offset);
5257 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt32 (gpointer ptr, gint32 offset)
5261 MONO_ARCH_SAVE_REGS;
5263 RETURN_UNALIGNED(gint32, p + offset);
5267 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt64 (gpointer ptr, gint32 offset)
5271 MONO_ARCH_SAVE_REGS;
5273 RETURN_UNALIGNED(gint64, p + offset);
5277 ves_icall_System_Runtime_InteropServices_Marshal_WriteByte (gpointer ptr, gint32 offset, unsigned char val)
5281 MONO_ARCH_SAVE_REGS;
5283 *(unsigned char*)(p + offset) = val;
5287 ves_icall_System_Runtime_InteropServices_Marshal_WriteIntPtr (gpointer ptr, gint32 offset, gpointer val)
5291 MONO_ARCH_SAVE_REGS;
5293 WRITE_UNALIGNED(gpointer, p + offset, val);
5297 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt16 (gpointer ptr, gint32 offset, gint16 val)
5301 MONO_ARCH_SAVE_REGS;
5303 WRITE_UNALIGNED(gint16, p + offset, val);
5307 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt32 (gpointer ptr, gint32 offset, gint32 val)
5311 MONO_ARCH_SAVE_REGS;
5313 WRITE_UNALIGNED(gint32, p + offset, val);
5317 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt64 (gpointer ptr, gint32 offset, gint64 val)
5321 MONO_ARCH_SAVE_REGS;
5323 WRITE_UNALIGNED(gint64, p + offset, val);
5327 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (char *ptr)
5329 MONO_ARCH_SAVE_REGS;
5332 return mono_string_new (mono_domain_get (), "");
5334 return mono_string_new (mono_domain_get (), ptr);
5338 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len (char *ptr, gint32 len)
5340 MONO_ARCH_SAVE_REGS;
5343 return mono_string_new (mono_domain_get (), "");
5345 return mono_string_new_len (mono_domain_get (), ptr, len);
5349 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni (guint16 *ptr)
5351 MonoDomain *domain = mono_domain_get ();
5355 MONO_ARCH_SAVE_REGS;
5358 return mono_string_new (mono_domain_get (), "");
5363 return mono_string_new_utf16 (domain, ptr, len);
5367 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len (guint16 *ptr, gint32 len)
5369 MonoDomain *domain = mono_domain_get ();
5371 MONO_ARCH_SAVE_REGS;
5374 return mono_string_new (mono_domain_get (), "");
5376 return mono_string_new_utf16 (domain, ptr, len);
5380 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR (gpointer ptr)
5382 MONO_ARCH_SAVE_REGS;
5384 g_warning ("PtrToStringBSTR not implemented");
5385 g_assert_not_reached ();
5391 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
5393 MONO_ARCH_SAVE_REGS;
5395 return ((guint32)TlsGetValue (last_error_tls_id));
5399 ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype)
5405 MONO_ARCH_SAVE_REGS;
5407 MONO_CHECK_ARG_NULL (rtype);
5410 klass = mono_class_from_mono_type (type);
5411 layout = (klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK);
5413 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
5417 msg = g_strdup_printf ("Type %s cannot be marshaled as an unmanaged structure.", klass->name);
5418 exc = mono_get_exception_argument ("t", msg);
5420 mono_raise_exception (exc);
5424 return mono_class_native_size (klass, NULL);
5428 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old)
5433 MONO_ARCH_SAVE_REGS;
5435 MONO_CHECK_ARG_NULL (obj);
5436 MONO_CHECK_ARG_NULL (dst);
5438 method = mono_marshal_get_struct_to_ptr (obj->vtable->klass);
5442 pa [2] = &delete_old;
5444 mono_runtime_invoke (method, NULL, pa, NULL);
5448 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, MonoObject *dst)
5453 MONO_ARCH_SAVE_REGS;
5455 MONO_CHECK_ARG_NULL (src);
5456 MONO_CHECK_ARG_NULL (dst);
5458 method = mono_marshal_get_ptr_to_struct (dst->vtable->klass);
5463 mono_runtime_invoke (method, NULL, pa, NULL);
5467 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer src, MonoReflectionType *type)
5469 MonoDomain *domain = mono_domain_get ();
5472 MONO_ARCH_SAVE_REGS;
5474 MONO_CHECK_ARG_NULL (src);
5475 MONO_CHECK_ARG_NULL (type);
5477 res = mono_object_new (domain, mono_class_from_mono_type (type->type));
5479 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (src, res);
5485 ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *type, MonoString *field_name)
5487 MonoMarshalType *info;
5490 int i, match_index = -1;
5492 MONO_ARCH_SAVE_REGS;
5494 MONO_CHECK_ARG_NULL (type);
5495 MONO_CHECK_ARG_NULL (field_name);
5497 fname = mono_string_to_utf8 (field_name);
5498 klass = mono_class_from_mono_type (type->type);
5500 while(klass && match_index == -1) {
5501 for (i = 0; i < klass->field.count; ++i) {
5502 if (*fname == *klass->fields [i].name && strcmp (fname, klass->fields [i].name) == 0) {
5508 if(match_index == -1)
5509 klass = klass->parent;
5514 if(match_index == -1) {
5518 /* Get back original class instance */
5519 klass = mono_class_from_mono_type (type->type);
5521 tmp = g_strdup_printf ("Field passed in is not a marshaled member of the type %s", klass->name);
5522 exc = mono_get_exception_argument ("fieldName", tmp);
5525 mono_raise_exception ((MonoException*)exc);
5528 info = mono_marshal_load_type_info (klass);
5529 return info->fields [match_index].offset;
5533 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString *string)
5535 MONO_ARCH_SAVE_REGS;
5537 return mono_string_to_utf8 (string);
5541 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni (MonoString *string)
5543 MONO_ARCH_SAVE_REGS;
5548 return g_memdup (mono_string_chars (string), mono_string_length (string)*2);
5552 mono_struct_delete_old (MonoClass *klass, char *ptr)
5554 MonoMarshalType *info;
5557 info = mono_marshal_load_type_info (klass);
5559 for (i = 0; i < info->num_fields; i++) {
5560 MonoMarshalNative ntype;
5561 MonoMarshalConv conv;
5562 MonoType *ftype = info->fields [i].field->type;
5565 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
5568 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE,
5569 klass->unicode, &conv);
5571 cpos = ptr + info->fields [i].offset;
5574 case MONO_MARSHAL_CONV_NONE:
5575 if (MONO_TYPE_ISSTRUCT (ftype)) {
5576 mono_struct_delete_old (ftype->data.klass, cpos);
5580 case MONO_MARSHAL_CONV_STR_LPWSTR:
5581 case MONO_MARSHAL_CONV_STR_LPSTR:
5582 case MONO_MARSHAL_CONV_STR_LPTSTR:
5583 case MONO_MARSHAL_CONV_STR_BSTR:
5584 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
5585 case MONO_MARSHAL_CONV_STR_TBSTR:
5586 g_free (*(gpointer *)cpos);
5595 ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure (gpointer src, MonoReflectionType *type)
5599 MONO_ARCH_SAVE_REGS;
5601 MONO_CHECK_ARG_NULL (src);
5602 MONO_CHECK_ARG_NULL (type);
5604 klass = mono_class_from_mono_type (type->type);
5606 mono_struct_delete_old (klass, (char *)src);
5610 ves_icall_System_Runtime_InteropServices_Marshal_AllocCoTaskMem (int size)
5612 /* FIXME: Call AllocCoTaskMem under windows */
5613 MONO_ARCH_SAVE_REGS;
5615 return g_try_malloc ((gulong)size);
5619 ves_icall_System_Runtime_InteropServices_Marshal_FreeCoTaskMem (void *ptr)
5621 /* FIXME: Call FreeCoTaskMem under windows */
5622 MONO_ARCH_SAVE_REGS;
5628 ves_icall_System_Runtime_InteropServices_Marshal_UnsafeAddrOfPinnedArrayElement (MonoArray *arrayobj, int index)
5630 return mono_array_addr_with_size (arrayobj, mono_array_element_size (arrayobj->obj.vtable->klass), index);
5634 mono_marshal_load_type_info (MonoClass* klass)
5636 int i, j, count = 0, native_size = 0, min_align = 1;
5637 MonoMarshalType *info;
5640 g_assert (klass != NULL);
5642 if (klass->marshal_info)
5643 return klass->marshal_info;
5646 mono_class_init (klass);
5648 for (i = 0; i < klass->field.count; ++i) {
5649 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
5651 if (mono_field_is_deleted (&klass->fields [i]))
5656 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
5658 klass->marshal_info = info = g_malloc0 (sizeof (MonoMarshalType) + sizeof (MonoMarshalField) * count);
5659 info->num_fields = count;
5661 /* Try to find a size for this type in metadata */
5662 mono_metadata_packing_from_typedef (klass->image, klass->type_token, NULL, &native_size);
5664 if (klass->parent) {
5665 int parent_size = mono_class_native_size (klass->parent, NULL);
5667 /* Add parent size to real size */
5668 native_size += parent_size;
5669 info->native_size = parent_size;
5672 for (j = i = 0; i < klass->field.count; ++i) {
5675 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
5678 if (mono_field_is_deleted (&klass->fields [i]))
5680 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL)
5681 mono_metadata_field_info (klass->image, klass->field.first + i,
5682 NULL, NULL, &info->fields [j].mspec);
5684 info->fields [j].field = &klass->fields [i];
5686 if ((klass->field.count == 1) && (klass->instance_size == sizeof (MonoObject)) &&
5687 (strcmp (klass->fields [i].name, "$PRIVATE$") == 0)) {
5688 /* This field is a hack inserted by MCS to empty structures */
5693 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
5694 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
5695 size = mono_marshal_type_size (klass->fields [i].type, info->fields [j].mspec,
5696 &align, TRUE, klass->unicode);
5697 align = klass->packing_size ? MIN (klass->packing_size, align): align;
5698 min_align = MAX (align, min_align);
5699 info->fields [j].offset = info->native_size;
5700 info->fields [j].offset += align - 1;
5701 info->fields [j].offset &= ~(align - 1);
5702 info->native_size = info->fields [j].offset + size;
5704 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
5705 size = mono_marshal_type_size (klass->fields [i].type, info->fields [j].mspec,
5706 &align, TRUE, klass->unicode);
5707 align = klass->packing_size ? MIN (klass->packing_size, align): align;
5708 min_align = MAX (align, min_align);
5709 info->fields [j].offset = klass->fields [i].offset - sizeof (MonoObject);
5710 info->native_size = MAX (info->native_size, info->fields [j].offset + size);
5716 if(layout != TYPE_ATTRIBUTE_AUTO_LAYOUT) {
5717 info->native_size = MAX (native_size, info->native_size);
5720 if (info->native_size & (min_align - 1)) {
5721 info->native_size += min_align - 1;
5722 info->native_size &= ~(min_align - 1);
5725 /* Update the class's blittable info, if the layouts don't match */
5726 if (info->native_size != mono_class_value_size (klass, NULL))
5727 klass->blittable = FALSE;
5729 /* If this is an array type, ensure that we have element info */
5730 if (klass->element_class) {
5731 mono_marshal_load_type_info (klass->element_class);
5734 return klass->marshal_info;
5738 * mono_class_native_size:
5741 * Returns: the native size of an object instance (when marshaled
5742 * to unmanaged code)
5745 mono_class_native_size (MonoClass *klass, guint32 *align)
5748 if (!klass->marshal_info)
5749 mono_marshal_load_type_info (klass);
5752 *align = klass->min_align;
5754 return klass->marshal_info->native_size;
5758 * mono_type_native_stack_size:
5759 * @t: the type to return the size it uses on the stack
5761 * Returns: the number of bytes required to hold an instance of this
5762 * type on the native stack
5765 mono_type_native_stack_size (MonoType *t, gint *align)
5769 g_assert (t != NULL);
5780 case MONO_TYPE_BOOLEAN:
5781 case MONO_TYPE_CHAR:
5790 case MONO_TYPE_STRING:
5791 case MONO_TYPE_OBJECT:
5792 case MONO_TYPE_CLASS:
5793 case MONO_TYPE_SZARRAY:
5795 case MONO_TYPE_FNPTR:
5796 case MONO_TYPE_ARRAY:
5797 case MONO_TYPE_TYPEDBYREF:
5808 case MONO_TYPE_VALUETYPE: {
5811 if (t->data.klass->enumtype)
5812 return mono_type_native_stack_size (t->data.klass->enum_basetype, align);
5814 size = mono_class_native_size (t->data.klass, align);
5815 *align = *align + 3;
5825 g_error ("type 0x%02x unknown", t->type);
5830 /* __alignof__ returns the preferred alignment of values not the actual alignment used by
5831 the compiler so is wrong e.g. for Linux where doubles are aligned on a 4 byte boundary
5832 but __alignof__ returns 8 - using G_STRUCT_OFFSET works better */
5833 #define ALIGNMENT(type) G_STRUCT_OFFSET(struct { char c; type x; }, x)
5836 mono_marshal_type_size (MonoType *type, MonoMarshalSpec *mspec, gint32 *align,
5837 gboolean as_field, gboolean unicode)
5839 MonoMarshalNative native_type = mono_type_to_unmanaged (type, mspec, as_field, unicode, NULL);
5842 switch (native_type) {
5843 case MONO_NATIVE_BOOLEAN:
5846 case MONO_NATIVE_I1:
5847 case MONO_NATIVE_U1:
5850 case MONO_NATIVE_I2:
5851 case MONO_NATIVE_U2:
5852 case MONO_NATIVE_VARIANTBOOL:
5855 case MONO_NATIVE_I4:
5856 case MONO_NATIVE_U4:
5857 case MONO_NATIVE_ERROR:
5860 case MONO_NATIVE_I8:
5861 case MONO_NATIVE_U8:
5862 *align = ALIGNMENT(guint64);
5864 case MONO_NATIVE_R4:
5867 case MONO_NATIVE_R8:
5868 *align = ALIGNMENT(double);
5870 case MONO_NATIVE_INT:
5871 case MONO_NATIVE_UINT:
5872 case MONO_NATIVE_LPSTR:
5873 case MONO_NATIVE_LPWSTR:
5874 case MONO_NATIVE_LPTSTR:
5875 case MONO_NATIVE_BSTR:
5876 case MONO_NATIVE_ANSIBSTR:
5877 case MONO_NATIVE_TBSTR:
5878 case MONO_NATIVE_LPARRAY:
5879 case MONO_NATIVE_SAFEARRAY:
5880 case MONO_NATIVE_IUNKNOWN:
5881 case MONO_NATIVE_IDISPATCH:
5882 case MONO_NATIVE_INTERFACE:
5883 case MONO_NATIVE_ASANY:
5884 case MONO_NATIVE_FUNC:
5885 case MONO_NATIVE_LPSTRUCT:
5886 *align = ALIGNMENT(gpointer);
5887 return sizeof (gpointer);
5888 case MONO_NATIVE_STRUCT:
5889 klass = mono_class_from_mono_type (type);
5890 return mono_class_native_size (klass, align);
5891 case MONO_NATIVE_BYVALTSTR: {
5892 int esize = unicode ? 2: 1;
5895 return mspec->data.array_data.num_elem * esize;
5897 case MONO_NATIVE_BYVALARRAY: {
5899 klass = mono_class_from_mono_type (type);
5900 esize = mono_class_native_size (klass->element_class, align);
5902 return mspec->data.array_data.num_elem * esize;
5904 case MONO_NATIVE_CUSTOM:
5905 g_assert_not_reached ();
5907 case MONO_NATIVE_CURRENCY:
5908 case MONO_NATIVE_VBBYREFSTR:
5910 g_error ("native type %02x not implemented", native_type);
5913 g_assert_not_reached ();
5918 mono_marshal_asany (MonoObject *o, MonoMarshalNative string_encoding)
5926 t = &o->vtable->klass->byval_arg;
5933 case MONO_TYPE_BOOLEAN:
5936 case MONO_TYPE_CHAR:
5941 return mono_object_unbox (o);
5943 case MONO_TYPE_STRING:
5944 switch (string_encoding) {
5945 case MONO_NATIVE_LPWSTR:
5946 return mono_string_to_utf16 ((MonoString*)o);
5948 case MONO_NATIVE_LPSTR:
5949 return mono_string_to_utf8 ((MonoString*)o);
5952 g_warning ("marshaling conversion %d not implemented", string_encoding);
5953 g_assert_not_reached ();
5956 case MONO_TYPE_CLASS:
5957 case MONO_TYPE_VALUETYPE: {
5961 MonoBoolean delete_old = FALSE;
5963 klass = t->data.klass;
5965 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT)
5968 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
5969 klass->blittable || klass->enumtype)
5970 return mono_object_unbox (o);
5972 res = g_malloc0 (mono_class_native_size (klass, NULL));
5974 method = mono_marshal_get_struct_to_ptr (o->vtable->klass);
5978 pa [2] = &delete_old;
5980 mono_runtime_invoke (method, NULL, pa, NULL);
5986 mono_raise_exception (mono_get_exception_argument ("", "No PInvoke conversion exists for value passed to Object-typed parameter."));
5992 mono_marshal_free_asany (MonoObject *o, gpointer ptr, MonoMarshalNative string_encoding)
5997 /* FIXME: Free embedded data as well */
6002 t = &o->vtable->klass->byval_arg;
6004 case MONO_TYPE_STRING:
6005 switch (string_encoding) {
6006 case MONO_NATIVE_LPWSTR:
6009 case MONO_NATIVE_LPSTR:
6013 g_warning ("marshaling conversion %d not implemented", string_encoding);
6014 g_assert_not_reached ();
6017 case MONO_TYPE_CLASS:
6018 case MONO_TYPE_VALUETYPE: {
6019 klass = t->data.klass;
6021 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
6022 klass->blittable || klass->enumtype)