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"
25 //#define DEBUG_RUNTIME_CODE
27 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
31 #include "mono/cil/opcode.def"
36 struct _MonoMethodBuilder {
40 guint32 code_size, pos;
45 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object);
48 mono_find_method_by_name (MonoClass *klass, const char *name, int param_count)
50 MonoMethod *res = NULL;
53 for (i = 0; i < klass->method.count; ++i) {
54 if (klass->methods [i]->name[0] == name [0] &&
55 !strcmp (name, klass->methods [i]->name) &&
56 klass->methods [i]->signature->param_count == param_count) {
57 res = klass->methods [i];
64 #ifdef DEBUG_RUNTIME_CODE
66 indenter (MonoDisHelper *dh, MonoMethod *method, guint32 ip_offset)
68 return g_strdup (" ");
71 static MonoDisHelper marshal_dh = {
81 /* This mutex protects the various marshalling related caches in MonoImage */
82 static CRITICAL_SECTION marshal_mutex;
84 /* Maps wrapper methods to the methods they wrap */
85 static MonoGHashTable *wrapper_hash;
87 static guint32 last_error_tls_id;
90 mono_marshal_init (void)
92 static gboolean module_initialized = FALSE;
94 if (!module_initialized) {
95 module_initialized = TRUE;
96 InitializeCriticalSection (&marshal_mutex);
97 wrapper_hash = mono_g_hash_table_new (NULL, NULL);
98 last_error_tls_id = TlsAlloc ();
103 mono_delegate_to_ftnptr (MonoDelegate *delegate)
105 MonoMethod *method, *wrapper, *invoke;
106 MonoMarshalSpec **mspecs;
113 if (delegate->delegate_trampoline)
114 return delegate->delegate_trampoline;
116 klass = ((MonoObject *)delegate)->vtable->klass;
117 g_assert (klass->delegate);
120 method = delegate->method_info->method;
121 invoke = mono_find_method_by_name (klass, "Invoke", method->signature->param_count);
123 mspecs = g_new (MonoMarshalSpec*, invoke->signature->param_count + 1);
124 mono_method_get_marshal_info (invoke, mspecs);
126 wrapper = mono_marshal_get_managed_wrapper (method, delegate->target, mspecs);
128 for (i = invoke->signature->param_count; i >= 0; i--)
132 delegate->delegate_trampoline = mono_compile_method (wrapper);
134 return delegate->delegate_trampoline;
138 mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn)
143 d = (MonoDelegate*)mono_object_new (mono_domain_get (), klass);
145 ji = mono_jit_info_table_find (mono_domain_get (), ftn);
147 mono_raise_exception (mono_get_exception_argument ("", "Function pointer was not created by a Delegate."));
149 /* FIXME: discard the wrapper and call the original method */
150 mono_delegate_ctor ((MonoObject*)d, NULL, ftn);
156 mono_array_to_savearray (MonoArray *array)
161 g_assert_not_reached ();
166 mono_array_to_lparray (MonoArray *array)
171 /* fixme: maybe we need to make a copy */
172 return array->vector;
176 mono_string_utf8_to_builder (MonoStringBuilder *sb, char *text)
178 GError *error = NULL;
188 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
190 if (items_written > mono_stringbuilder_capacity (sb))
191 items_written = mono_stringbuilder_capacity (sb);
194 memcpy (mono_string_chars (sb->str), ut, items_written * 2);
195 sb->length = items_written;
197 g_error_free (error);
203 mono_string_utf16_to_builder (MonoStringBuilder *sb, gunichar2 *text)
210 g_assert (mono_string_chars (sb->str) == text);
212 for (len = 0; text [len] != 0; ++len)
219 mono_string_builder_to_utf8 (MonoStringBuilder *sb)
221 GError *error = NULL;
227 res = g_malloc0 (mono_stringbuilder_capacity (sb) + 1);
229 g_utf16_to_utf8 (mono_string_chars (sb->str), sb->length, NULL, res, &error);
231 g_error_free (error);
232 mono_raise_exception (mono_get_exception_execution_engine ("Failed to convert StringBuilder from utf16 to utf8"));
239 mono_string_builder_to_utf16 (MonoStringBuilder *sb)
244 return mono_string_chars (sb->str);
248 mono_string_to_ansibstr (MonoString *string_obj)
250 g_error ("implement me");
255 mono_string_to_bstr (MonoString *string_obj)
257 g_error ("implement me");
262 mono_string_to_byvalstr (gpointer dst, MonoString *src, int size)
267 g_assert (dst != NULL);
270 memset (dst, 0, size);
275 s = mono_string_to_utf8 (src);
276 len = MIN (size, strlen (s));
277 memcpy (dst, s, len);
280 *((char *)dst + size - 1) = 0;
284 mono_string_to_byvalwstr (gpointer dst, MonoString *src, int size)
288 g_assert (dst != NULL);
292 memset (dst, 0, size);
296 len = MIN (size, (mono_string_length (src) * 2));
297 memcpy (dst, mono_string_chars (src), len);
299 *((char *)dst + size - 1) = 0;
300 *((char *)dst + size - 2) = 0;
304 mono_mb_free (MonoMethodBuilder *mb)
306 g_list_free (mb->locals_list);
311 mono_mb_new (MonoClass *klass, const char *name, MonoWrapperType type)
313 MonoMethodBuilder *mb;
316 g_assert (klass != NULL);
317 g_assert (name != NULL);
319 mb = g_new0 (MonoMethodBuilder, 1);
321 mb->method = m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
324 m->name = g_strdup (name);
326 m->inline_count = -1;
327 m->wrapper_type = type;
330 mb->code = g_malloc (mb->code_size);
336 mono_mb_add_local (MonoMethodBuilder *mb, MonoType *type)
338 int res = mb->locals;
340 g_assert (mb != NULL);
341 g_assert (type != NULL);
343 mb->locals_list = g_list_append (mb->locals_list, type);
350 mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack)
352 MonoMethodHeader *header;
356 g_assert (mb != NULL);
358 ((MonoMethodNormal *)mb->method)->header = header = (MonoMethodHeader *)
359 g_malloc0 (sizeof (MonoMethodHeader) + mb->locals * sizeof (MonoType *));
364 header->max_stack = max_stack;
366 for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
367 header->locals [i] = (MonoType *)l->data;
370 mb->method->signature = signature;
371 header->code = mb->code;
372 header->code_size = mb->pos;
373 header->num_locals = mb->locals;
375 #ifdef DEBUG_RUNTIME_CODE
376 printf ("RUNTIME CODE FOR %s\n", mono_method_full_name (mb->method, TRUE));
377 printf ("%s\n", mono_disasm_code (&marshal_dh, mb->method, mb->code, mb->code + mb->pos));
384 mono_mb_add_data (MonoMethodBuilder *mb, gpointer data)
386 MonoMethodWrapper *mw;
388 g_assert (mb != NULL);
390 mw = (MonoMethodWrapper *)mb->method;
392 mw->data = g_list_append (mw->data, data);
394 return g_list_length (mw->data);
398 mono_mb_patch_addr (MonoMethodBuilder *mb, int pos, int value)
400 mb->code [pos] = value & 0xff;
401 mb->code [pos + 1] = (value >> 8) & 0xff;
402 mb->code [pos + 2] = (value >> 16) & 0xff;
403 mb->code [pos + 3] = (value >> 24) & 0xff;
407 mono_mb_patch_addr_s (MonoMethodBuilder *mb, int pos, gint8 value)
409 *((gint8 *)(&mb->code [pos])) = value;
413 mono_mb_emit_byte (MonoMethodBuilder *mb, guint8 op)
415 if (mb->pos >= mb->code_size) {
417 mb->code = g_realloc (mb->code, mb->code_size);
420 mb->code [mb->pos++] = op;
424 mono_mb_emit_ldflda (MonoMethodBuilder *mb, gint32 offset)
426 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
427 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
430 mono_mb_emit_icon (mb, offset);
431 mono_mb_emit_byte (mb, CEE_ADD);
436 mono_mb_emit_proxy_check (MonoMethodBuilder *mb, int branch_code)
439 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoObject, vtable));
440 mono_mb_emit_byte (mb, CEE_LDIND_I);
441 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoVTable, klass));
442 mono_mb_emit_byte (mb, CEE_ADD);
443 mono_mb_emit_byte (mb, CEE_LDIND_I);
444 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
445 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
446 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_defaults.transparent_proxy_class));
447 mono_mb_emit_byte (mb, branch_code);
449 mono_mb_emit_i4 (mb, 0);
454 mono_mb_emit_i4 (MonoMethodBuilder *mb, gint32 data)
456 if ((mb->pos + 4) >= mb->code_size) {
458 mb->code = g_realloc (mb->code, mb->code_size);
461 mono_mb_patch_addr (mb, mb->pos, data);
466 mono_mb_emit_i2 (MonoMethodBuilder *mb, gint16 data)
468 if ((mb->pos + 2) >= mb->code_size) {
470 mb->code = g_realloc (mb->code, mb->code_size);
473 mb->code [mb->pos] = data & 0xff;
474 mb->code [mb->pos + 1] = (data >> 8) & 0xff;
479 mono_mb_emit_ldstr (MonoMethodBuilder *mb, char *str)
481 mono_mb_emit_byte (mb, CEE_LDSTR);
482 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, str));
487 mono_mb_emit_ldarg (MonoMethodBuilder *mb, guint argnum)
490 mono_mb_emit_byte (mb, CEE_LDARG_0 + argnum);
491 } else if (argnum < 256) {
492 mono_mb_emit_byte (mb, CEE_LDARG_S);
493 mono_mb_emit_byte (mb, argnum);
495 mono_mb_emit_byte (mb, CEE_PREFIX1);
496 mono_mb_emit_byte (mb, CEE_LDARG);
497 mono_mb_emit_i2 (mb, argnum);
502 mono_mb_emit_ldarg_addr (MonoMethodBuilder *mb, guint argnum)
505 mono_mb_emit_byte (mb, CEE_LDARGA_S);
506 mono_mb_emit_byte (mb, argnum);
508 mono_mb_emit_byte (mb, CEE_PREFIX1);
509 mono_mb_emit_byte (mb, CEE_LDARGA);
510 mono_mb_emit_i2 (mb, argnum);
515 mono_mb_emit_ldloc_addr (MonoMethodBuilder *mb, guint locnum)
518 mono_mb_emit_byte (mb, CEE_LDLOCA_S);
519 mono_mb_emit_byte (mb, locnum);
521 mono_mb_emit_byte (mb, CEE_PREFIX1);
522 mono_mb_emit_byte (mb, CEE_LDLOCA);
523 mono_mb_emit_i2 (mb, locnum);
528 mono_mb_emit_ldloc (MonoMethodBuilder *mb, guint num)
531 mono_mb_emit_byte (mb, CEE_LDLOC_0 + num);
532 } else if (num < 256) {
533 mono_mb_emit_byte (mb, CEE_LDLOC_S);
534 mono_mb_emit_byte (mb, num);
536 mono_mb_emit_byte (mb, CEE_PREFIX1);
537 mono_mb_emit_byte (mb, CEE_LDLOC);
538 mono_mb_emit_i2 (mb, num);
543 mono_mb_emit_stloc (MonoMethodBuilder *mb, guint num)
546 mono_mb_emit_byte (mb, CEE_STLOC_0 + num);
547 } else if (num < 256) {
548 mono_mb_emit_byte (mb, CEE_STLOC_S);
549 mono_mb_emit_byte (mb, num);
551 mono_mb_emit_byte (mb, CEE_PREFIX1);
552 mono_mb_emit_byte (mb, CEE_STLOC);
553 mono_mb_emit_i2 (mb, num);
558 mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value)
560 if (value >= -1 && value < 8) {
561 mono_mb_emit_byte (mb, CEE_LDC_I4_0 + value);
562 } else if (value >= -128 && value <= 127) {
563 mono_mb_emit_byte (mb, CEE_LDC_I4_S);
564 mono_mb_emit_byte (mb, value);
566 mono_mb_emit_byte (mb, CEE_LDC_I4);
567 mono_mb_emit_i4 (mb, value);
572 mono_mb_emit_branch (MonoMethodBuilder *mb, guint8 op)
575 mono_mb_emit_byte (mb, op);
577 mono_mb_emit_i4 (mb, 0);
582 mono_mb_emit_calli (MonoMethodBuilder *mb, MonoMethodSignature *sig)
584 mono_mb_emit_byte (mb, CEE_CALLI);
585 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
589 mono_mb_emit_managed_call (MonoMethodBuilder *mb, MonoMethod *method, MonoMethodSignature *opt_sig)
591 mono_mb_emit_byte (mb, CEE_PREFIX1);
592 mono_mb_emit_byte (mb, CEE_LDFTN);
593 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
594 mono_mb_emit_calli (mb, opt_sig ? opt_sig : method->signature);
598 mono_mb_emit_native_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, gpointer func)
600 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
601 mono_mb_emit_byte (mb, CEE_MONO_SAVE_LMF);
602 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
603 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
604 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, func));
605 mono_mb_emit_calli (mb, sig);
606 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
607 mono_mb_emit_byte (mb, CEE_MONO_RESTORE_LMF);
611 mono_mb_emit_exception (MonoMethodBuilder *mb, const char *exc_name, const char *msg)
613 /* fixme: we need a better way to throw exception,
614 * supporting several exception types and messages */
615 MonoMethod *ctor = NULL;
617 MonoClass *mme = mono_class_from_name (mono_defaults.corlib, "System", exc_name);
619 mono_class_init (mme);
620 for (i = 0; i < mme->method.count; ++i) {
621 if (strcmp (mme->methods [i]->name, ".ctor") == 0 && mme->methods [i]->signature->param_count == 0) {
622 ctor = mme->methods [i];
627 mono_mb_emit_byte (mb, CEE_NEWOBJ);
628 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, ctor));
630 mono_mb_emit_byte (mb, CEE_DUP);
631 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoException, message));
632 mono_mb_emit_ldstr (mb, (char*)msg);
633 mono_mb_emit_byte (mb, CEE_STIND_I);
635 mono_mb_emit_byte (mb, CEE_THROW);
639 mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint16 local, gint32 incr)
641 mono_mb_emit_ldloc (mb, local);
642 mono_mb_emit_icon (mb, incr);
643 mono_mb_emit_byte (mb, CEE_ADD);
644 mono_mb_emit_stloc (mb, local);
648 emit_ptr_to_str_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv,
649 int usize, int msize, MonoMarshalSpec *mspec)
652 case MONO_MARSHAL_CONV_BOOL_I4:
653 mono_mb_emit_byte (mb, CEE_LDLOC_1);
654 mono_mb_emit_byte (mb, CEE_LDLOC_0);
655 mono_mb_emit_byte (mb, CEE_LDIND_I4);
656 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
657 mono_mb_emit_byte (mb, 3);
658 mono_mb_emit_byte (mb, CEE_LDC_I4_1);
659 mono_mb_emit_byte (mb, CEE_BR_S);
660 mono_mb_emit_byte (mb, 1);
661 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
662 mono_mb_emit_byte (mb, CEE_STIND_I1);
664 case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
665 mono_mb_emit_byte (mb, CEE_LDLOC_1);
666 mono_mb_emit_byte (mb, CEE_LDLOC_0);
667 mono_mb_emit_byte (mb, CEE_LDIND_I2);
668 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
669 mono_mb_emit_byte (mb, 3);
670 mono_mb_emit_byte (mb, CEE_LDC_I4_1);
671 mono_mb_emit_byte (mb, CEE_BR_S);
672 mono_mb_emit_byte (mb, 1);
673 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
674 mono_mb_emit_byte (mb, CEE_STIND_I1);
676 case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
677 MonoClass *eclass = NULL;
680 if (type->type == MONO_TYPE_SZARRAY) {
681 eclass = type->data.klass;
683 g_assert_not_reached ();
686 if (eclass->valuetype)
687 esize = mono_class_instance_size (eclass) - sizeof (MonoObject);
689 esize = sizeof (gpointer);
691 /* create a new array */
692 mono_mb_emit_byte (mb, CEE_LDLOC_1);
693 mono_mb_emit_icon (mb, mspec->data.array_data.num_elem);
694 mono_mb_emit_byte (mb, CEE_NEWARR);
695 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eclass));
696 mono_mb_emit_byte (mb, CEE_STIND_I);
698 /* copy the elements */
699 mono_mb_emit_byte (mb, CEE_LDLOC_1);
700 mono_mb_emit_byte (mb, CEE_LDIND_I);
701 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
702 mono_mb_emit_byte (mb, CEE_ADD);
703 mono_mb_emit_byte (mb, CEE_LDLOC_0);
704 mono_mb_emit_icon (mb, mspec->data.array_data.num_elem * esize);
705 mono_mb_emit_byte (mb, CEE_PREFIX1);
706 mono_mb_emit_byte (mb, CEE_CPBLK);
710 case MONO_MARSHAL_CONV_STR_BYVALSTR:
711 mono_mb_emit_byte (mb, CEE_LDLOC_1);
712 mono_mb_emit_byte (mb, CEE_LDLOC_0);
713 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
714 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
715 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
716 mono_mb_emit_byte (mb, CEE_STIND_I);
718 case MONO_MARSHAL_CONV_STR_LPTSTR:
719 case MONO_MARSHAL_CONV_STR_LPSTR:
720 mono_mb_emit_byte (mb, CEE_LDLOC_1);
721 mono_mb_emit_byte (mb, CEE_LDLOC_0);
722 mono_mb_emit_byte (mb, CEE_LDIND_I);
723 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
724 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
725 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
726 mono_mb_emit_byte (mb, CEE_STIND_I);
728 case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
729 MonoClass *klass = mono_class_from_mono_type (type);
730 int src_var, dst_var;
732 src_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
733 dst_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
735 /* *dst = new object */
736 mono_mb_emit_byte (mb, CEE_LDLOC_1);
737 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
738 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
739 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
740 mono_mb_emit_byte (mb, CEE_STIND_I);
742 /* save the old src pointer */
743 mono_mb_emit_byte (mb, CEE_LDLOC_0);
744 mono_mb_emit_stloc (mb, src_var);
745 /* save the old dst pointer */
746 mono_mb_emit_byte (mb, CEE_LDLOC_1);
747 mono_mb_emit_stloc (mb, dst_var);
749 /* dst = pointer to newly created object data */
750 mono_mb_emit_byte (mb, CEE_LDLOC_1);
751 mono_mb_emit_byte (mb, CEE_LDIND_I);
752 mono_mb_emit_icon (mb, sizeof (MonoObject));
753 mono_mb_emit_byte (mb, CEE_ADD);
754 mono_mb_emit_byte (mb, CEE_STLOC_1);
756 emit_struct_conv (mb, klass, TRUE);
758 /* restore the old src pointer */
759 mono_mb_emit_ldloc (mb, src_var);
760 mono_mb_emit_byte (mb, CEE_STLOC_0);
761 /* restore the old dst pointer */
762 mono_mb_emit_ldloc (mb, dst_var);
763 mono_mb_emit_byte (mb, CEE_STLOC_1);
766 case MONO_MARSHAL_CONV_DEL_FTN: {
767 // fixme: we never convert functions back to delegates, dont
768 // know if thats the correct behaviour
771 case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
772 g_error ("Structure field of type %s can't be marshalled as LPArray", mono_class_from_mono_type (type)->name);
774 case MONO_MARSHAL_CONV_STR_LPWSTR:
775 case MONO_MARSHAL_CONV_STR_BSTR:
776 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
777 case MONO_MARSHAL_CONV_STR_TBSTR:
778 case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
779 case MONO_MARSHAL_CONV_STR_BYVALWSTR:
781 g_warning ("marshaling conversion %d not implemented", conv);
782 g_assert_not_reached ();
787 emit_str_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, int usize, int msize,
788 MonoMarshalSpec *mspec)
793 case MONO_MARSHAL_CONV_BOOL_I4:
794 mono_mb_emit_byte (mb, CEE_LDLOC_1);
795 mono_mb_emit_byte (mb, CEE_LDLOC_0);
796 mono_mb_emit_byte (mb, CEE_LDIND_U1);
797 mono_mb_emit_byte (mb, CEE_STIND_I4);
799 case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
800 mono_mb_emit_byte (mb, CEE_LDLOC_1);
801 mono_mb_emit_byte (mb, CEE_LDLOC_0);
802 mono_mb_emit_byte (mb, CEE_LDIND_U1);
803 mono_mb_emit_byte (mb, CEE_NEG);
804 mono_mb_emit_byte (mb, CEE_STIND_I2);
806 case MONO_MARSHAL_CONV_STR_LPWSTR:
807 case MONO_MARSHAL_CONV_STR_LPSTR:
808 case MONO_MARSHAL_CONV_STR_LPTSTR:
809 case MONO_MARSHAL_CONV_STR_BSTR:
810 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
811 case MONO_MARSHAL_CONV_STR_TBSTR:
812 /* free space if free == true */
813 mono_mb_emit_byte (mb, CEE_LDLOC_2);
814 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
815 mono_mb_emit_byte (mb, 4);
816 mono_mb_emit_byte (mb, CEE_LDLOC_1);
817 mono_mb_emit_byte (mb, CEE_LDIND_I);
818 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
819 mono_mb_emit_byte (mb, CEE_MONO_FREE);
821 mono_mb_emit_byte (mb, CEE_LDLOC_1);
822 mono_mb_emit_byte (mb, CEE_LDLOC_0);
823 mono_mb_emit_byte (mb, CEE_LDIND_I);
824 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
825 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
826 mono_mb_emit_byte (mb, conv);
827 mono_mb_emit_byte (mb, CEE_STIND_I);
829 case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
830 case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
831 case MONO_MARSHAL_CONV_DEL_FTN:
832 mono_mb_emit_byte (mb, CEE_LDLOC_1);
833 mono_mb_emit_byte (mb, CEE_LDLOC_0);
834 mono_mb_emit_byte (mb, CEE_LDIND_I);
835 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
836 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
837 mono_mb_emit_byte (mb, conv);
838 mono_mb_emit_byte (mb, CEE_STIND_I);
840 case MONO_MARSHAL_CONV_STR_BYVALSTR:
841 case MONO_MARSHAL_CONV_STR_BYVALWSTR: {
845 mono_mb_emit_byte (mb, CEE_LDLOC_1); /* dst */
846 mono_mb_emit_byte (mb, CEE_LDLOC_0);
847 mono_mb_emit_byte (mb, CEE_LDIND_I); /* src String */
848 mono_mb_emit_icon (mb, usize);
849 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
850 mono_mb_emit_byte (mb, CEE_MONO_PROC3);
851 mono_mb_emit_byte (mb, conv);
854 case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
855 MonoClass *eclass = NULL;
858 if (type->type == MONO_TYPE_SZARRAY) {
859 eclass = type->data.klass;
861 g_assert_not_reached ();
864 if (eclass->valuetype)
865 esize = mono_class_native_size (eclass, NULL);
867 esize = sizeof (gpointer);
872 mono_mb_emit_byte (mb, CEE_LDLOC_0);
873 mono_mb_emit_byte (mb, CEE_LDIND_I);
874 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
876 mono_mb_emit_byte (mb, 0);
878 mono_mb_emit_byte (mb, CEE_LDLOC_1);
879 mono_mb_emit_byte (mb, CEE_LDLOC_0);
880 mono_mb_emit_byte (mb, CEE_LDIND_I);
881 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
882 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
883 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
884 mono_mb_emit_byte (mb, CEE_ADD);
885 mono_mb_emit_icon (mb, mspec->data.array_data.num_elem * esize);
886 mono_mb_emit_byte (mb, CEE_PREFIX1);
887 mono_mb_emit_byte (mb, CEE_CPBLK);
888 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
891 case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
892 int src_var, dst_var;
894 src_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
895 dst_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
897 mono_mb_emit_byte (mb, CEE_LDLOC_0);
898 mono_mb_emit_byte (mb, CEE_LDIND_I);
899 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
901 mono_mb_emit_byte (mb, 0);
903 /* save the old src pointer */
904 mono_mb_emit_byte (mb, CEE_LDLOC_0);
905 mono_mb_emit_stloc (mb, src_var);
906 /* save the old dst pointer */
907 mono_mb_emit_byte (mb, CEE_LDLOC_1);
908 mono_mb_emit_stloc (mb, dst_var);
910 /* src = pointer to object data */
911 mono_mb_emit_byte (mb, CEE_LDLOC_0);
912 mono_mb_emit_byte (mb, CEE_LDIND_I);
913 mono_mb_emit_icon (mb, sizeof (MonoObject));
914 mono_mb_emit_byte (mb, CEE_ADD);
915 mono_mb_emit_byte (mb, CEE_STLOC_0);
917 emit_struct_conv (mb, mono_class_from_mono_type (type), FALSE);
919 /* restore the old src pointer */
920 mono_mb_emit_ldloc (mb, src_var);
921 mono_mb_emit_byte (mb, CEE_STLOC_0);
922 /* restore the old dst pointer */
923 mono_mb_emit_ldloc (mb, dst_var);
924 mono_mb_emit_byte (mb, CEE_STLOC_1);
926 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
930 char *msg = g_strdup_printf ("marshalling conversion %d not implemented", conv);
931 MonoException *exc = mono_get_exception_not_implemented (msg);
934 mono_raise_exception (exc);
940 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
942 MonoMarshalType *info;
946 emit_struct_conv(mb, klass->parent, to_object);
948 info = mono_marshal_load_type_info (klass);
950 if (info->native_size == 0)
953 if (klass->blittable) {
954 mono_mb_emit_byte (mb, CEE_LDLOC_1);
955 mono_mb_emit_byte (mb, CEE_LDLOC_0);
956 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
957 mono_mb_emit_byte (mb, CEE_PREFIX1);
958 mono_mb_emit_byte (mb, CEE_CPBLK);
962 for (i = 0; i < info->num_fields; i++) {
963 MonoMarshalNative ntype;
964 MonoMarshalConv conv;
965 MonoType *ftype = info->fields [i].field->type;
968 gboolean last_field = i < (info->num_fields -1) ? 0 : 1;
970 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
973 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, klass->unicode, &conv);
976 msize = klass->instance_size - info->fields [i].field->offset;
977 usize = info->native_size - info->fields [i].offset;
979 msize = info->fields [i + 1].field->offset - info->fields [i].field->offset;
980 usize = info->fields [i + 1].offset - info->fields [i].offset;
982 if ((msize < 0) || (usize < 0))
983 /* This happens with GC aware auto layout */
984 g_error ("Type %s which is passed to unmanaged code must have a StructLayout attribute", mono_type_full_name (&klass->byval_arg));
986 g_assert ((msize >= 0) && (usize >= 0));
989 case MONO_MARSHAL_CONV_NONE: {
992 if (ftype->byref || ftype->type == MONO_TYPE_I ||
993 ftype->type == MONO_TYPE_U) {
994 mono_mb_emit_byte (mb, CEE_LDLOC_1);
995 mono_mb_emit_byte (mb, CEE_LDLOC_0);
996 mono_mb_emit_byte (mb, CEE_LDIND_I);
997 mono_mb_emit_byte (mb, CEE_STIND_I);
1006 #if SIZEOF_VOID_P == 4
1009 mono_mb_emit_byte (mb, CEE_LDLOC_1);
1010 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1011 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1012 mono_mb_emit_byte (mb, CEE_STIND_I4);
1016 case MONO_TYPE_BOOLEAN:
1017 mono_mb_emit_byte (mb, CEE_LDLOC_1);
1018 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1019 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1020 mono_mb_emit_byte (mb, CEE_STIND_I1);
1024 case MONO_TYPE_CHAR:
1025 mono_mb_emit_byte (mb, CEE_LDLOC_1);
1026 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1027 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1028 mono_mb_emit_byte (mb, CEE_STIND_I2);
1032 #if SIZEOF_VOID_P == 8
1035 mono_mb_emit_byte (mb, CEE_LDLOC_1);
1036 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1037 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1038 mono_mb_emit_byte (mb, CEE_STIND_I8);
1041 mono_mb_emit_byte (mb, CEE_LDLOC_1);
1042 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1043 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1044 mono_mb_emit_byte (mb, CEE_STIND_R4);
1047 mono_mb_emit_byte (mb, CEE_LDLOC_1);
1048 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1049 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1050 mono_mb_emit_byte (mb, CEE_STIND_R8);
1052 case MONO_TYPE_VALUETYPE:
1053 if (ftype->data.klass->enumtype) {
1054 t = ftype->data.klass->enum_basetype->type;
1057 emit_struct_conv (mb, ftype->data.klass, to_object);
1060 g_warning ("marshaling type %02x not implemented", ftype->type);
1061 g_assert_not_reached ();
1067 emit_ptr_to_str_conv (mb, ftype, conv, usize, msize, info->fields [i].mspec);
1069 emit_str_to_ptr_conv (mb, ftype, conv, usize, msize, info->fields [i].mspec);
1073 mono_mb_emit_add_to_local (mb, 0, usize);
1074 mono_mb_emit_add_to_local (mb, 1, msize);
1076 mono_mb_emit_add_to_local (mb, 0, msize);
1077 mono_mb_emit_add_to_local (mb, 1, usize);
1083 emit_thread_interrupt_checkpoint (MonoMethodBuilder *mb)
1085 static MonoMethodSignature *state_check_sig = NULL;
1088 if (!state_check_sig) {
1089 state_check_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
1090 state_check_sig->ret = &mono_defaults.void_class->byval_arg;
1091 state_check_sig->pinvoke = 0;
1094 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1095 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1096 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, (gpointer) mono_thread_interruption_request_flag ()));
1097 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1098 pos_noabort = mono_mb_emit_branch (mb, CEE_BRFALSE);
1100 mono_mb_emit_native_call (mb, state_check_sig, mono_thread_interruption_checkpoint);
1102 mono_mb_patch_addr (mb, pos_noabort, mb->pos - (pos_noabort + 4));
1105 static MonoAsyncResult *
1106 mono_delegate_begin_invoke (MonoDelegate *delegate, gpointer *params)
1108 MonoMethodMessage *msg;
1109 MonoDelegate *async_callback;
1113 MonoMethod *method = NULL;
1116 g_assert (delegate);
1118 if (delegate->target && mono_object_class (delegate->target) == mono_defaults.transparent_proxy_class) {
1120 MonoTransparentProxy* tp = (MonoTransparentProxy *)delegate->target;
1121 if (!tp->remote_class->proxy_class->contextbound || tp->rp->context != (MonoObject *) mono_context_get ()) {
1123 // If the target is a proxy, make a direct call. Is proxy's work
1124 // to make the call asynchronous.
1126 MonoAsyncResult *ares;
1128 MonoArray *out_args;
1130 method = delegate->method_info->method;
1132 msg = mono_method_call_message_new (mono_marshal_method_from_wrapper (method), params, NULL, &async_callback, &state);
1133 handle = CreateEvent (NULL, TRUE, FALSE, NULL);
1134 ares = mono_async_result_new (mono_domain_get (), handle, state, handle);
1135 ares->async_delegate = (MonoObject *)delegate;
1136 ares->async_callback = (MonoObject *)async_callback;
1137 msg->async_result = ares;
1138 msg->call_type = CallType_BeginInvoke;
1140 mono_remoting_invoke ((MonoObject *)tp->rp, msg, &exc, &out_args);
1145 klass = delegate->object.vtable->klass;
1147 method = mono_get_delegate_invoke (klass);
1148 for (i = 0; i < klass->method.count; ++i) {
1149 if (klass->methods [i]->name[0] == 'B' &&
1150 !strcmp ("BeginInvoke", klass->methods [i]->name)) {
1151 method = klass->methods [i];
1156 g_assert (method != NULL);
1158 im = mono_get_delegate_invoke (method->klass);
1159 msg = mono_method_call_message_new (method, params, im, &async_callback, &state);
1161 return mono_thread_pool_add ((MonoObject *)delegate, msg, async_callback, state);
1165 mono_mb_emit_save_args (MonoMethodBuilder *mb, MonoMethodSignature *sig, gboolean save_this)
1167 int i, params_var, tmp_var;
1169 /* allocate local (pointer) *params[] */
1170 params_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1171 /* allocate local (pointer) tmp */
1172 tmp_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1174 /* alloate space on stack to store an array of pointers to the arguments */
1175 mono_mb_emit_icon (mb, sizeof (gpointer) * (sig->param_count + 1));
1176 mono_mb_emit_byte (mb, CEE_PREFIX1);
1177 mono_mb_emit_byte (mb, CEE_LOCALLOC);
1178 mono_mb_emit_stloc (mb, params_var);
1181 mono_mb_emit_ldloc (mb, params_var);
1182 mono_mb_emit_stloc (mb, tmp_var);
1184 if (save_this && sig->hasthis) {
1185 mono_mb_emit_ldloc (mb, tmp_var);
1186 mono_mb_emit_ldarg_addr (mb, 0);
1187 mono_mb_emit_byte (mb, CEE_STIND_I);
1188 /* tmp = tmp + sizeof (gpointer) */
1189 if (sig->param_count)
1190 mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
1194 for (i = 0; i < sig->param_count; i++) {
1195 mono_mb_emit_ldloc (mb, tmp_var);
1196 mono_mb_emit_ldarg_addr (mb, i + sig->hasthis);
1197 mono_mb_emit_byte (mb, CEE_STIND_I);
1198 /* tmp = tmp + sizeof (gpointer) */
1199 if (i < (sig->param_count - 1))
1200 mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
1207 mono_signature_to_name (MonoMethodSignature *sig, const char *prefix)
1211 GString *res = g_string_new ("");
1214 g_string_append (res, prefix);
1215 g_string_append_c (res, '_');
1218 mono_type_get_desc (res, sig->ret, FALSE);
1220 for (i = 0; i < sig->param_count; ++i) {
1221 g_string_append_c (res, '_');
1222 mono_type_get_desc (res, sig->params [i], FALSE);
1225 g_string_free (res, FALSE);
1230 * mono_marshal_get_string_encoding:
1232 * Return the string encoding which should be used for a given parameter.
1234 static MonoMarshalNative
1235 mono_marshal_get_string_encoding (MonoMethodPInvoke *piinfo, MonoMarshalSpec *spec)
1237 /* First try the parameter marshal info */
1239 if (spec->native == MONO_NATIVE_LPARRAY) {
1240 if (spec->data.array_data.elem_type != 0)
1241 return spec->data.array_data.elem_type;
1244 return spec->native;
1248 return MONO_NATIVE_LPSTR;
1250 /* Then try the method level marshal info */
1251 switch (piinfo->piflags & PINVOKE_ATTRIBUTE_CHAR_SET_MASK) {
1252 case PINVOKE_ATTRIBUTE_CHAR_SET_ANSI:
1253 return MONO_NATIVE_LPSTR;
1254 case PINVOKE_ATTRIBUTE_CHAR_SET_UNICODE:
1255 return MONO_NATIVE_LPWSTR;
1256 case PINVOKE_ATTRIBUTE_CHAR_SET_AUTO:
1257 return MONO_NATIVE_LPTSTR;
1259 return MONO_NATIVE_LPSTR;
1263 static inline MonoMethod*
1264 mono_marshal_find_in_cache (GHashTable *cache, gpointer key)
1268 EnterCriticalSection (&marshal_mutex);
1269 res = g_hash_table_lookup (cache, key);
1270 LeaveCriticalSection (&marshal_mutex);
1274 /* Create the method from the builder and place it in the cache */
1275 static inline MonoMethod*
1276 mono_mb_create_and_cache (GHashTable *cache, gpointer key,
1277 MonoMethodBuilder *mb, MonoMethodSignature *sig,
1282 EnterCriticalSection (&marshal_mutex);
1283 res = g_hash_table_lookup (cache, key);
1285 /* This does not acquire any locks */
1286 res = mono_mb_create_method (mb, sig, max_stack);
1287 g_hash_table_insert (cache, key, res);
1288 mono_g_hash_table_insert (wrapper_hash, res, key);
1291 /* Somebody created it before us */
1293 LeaveCriticalSection (&marshal_mutex);
1299 mono_marshal_method_from_wrapper (MonoMethod *wrapper)
1303 if (wrapper->wrapper_type == MONO_WRAPPER_NONE)
1306 EnterCriticalSection (&marshal_mutex);
1307 res = mono_g_hash_table_lookup (wrapper_hash, wrapper);
1308 LeaveCriticalSection (&marshal_mutex);
1310 if (res && wrapper->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)
1311 /* See mono_marshal_get_remoting_invoke_with_check */
1312 return (MonoMethod*)((char*)res - 1);
1318 mono_marshal_get_delegate_begin_invoke (MonoMethod *method)
1320 MonoMethodSignature *sig;
1321 static MonoMethodSignature *csig = NULL;
1322 MonoMethodBuilder *mb;
1328 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1329 !strcmp (method->name, "BeginInvoke"));
1331 sig = method->signature;
1333 cache = method->klass->image->delegate_begin_invoke_cache;
1334 if ((res = mono_marshal_find_in_cache (cache, sig)))
1337 g_assert (sig->hasthis);
1340 csig = mono_metadata_signature_alloc (method->klass->image, 2);
1342 /* MonoAsyncResult * begin_invoke (MonoDelegate *delegate, gpointer params[]) */
1343 csig->ret = &mono_defaults.object_class->byval_arg;
1344 csig->params [0] = &mono_defaults.object_class->byval_arg;
1345 csig->params [1] = &mono_defaults.int_class->byval_arg;
1348 name = mono_signature_to_name (sig, "begin_invoke");
1349 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_BEGIN_INVOKE);
1352 mb->method->save_lmf = 1;
1354 params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1356 mono_mb_emit_ldarg (mb, 0);
1357 mono_mb_emit_ldloc (mb, params_var);
1358 mono_mb_emit_native_call (mb, csig, mono_delegate_begin_invoke);
1359 emit_thread_interrupt_checkpoint (mb);
1360 mono_mb_emit_byte (mb, CEE_RET);
1362 res = mono_mb_create_and_cache (cache, sig, mb, sig, sig->param_count + 16);
1368 mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params)
1370 MonoDomain *domain = mono_domain_get ();
1371 MonoAsyncResult *ares;
1372 MonoMethod *method = NULL;
1373 MonoMethodSignature *sig;
1374 MonoMethodMessage *msg;
1375 MonoObject *res, *exc;
1376 MonoArray *out_args;
1380 g_assert (delegate);
1382 if (!delegate->method_info || !delegate->method_info->method)
1383 g_assert_not_reached ();
1385 klass = delegate->object.vtable->klass;
1387 for (i = 0; i < klass->method.count; ++i) {
1388 if (klass->methods [i]->name[0] == 'E' &&
1389 !strcmp ("EndInvoke", klass->methods [i]->name)) {
1390 method = klass->methods [i];
1395 g_assert (method != NULL);
1397 sig = method->signature;
1399 msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1401 ares = mono_array_get (msg->args, gpointer, sig->param_count - 1);
1404 if (delegate->target && mono_object_class (delegate->target) == mono_defaults.transparent_proxy_class) {
1405 MonoTransparentProxy* tp = (MonoTransparentProxy *)delegate->target;
1406 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
1407 mono_message_init (domain, msg, delegate->method_info, NULL);
1408 msg->call_type = CallType_EndInvoke;
1409 msg->async_result = ares;
1410 res = mono_remoting_invoke ((MonoObject *)tp->rp, msg, &exc, &out_args);
1413 res = mono_thread_pool_finish (ares, &out_args, &exc);
1416 char *strace = mono_string_to_utf8 (((MonoException*)exc)->stack_trace);
1418 tmp = g_strdup_printf ("%s\nException Rethrown at:\n", strace);
1420 ((MonoException*)exc)->stack_trace = mono_string_new (domain, tmp);
1422 mono_raise_exception ((MonoException*)exc);
1425 mono_method_return_message_restore (method, params, out_args);
1430 mono_mb_emit_restore_result (MonoMethodBuilder *mb, MonoType *return_type)
1432 if (return_type->byref)
1433 return_type = &mono_defaults.int_class->byval_arg;
1434 else if (return_type->type == MONO_TYPE_VALUETYPE && return_type->data.klass->enumtype)
1435 return_type = return_type->data.klass->enum_basetype;
1437 switch (return_type->type) {
1438 case MONO_TYPE_VOID:
1439 g_assert_not_reached ();
1442 case MONO_TYPE_STRING:
1443 case MONO_TYPE_CLASS:
1444 case MONO_TYPE_OBJECT:
1445 case MONO_TYPE_ARRAY:
1446 case MONO_TYPE_SZARRAY:
1450 case MONO_TYPE_BOOLEAN:
1451 mono_mb_emit_byte (mb, CEE_UNBOX);
1452 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1453 mono_mb_emit_byte (mb, CEE_LDIND_U1);
1456 mono_mb_emit_byte (mb, CEE_UNBOX);
1457 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1458 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1461 case MONO_TYPE_CHAR:
1462 mono_mb_emit_byte (mb, CEE_UNBOX);
1463 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1464 mono_mb_emit_byte (mb, CEE_LDIND_U2);
1467 mono_mb_emit_byte (mb, CEE_UNBOX);
1468 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1469 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1473 mono_mb_emit_byte (mb, CEE_UNBOX);
1474 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1475 mono_mb_emit_byte (mb, CEE_LDIND_I);
1478 mono_mb_emit_byte (mb, CEE_UNBOX);
1479 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1480 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1483 mono_mb_emit_byte (mb, CEE_UNBOX);
1484 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1485 mono_mb_emit_byte (mb, CEE_LDIND_U4);
1489 mono_mb_emit_byte (mb, CEE_UNBOX);
1490 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1491 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1494 mono_mb_emit_byte (mb, CEE_UNBOX);
1495 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1496 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1499 mono_mb_emit_byte (mb, CEE_UNBOX);
1500 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1501 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1503 case MONO_TYPE_VALUETYPE: {
1505 mono_mb_emit_byte (mb, CEE_UNBOX);
1506 class = mono_mb_add_data (mb, mono_class_from_mono_type (return_type));
1507 mono_mb_emit_i4 (mb, class);
1508 mono_mb_emit_byte (mb, CEE_LDOBJ);
1509 mono_mb_emit_i4 (mb, class);
1513 g_warning ("type 0x%x not handled", return_type->type);
1514 g_assert_not_reached ();
1517 mono_mb_emit_byte (mb, CEE_RET);
1521 mono_marshal_get_delegate_end_invoke (MonoMethod *method)
1523 MonoMethodSignature *sig;
1524 static MonoMethodSignature *csig = NULL;
1525 MonoMethodBuilder *mb;
1531 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1532 !strcmp (method->name, "EndInvoke"));
1534 sig = method->signature;
1536 cache = method->klass->image->delegate_end_invoke_cache;
1537 if ((res = mono_marshal_find_in_cache (cache, sig)))
1540 g_assert (sig->hasthis);
1543 csig = mono_metadata_signature_alloc (method->klass->image, 2);
1545 /* MonoObject *end_invoke (MonoDelegate *delegate, gpointer params[]) */
1546 csig->ret = &mono_defaults.object_class->byval_arg;
1547 csig->params [0] = &mono_defaults.object_class->byval_arg;
1548 csig->params [1] = &mono_defaults.int_class->byval_arg;
1551 name = mono_signature_to_name (sig, "end_invoke");
1552 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_END_INVOKE);
1555 mb->method->save_lmf = 1;
1557 params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1559 mono_mb_emit_ldarg (mb, 0);
1560 mono_mb_emit_ldloc (mb, params_var);
1561 mono_mb_emit_native_call (mb, csig, mono_delegate_end_invoke);
1562 emit_thread_interrupt_checkpoint (mb);
1564 if (sig->ret->type == MONO_TYPE_VOID) {
1565 mono_mb_emit_byte (mb, CEE_POP);
1566 mono_mb_emit_byte (mb, CEE_RET);
1568 mono_mb_emit_restore_result (mb, sig->ret);
1570 res = mono_mb_create_and_cache (cache, sig,
1571 mb, sig, sig->param_count + 16);
1578 mono_remoting_wrapper (MonoMethod *method, gpointer *params)
1580 MonoMethodMessage *msg;
1581 MonoTransparentProxy *this;
1582 MonoObject *res, *exc;
1583 MonoArray *out_args;
1585 this = *((MonoTransparentProxy **)params [0]);
1588 g_assert (((MonoObject *)this)->vtable->klass == mono_defaults.transparent_proxy_class);
1590 /* skip the this pointer */
1593 if (this->remote_class->proxy_class->contextbound && this->rp->context == (MonoObject *) mono_context_get ())
1596 MonoMethodSignature *sig = method->signature;
1597 int count = sig->param_count;
1598 gpointer* mparams = (gpointer*) alloca(count*sizeof(gpointer));
1600 for (i=0; i<count; i++) {
1601 MonoClass *class = mono_class_from_mono_type (sig->params [i]);
1602 if (class->valuetype) {
1603 if (sig->params [i]->byref)
1604 mparams[i] = *((gpointer *)params [i]);
1606 mparams[i] = params [i];
1608 mparams[i] = *((gpointer**)params [i]);
1612 return mono_runtime_invoke (method, this, mparams, NULL);
1615 msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1617 res = mono_remoting_invoke ((MonoObject *)this->rp, msg, &exc, &out_args);
1620 mono_raise_exception ((MonoException *)exc);
1622 mono_method_return_message_restore (method, params, out_args);
1628 mono_marshal_get_remoting_invoke (MonoMethod *method)
1630 MonoMethodSignature *sig;
1631 static MonoMethodSignature *csig = NULL;
1632 MonoMethodBuilder *mb;
1639 if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE)
1642 sig = method->signature;
1644 /* we cant remote methods without this pointer */
1648 cache = method->klass->image->remoting_invoke_cache;
1649 if ((res = mono_marshal_find_in_cache (cache, method)))
1653 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
1654 csig->params [0] = &mono_defaults.int_class->byval_arg;
1655 csig->params [1] = &mono_defaults.int_class->byval_arg;
1656 csig->ret = &mono_defaults.object_class->byval_arg;
1660 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE);
1661 mb->method->save_lmf = 1;
1663 params_var = mono_mb_emit_save_args (mb, sig, TRUE);
1665 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1666 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1667 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
1668 mono_mb_emit_ldloc (mb, params_var);
1669 mono_mb_emit_native_call (mb, csig, mono_remoting_wrapper);
1670 emit_thread_interrupt_checkpoint (mb);
1672 if (sig->ret->type == MONO_TYPE_VOID) {
1673 mono_mb_emit_byte (mb, CEE_POP);
1674 mono_mb_emit_byte (mb, CEE_RET);
1676 mono_mb_emit_restore_result (mb, sig->ret);
1679 res = mono_mb_create_and_cache (cache, method, mb, sig, sig->param_count + 16);
1686 mono_marshal_get_remoting_invoke_with_check (MonoMethod *method)
1688 MonoMethodSignature *sig;
1689 MonoMethodBuilder *mb;
1690 MonoMethod *res, *native;
1696 if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)
1699 sig = method->signature;
1701 /* we cant remote methods without this pointer */
1702 g_assert (sig->hasthis);
1704 cache = method->klass->image->remoting_invoke_cache;
1705 if ((res = mono_marshal_find_in_cache (cache, (char *)method + 1)))
1708 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK);
1710 mono_mb_emit_ldarg (mb, 0);
1711 pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
1713 native = mono_marshal_get_remoting_invoke (method);
1715 for (i = 0; i <= sig->param_count; i++)
1716 mono_mb_emit_ldarg (mb, i);
1718 mono_mb_emit_managed_call (mb, native, native->signature);
1719 mono_mb_emit_byte (mb, CEE_RET);
1721 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1723 for (i = 0; i <= sig->param_count; i++)
1724 mono_mb_emit_ldarg (mb, i);
1726 mono_mb_emit_managed_call (mb, method, method->signature);
1727 mono_mb_emit_byte (mb, CEE_RET);
1729 res = mono_mb_create_and_cache (cache, (char*)method + 1,
1730 mb, sig, sig->param_count + 16);
1737 * the returned method invokes all methods in a multicast delegate
1740 mono_marshal_get_delegate_invoke (MonoMethod *method)
1742 MonoMethodSignature *sig, *static_sig;
1744 MonoMethodBuilder *mb;
1750 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1751 !strcmp (method->name, "Invoke"));
1753 sig = method->signature;
1755 cache = method->klass->image->delegate_invoke_cache;
1756 if ((res = mono_marshal_find_in_cache (cache, sig)))
1759 static_sig = mono_metadata_signature_dup (sig);
1760 static_sig->hasthis = 0;
1762 name = mono_signature_to_name (sig, "invoke");
1763 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_INVOKE);
1766 /* allocate local 0 (object) */
1767 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1769 g_assert (sig->hasthis);
1773 * prev.Invoke( args .. );
1774 * return this.<target>( args .. );
1777 /* this wrapper can be used in unmanaged-managed transitions */
1778 emit_thread_interrupt_checkpoint (mb);
1780 /* get this->prev */
1781 mono_mb_emit_ldarg (mb, 0);
1782 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoMulticastDelegate, prev));
1783 mono_mb_emit_byte (mb, CEE_LDIND_I );
1784 mono_mb_emit_stloc (mb, 0);
1786 /* if prev != null */
1787 mono_mb_emit_ldloc (mb, 0);
1788 mono_mb_emit_byte (mb, CEE_BRFALSE);
1791 mono_mb_emit_i4 (mb, 0);
1794 mono_mb_emit_ldloc (mb, 0);
1795 for (i = 0; i < sig->param_count; i++)
1796 mono_mb_emit_ldarg (mb, i + 1);
1797 mono_mb_emit_managed_call (mb, method, method->signature);
1798 if (sig->ret->type != MONO_TYPE_VOID)
1799 mono_mb_emit_byte (mb, CEE_POP);
1801 /* continued or prev == null */
1802 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1804 /* get this->target */
1805 mono_mb_emit_ldarg (mb, 0);
1806 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, target));
1807 mono_mb_emit_byte (mb, CEE_LDIND_I );
1808 mono_mb_emit_stloc (mb, 0);
1810 /* if target != null */
1811 mono_mb_emit_ldloc (mb, 0);
1812 mono_mb_emit_byte (mb, CEE_BRFALSE);
1814 mono_mb_emit_i4 (mb, 0);
1816 /* then call this->method_ptr nonstatic */
1817 mono_mb_emit_ldloc (mb, 0);
1818 for (i = 0; i < sig->param_count; ++i)
1819 mono_mb_emit_ldarg (mb, i + 1);
1820 mono_mb_emit_ldarg (mb, 0);
1821 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1822 mono_mb_emit_byte (mb, CEE_LDIND_I );
1823 mono_mb_emit_byte (mb, CEE_CALLI);
1824 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
1826 mono_mb_emit_byte (mb, CEE_BR);
1828 mono_mb_emit_i4 (mb, 0);
1830 /* else [target == null] call this->method_ptr static */
1831 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1833 for (i = 0; i < sig->param_count; ++i)
1834 mono_mb_emit_ldarg (mb, i + 1);
1835 mono_mb_emit_ldarg (mb, 0);
1836 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1837 mono_mb_emit_byte (mb, CEE_LDIND_I );
1838 mono_mb_emit_byte (mb, CEE_CALLI);
1839 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, static_sig));
1842 mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
1843 mono_mb_emit_byte (mb, CEE_RET);
1845 res = mono_mb_create_and_cache (cache, sig,
1846 mb, sig, sig->param_count + 16);
1853 * generates IL code for the runtime invoke function
1854 * MonoObject *runtime_invoke (MonoObject *this, void **params, MonoObject **exc, void* method)
1856 * we also catch exceptions if exc != null
1859 mono_marshal_get_runtime_invoke (MonoMethod *method)
1861 MonoMethodSignature *sig, *csig, *callsig;
1862 MonoExceptionClause *clause;
1863 MonoMethodHeader *header;
1864 MonoMethodBuilder *mb;
1867 static MonoString *string_dummy = NULL;
1873 if (method->string_ctor) {
1874 static MonoMethodSignature *strsig = NULL;
1876 strsig = mono_metadata_signature_dup (method->signature);
1877 strsig->ret = &mono_defaults.string_class->byval_arg;
1882 callsig = method->signature;
1884 cache = method->klass->image->runtime_invoke_cache;
1885 if ((res = mono_marshal_find_in_cache (cache, callsig)))
1888 /* to make it work with our special string constructors */
1890 string_dummy = mono_string_new_wrapper ("dummy");
1892 sig = method->signature;
1894 csig = mono_metadata_signature_alloc (method->klass->image, 4);
1896 csig->ret = &mono_defaults.object_class->byval_arg;
1897 csig->params [0] = &mono_defaults.object_class->byval_arg;
1898 csig->params [1] = &mono_defaults.int_class->byval_arg;
1899 csig->params [2] = &mono_defaults.int_class->byval_arg;
1900 csig->params [3] = &mono_defaults.int_class->byval_arg;
1902 name = mono_signature_to_name (callsig, "runtime_invoke");
1903 mb = mono_mb_new (method->klass, name, MONO_WRAPPER_RUNTIME_INVOKE);
1906 /* allocate local 0 (object) tmp */
1907 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1908 /* allocate local 1 (object) exc */
1909 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1911 /* cond set *exc to null */
1912 mono_mb_emit_byte (mb, CEE_LDARG_2);
1913 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
1914 mono_mb_emit_byte (mb, 3);
1915 mono_mb_emit_byte (mb, CEE_LDARG_2);
1916 mono_mb_emit_byte (mb, CEE_LDNULL);
1917 mono_mb_emit_byte (mb, CEE_STIND_I);
1920 if (method->string_ctor) {
1921 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1922 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1923 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, string_dummy));
1925 mono_mb_emit_ldarg (mb, 0);
1926 if (method->klass->valuetype) {
1927 mono_mb_emit_byte (mb, CEE_UNBOX);
1928 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method->klass));
1933 for (i = 0; i < sig->param_count; i++) {
1934 MonoType *t = sig->params [i];
1937 mono_mb_emit_ldarg (mb, 1);
1939 mono_mb_emit_icon (mb, sizeof (gpointer) * i);
1940 mono_mb_emit_byte (mb, CEE_ADD);
1942 mono_mb_emit_byte (mb, CEE_LDIND_I);
1947 type = sig->params [i]->type;
1951 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1953 case MONO_TYPE_BOOLEAN:
1955 mono_mb_emit_byte (mb, CEE_LDIND_U1);
1958 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1961 case MONO_TYPE_CHAR:
1962 mono_mb_emit_byte (mb, CEE_LDIND_U2);
1966 mono_mb_emit_byte (mb, CEE_LDIND_I);
1969 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1972 mono_mb_emit_byte (mb, CEE_LDIND_U4);
1975 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1978 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1982 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1984 case MONO_TYPE_STRING:
1985 case MONO_TYPE_CLASS:
1986 case MONO_TYPE_ARRAY:
1988 case MONO_TYPE_SZARRAY:
1989 case MONO_TYPE_OBJECT:
1992 case MONO_TYPE_VALUETYPE:
1993 if (t->data.klass->enumtype) {
1994 type = t->data.klass->enum_basetype->type;
1997 mono_mb_emit_byte (mb, CEE_LDOBJ);
1998 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, t->data.klass));
2001 g_assert_not_reached ();
2005 mono_mb_emit_ldarg (mb, 3);
2006 mono_mb_emit_calli (mb, callsig);
2008 if (sig->ret->byref) {
2010 g_assert_not_reached ();
2014 switch (sig->ret->type) {
2015 case MONO_TYPE_VOID:
2016 if (!method->string_ctor)
2017 mono_mb_emit_byte (mb, CEE_LDNULL);
2019 case MONO_TYPE_BOOLEAN:
2020 case MONO_TYPE_CHAR:
2033 case MONO_TYPE_VALUETYPE:
2034 /* box value types */
2035 mono_mb_emit_byte (mb, CEE_BOX);
2036 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (sig->ret)));
2038 case MONO_TYPE_STRING:
2039 case MONO_TYPE_CLASS:
2040 case MONO_TYPE_ARRAY:
2041 case MONO_TYPE_SZARRAY:
2042 case MONO_TYPE_OBJECT:
2047 g_assert_not_reached ();
2050 mono_mb_emit_stloc (mb, 0);
2052 mono_mb_emit_byte (mb, CEE_LEAVE);
2054 mono_mb_emit_i4 (mb, 0);
2056 clause = g_new0 (MonoExceptionClause, 1);
2057 clause->flags = MONO_EXCEPTION_CLAUSE_FILTER;
2058 clause->try_len = mb->pos;
2061 clause->token_or_filter = mb->pos;
2063 mono_mb_emit_byte (mb, CEE_POP);
2064 mono_mb_emit_byte (mb, CEE_LDARG_2);
2065 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
2066 mono_mb_emit_byte (mb, CEE_PREFIX1);
2067 mono_mb_emit_byte (mb, CEE_CGT_UN);
2068 mono_mb_emit_byte (mb, CEE_PREFIX1);
2069 mono_mb_emit_byte (mb, CEE_ENDFILTER);
2071 clause->handler_offset = mb->pos;
2074 /* store exception */
2075 mono_mb_emit_stloc (mb, 1);
2077 mono_mb_emit_byte (mb, CEE_LDARG_2);
2078 mono_mb_emit_ldloc (mb, 1);
2079 mono_mb_emit_byte (mb, CEE_STIND_I);
2081 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
2082 mono_mb_emit_stloc (mb, 0);
2084 mono_mb_emit_byte (mb, CEE_LEAVE);
2085 mono_mb_emit_i4 (mb, 0);
2087 clause->handler_len = mb->pos - clause->handler_offset;
2090 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2091 mono_mb_emit_ldloc (mb, 0);
2092 mono_mb_emit_byte (mb, CEE_RET);
2094 res = mono_mb_create_and_cache (cache, callsig, mb, csig, sig->param_count + 16);
2097 header = ((MonoMethodNormal *)res)->header;
2098 header->num_clauses = 1;
2099 header->clauses = clause;
2105 * generates IL code to call managed methods from unmanaged code
2108 mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this, MonoMarshalSpec **mspecs)
2110 MonoMethodSignature *sig, *csig;
2111 MonoMethodBuilder *mb;
2112 MonoClass *klass = NULL;
2115 int i, pos = 0, *tmp_locals;
2116 static MonoMethodSignature *alloc_sig = NULL;
2119 g_assert (method != NULL);
2120 g_assert (!method->signature->pinvoke);
2122 cache = method->klass->image->managed_wrapper_cache;
2123 if (!this && (res = mono_marshal_find_in_cache (cache, method)))
2126 /* Under MS, the allocation should be done using CoTaskMemAlloc */
2128 alloc_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
2129 alloc_sig->params [0] = &mono_defaults.int_class->byval_arg;
2130 alloc_sig->ret = &mono_defaults.int_class->byval_arg;
2131 alloc_sig->pinvoke = 1;
2135 /* fime: howto free that memory ? */
2138 sig = method->signature;
2140 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_NATIVE_TO_MANAGED);
2142 /* allocate local 0 (pointer) src_ptr */
2143 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2144 /* allocate local 1 (pointer) dst_ptr */
2145 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2146 /* allocate local 2 (boolean) delete_old */
2147 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2149 if (!MONO_TYPE_IS_VOID(sig->ret)) {
2150 /* allocate local 3 to store the return value */
2151 mono_mb_add_local (mb, sig->ret);
2154 mono_mb_emit_icon (mb, 0);
2155 mono_mb_emit_byte (mb, CEE_STLOC_2);
2157 /* we copy the signature, so that we can modify it */
2158 csig = mono_metadata_signature_dup (sig);
2162 #ifdef PLATFORM_WIN32
2164 * Under windows, delegates passed to native code must use the STDCALL
2165 * calling convention.
2167 csig->call_convention = MONO_CALL_STDCALL;
2170 /* fixme: howto handle this ? */
2174 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2175 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
2176 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, this));
2181 g_assert_not_reached ();
2186 /* we first do all conversions */
2187 tmp_locals = alloca (sizeof (int) * sig->param_count);
2188 for (i = 0; i < sig->param_count; i ++) {
2189 MonoType *t = sig->params [i];
2190 MonoMarshalSpec *spec = mspecs [i + 1];
2194 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
2197 MonoMethod *marshal_native_to_managed;
2198 MonoMethod *get_instance;
2200 /* FIXME: Call CleanUpNativeData after the call */
2202 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
2203 g_assert (mtype != NULL);
2204 mklass = mono_class_from_mono_type (mtype);
2205 g_assert (mklass != NULL);
2207 marshal_native_to_managed = mono_find_method_by_name (mklass, "MarshalNativeToManaged", 1);
2208 g_assert (marshal_native_to_managed);
2209 get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
2210 g_assert (get_instance);
2213 case MONO_TYPE_CLASS:
2214 case MONO_TYPE_OBJECT:
2215 case MONO_TYPE_STRING:
2216 case MONO_TYPE_ARRAY:
2217 case MONO_TYPE_SZARRAY:
2221 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2223 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
2225 mono_mb_emit_byte (mb, CEE_CALL);
2226 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
2228 mono_mb_emit_ldarg (mb, i);
2230 mono_mb_emit_byte (mb, CEE_CALLVIRT);
2231 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_native_to_managed));
2233 mono_mb_emit_stloc (mb, tmp_locals [i]);
2236 g_warning ("custom marshalling of type %x is currently not supported", t->type);
2237 g_assert_not_reached ();
2244 case MONO_TYPE_CLASS: {
2245 klass = t->data.klass;
2247 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2249 if (klass->delegate) {
2250 g_assert (!t->byref);
2251 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2252 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
2253 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2254 mono_mb_emit_ldarg (mb, i);
2255 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2256 mono_mb_emit_byte (mb, CEE_MONO_FUNC2);
2257 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_FTN_DEL);
2258 mono_mb_emit_stloc (mb, tmp_locals [i]);
2262 /* FIXME: Raise a MarshalDirectiveException here */
2263 g_assert ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT);
2265 if (t->attrs & PARAM_ATTRIBUTE_OUT) {
2266 mono_mb_emit_byte (mb, CEE_LDNULL);
2267 mono_mb_emit_stloc (mb, tmp_locals [i]);
2272 mono_mb_emit_ldarg (mb, i);
2276 /* Check for NULL and raise an exception */
2277 mono_mb_emit_byte (mb, CEE_BRTRUE);
2279 mono_mb_emit_i4 (mb, 0);
2281 mono_mb_emit_exception (mb, "ArgumentNullException", NULL);
2283 mono_mb_patch_addr (mb, pos2, mb->pos - (pos2 + 4));
2284 mono_mb_emit_ldarg (mb, i);
2285 mono_mb_emit_byte (mb, CEE_LDIND_I);
2288 mono_mb_emit_byte (mb, CEE_STLOC_0);
2290 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
2291 mono_mb_emit_stloc (mb, tmp_locals [i]);
2293 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2294 mono_mb_emit_byte (mb, CEE_BRFALSE);
2296 mono_mb_emit_i4 (mb, 0);
2298 /* Create and set dst */
2299 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2300 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
2301 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2302 mono_mb_emit_stloc (mb, tmp_locals [i]);
2303 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2304 mono_mb_emit_icon (mb, sizeof (MonoObject));
2305 mono_mb_emit_byte (mb, CEE_ADD);
2306 mono_mb_emit_byte (mb, CEE_STLOC_1);
2308 /* emit valuetype conversion code */
2309 emit_struct_conv (mb, klass, TRUE);
2311 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2314 case MONO_TYPE_VALUETYPE:
2316 klass = sig->params [i]->data.klass;
2317 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2318 klass->blittable || klass->enumtype)
2321 tmp_locals [i] = mono_mb_add_local (mb, &klass->byval_arg);
2324 mono_mb_emit_ldarg (mb, i);
2326 mono_mb_emit_ldarg_addr (mb, i);
2327 mono_mb_emit_byte (mb, CEE_STLOC_0);
2330 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2331 mono_mb_emit_byte (mb, CEE_BRFALSE);
2333 mono_mb_emit_i4 (mb, 0);
2336 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2337 mono_mb_emit_byte (mb, CEE_STLOC_1);
2339 /* emit valuetype convnversion code code */
2340 emit_struct_conv (mb, klass, TRUE);
2343 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2345 case MONO_TYPE_STRING: {
2346 MonoMarshalNative encoding = mono_marshal_get_string_encoding (NULL, spec);
2351 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2352 csig->params [i] = &mono_defaults.int_class->byval_arg;
2354 mono_mb_emit_ldarg (mb, i);
2355 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2356 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2359 case MONO_NATIVE_LPWSTR:
2360 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPWSTR_STR);
2362 case MONO_NATIVE_LPSTR:
2363 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
2366 char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding);
2367 MonoException *exc = mono_get_exception_not_implemented (msg);
2370 mono_raise_exception (exc);
2374 mono_mb_emit_stloc (mb, tmp_locals [i]);
2377 case MONO_TYPE_ARRAY:
2378 case MONO_TYPE_SZARRAY:
2382 klass = mono_class_from_mono_type (t);
2384 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2385 csig->params [i] = &mono_defaults.int_class->byval_arg;
2387 g_warning ("array marshaling not implemented");
2388 g_assert_not_reached ();
2393 for (i = 0; i < sig->param_count; i++) {
2394 MonoType *t = sig->params [i];
2397 case MONO_TYPE_BOOLEAN:
2411 mono_mb_emit_ldarg (mb, i);
2413 case MONO_TYPE_STRING:
2415 mono_mb_emit_ldarg (mb, i);
2417 g_assert (tmp_locals [i]);
2418 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2421 case MONO_TYPE_CLASS:
2423 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2425 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2427 case MONO_TYPE_ARRAY:
2428 case MONO_TYPE_SZARRAY:
2429 case MONO_TYPE_OBJECT:
2431 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2433 mono_mb_emit_ldarg (mb, i);
2435 case MONO_TYPE_VALUETYPE:
2436 klass = sig->params [i]->data.klass;
2437 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2438 klass->blittable || klass->enumtype) {
2439 mono_mb_emit_ldarg (mb, i);
2443 g_assert (tmp_locals [i]);
2445 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2447 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2450 g_warning ("type 0x%02x unknown", t->type);
2451 g_assert_not_reached ();
2455 emit_thread_interrupt_checkpoint (mb);
2456 mono_mb_emit_managed_call (mb, method, NULL);
2458 if (!sig->ret->byref) {
2459 switch (sig->ret->type) {
2460 case MONO_TYPE_VOID:
2462 case MONO_TYPE_BOOLEAN:
2476 case MONO_TYPE_OBJECT:
2477 mono_mb_emit_byte (mb, CEE_STLOC_3);
2479 case MONO_TYPE_STRING:
2480 csig->ret = &mono_defaults.int_class->byval_arg;
2482 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2483 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2484 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
2485 mono_mb_emit_byte (mb, CEE_STLOC_3);
2487 case MONO_TYPE_VALUETYPE:
2488 klass = sig->ret->data.klass;
2489 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2490 klass->blittable || klass->enumtype)
2493 /* load pointer to returned value type */
2494 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2495 mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
2497 /* store the address of the source into local variable 0 */
2498 mono_mb_emit_byte (mb, CEE_STLOC_0);
2499 /* allocate space for the native struct and
2500 * store the address into dst_ptr */
2501 retobj_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2502 g_assert (retobj_var);
2503 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2504 mono_mb_emit_byte (mb, CEE_CONV_I);
2505 mono_mb_emit_native_call (mb, alloc_sig, mono_marshal_alloc);
2506 emit_thread_interrupt_checkpoint (mb);
2507 mono_mb_emit_byte (mb, CEE_STLOC_1);
2508 mono_mb_emit_byte (mb, CEE_LDLOC_1);
2509 mono_mb_emit_stloc (mb, retobj_var);
2511 /* emit valuetype conversion code */
2512 emit_struct_conv (mb, klass, FALSE);
2514 case MONO_TYPE_CLASS: {
2517 klass = sig->ret->data.klass;
2519 /* FIXME: Raise a MarshalDirectiveException here */
2520 g_assert ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT);
2522 mono_mb_emit_byte (mb, CEE_STLOC_0);
2523 /* Check for null */
2524 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2525 pos = mono_mb_emit_branch (mb, CEE_BRTRUE);
2526 mono_mb_emit_byte (mb, CEE_LDNULL);
2527 mono_mb_emit_byte (mb, CEE_STLOC_3);
2528 pos2 = mono_mb_emit_branch (mb, CEE_BR);
2530 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2533 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2534 mono_mb_emit_icon (mb, sizeof (MonoObject));
2535 mono_mb_emit_byte (mb, CEE_ADD);
2536 mono_mb_emit_byte (mb, CEE_STLOC_0);
2538 /* Allocate and set dest */
2539 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2540 mono_mb_emit_byte (mb, CEE_CONV_I);
2541 mono_mb_emit_native_call (mb, alloc_sig, mono_marshal_alloc);
2542 emit_thread_interrupt_checkpoint (mb);
2543 mono_mb_emit_byte (mb, CEE_DUP);
2544 mono_mb_emit_byte (mb, CEE_STLOC_1);
2545 mono_mb_emit_byte (mb, CEE_STLOC_3);
2547 emit_struct_conv (mb, klass, FALSE);
2549 mono_mb_patch_addr (mb, pos2, mb->pos - (pos2 + 4));
2553 g_warning ("return type 0x%02x unknown", sig->ret->type);
2554 g_assert_not_reached ();
2557 mono_mb_emit_byte (mb, CEE_STLOC_3);
2560 /* Convert byref arguments back */
2561 for (i = 0; i < sig->param_count; i ++) {
2562 MonoType *t = sig->params [i];
2568 case MONO_TYPE_CLASS: {
2571 klass = t->data.klass;
2573 /* Check for null */
2574 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2575 pos = mono_mb_emit_branch (mb, CEE_BRTRUE);
2576 mono_mb_emit_ldarg (mb, i);
2577 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
2578 mono_mb_emit_byte (mb, CEE_STIND_I);
2579 pos2 = mono_mb_emit_branch (mb, CEE_BR);
2581 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2584 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2585 mono_mb_emit_icon (mb, sizeof (MonoObject));
2586 mono_mb_emit_byte (mb, CEE_ADD);
2587 mono_mb_emit_byte (mb, CEE_STLOC_0);
2589 /* Allocate and set dest */
2590 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2591 mono_mb_emit_byte (mb, CEE_CONV_I);
2592 mono_mb_emit_native_call (mb, alloc_sig, mono_marshal_alloc);
2593 emit_thread_interrupt_checkpoint (mb);
2594 mono_mb_emit_byte (mb, CEE_STLOC_1);
2596 /* Update argument pointer */
2597 mono_mb_emit_ldarg (mb, i);
2598 mono_mb_emit_byte (mb, CEE_LDLOC_1);
2599 mono_mb_emit_byte (mb, CEE_STIND_I);
2601 /* emit valuetype conversion code */
2602 emit_struct_conv (mb, klass, FALSE);
2604 mono_mb_patch_addr (mb, pos2, mb->pos - (pos2 + 4));
2611 mono_mb_emit_ldloc (mb, retobj_var);
2612 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2613 mono_mb_emit_byte (mb, CEE_MONO_RETOBJ);
2614 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2617 if (!MONO_TYPE_IS_VOID(sig->ret))
2618 mono_mb_emit_byte (mb, CEE_LDLOC_3);
2619 mono_mb_emit_byte (mb, CEE_RET);
2623 res = mono_mb_create_and_cache (cache, method,
2624 mb, csig, sig->param_count + 16);
2626 res = mono_mb_create_method (mb, csig, sig->param_count + 16);
2629 //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));
2635 * mono_marshal_get_ldfld_wrapper:
2636 * @type: the type of the field
2638 * This method generates a function which can be use to load a field with type
2639 * @type from an object. The generated function has the following signature:
2640 * <@type> ldfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset)
2643 mono_marshal_get_ldfld_wrapper (MonoType *type)
2645 MonoMethodSignature *sig, *csig;
2646 MonoMethodBuilder *mb;
2649 static GHashTable *ldfld_hash = NULL;
2651 int t, pos0, pos1 = 0;
2656 if (type->type == MONO_TYPE_SZARRAY) {
2657 klass = mono_defaults.array_class;
2658 } else if (type->type == MONO_TYPE_VALUETYPE) {
2659 klass = type->data.klass;
2660 if (klass->enumtype) {
2661 t = klass->enum_basetype->type;
2662 klass = mono_class_from_mono_type (klass->enum_basetype);
2664 } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
2665 t == MONO_TYPE_CLASS) {
2666 klass = mono_defaults.object_class;
2667 } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
2668 klass = mono_defaults.int_class;
2670 klass = mono_class_from_mono_type (type);
2673 klass = mono_defaults.int_class;
2676 EnterCriticalSection (&marshal_mutex);
2678 ldfld_hash = g_hash_table_new (NULL, NULL);
2679 res = g_hash_table_lookup (ldfld_hash, klass);
2680 LeaveCriticalSection (&marshal_mutex);
2684 name = g_strdup_printf ("__ldfld_wrapper_%s.%s", klass->name_space, klass->name);
2685 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_LDFLD);
2688 mb->method->save_lmf = 1;
2690 sig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
2691 sig->params [0] = &mono_defaults.object_class->byval_arg;
2692 sig->params [1] = &mono_defaults.int_class->byval_arg;
2693 sig->params [2] = &mono_defaults.int_class->byval_arg;
2694 sig->params [3] = &mono_defaults.int_class->byval_arg;
2695 sig->ret = &klass->byval_arg;
2697 mono_mb_emit_ldarg (mb, 0);
2698 pos0 = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
2700 mono_mb_emit_ldarg (mb, 0);
2701 mono_mb_emit_ldarg (mb, 1);
2702 mono_mb_emit_ldarg (mb, 2);
2704 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
2705 csig->params [0] = &mono_defaults.object_class->byval_arg;
2706 csig->params [1] = &mono_defaults.int_class->byval_arg;
2707 csig->params [2] = &mono_defaults.int_class->byval_arg;
2708 csig->ret = &klass->this_arg;
2711 mono_mb_emit_native_call (mb, csig, mono_load_remote_field_new);
2712 emit_thread_interrupt_checkpoint (mb);
2714 if (klass->valuetype) {
2715 mono_mb_emit_byte (mb, CEE_UNBOX);
2716 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2717 mono_mb_emit_byte (mb, CEE_BR);
2719 mono_mb_emit_i4 (mb, 0);
2721 mono_mb_emit_byte (mb, CEE_RET);
2725 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
2727 mono_mb_emit_ldarg (mb, 0);
2728 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2729 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2730 mono_mb_emit_ldarg (mb, 3);
2731 mono_mb_emit_byte (mb, CEE_ADD);
2733 if (klass->valuetype)
2734 mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
2739 case MONO_TYPE_BOOLEAN:
2740 mono_mb_emit_byte (mb, CEE_LDIND_I1);
2742 case MONO_TYPE_CHAR:
2745 mono_mb_emit_byte (mb, CEE_LDIND_I2);
2749 mono_mb_emit_byte (mb, CEE_LDIND_I4);
2753 mono_mb_emit_byte (mb, CEE_LDIND_I8);
2756 mono_mb_emit_byte (mb, CEE_LDIND_R4);
2759 mono_mb_emit_byte (mb, CEE_LDIND_R8);
2761 case MONO_TYPE_ARRAY:
2763 case MONO_TYPE_FNPTR:
2764 case MONO_TYPE_SZARRAY:
2765 case MONO_TYPE_OBJECT:
2766 case MONO_TYPE_CLASS:
2767 case MONO_TYPE_STRING:
2770 mono_mb_emit_byte (mb, CEE_LDIND_I);
2772 case MONO_TYPE_VALUETYPE:
2773 g_assert (!klass->enumtype);
2774 mono_mb_emit_byte (mb, CEE_LDOBJ);
2775 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2778 g_warning ("type %x not implemented", type->type);
2779 g_assert_not_reached ();
2782 mono_mb_emit_byte (mb, CEE_RET);
2784 res = mono_mb_create_and_cache (ldfld_hash, klass,
2785 mb, sig, sig->param_count + 16);
2792 * mono_marshal_get_stfld_wrapper:
2793 * @type: the type of the field
2795 * This method generates a function which can be use to store a field with type
2796 * @type. The generated function has the following signature:
2797 * void stfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset, <@type> val)
2800 mono_marshal_get_stfld_wrapper (MonoType *type)
2802 MonoMethodSignature *sig, *csig;
2803 MonoMethodBuilder *mb;
2806 static GHashTable *stfld_hash = NULL;
2813 if (type->type == MONO_TYPE_SZARRAY) {
2814 klass = mono_defaults.array_class;
2815 } else if (type->type == MONO_TYPE_VALUETYPE) {
2816 klass = type->data.klass;
2817 if (klass->enumtype) {
2818 t = klass->enum_basetype->type;
2819 klass = mono_class_from_mono_type (klass->enum_basetype);
2821 } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
2822 t == MONO_TYPE_CLASS) {
2823 klass = mono_defaults.object_class;
2824 } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
2825 klass = mono_defaults.int_class;
2827 klass = mono_class_from_mono_type (type);
2830 klass = mono_defaults.int_class;
2833 EnterCriticalSection (&marshal_mutex);
2835 stfld_hash = g_hash_table_new (NULL, NULL);
2836 res = g_hash_table_lookup (stfld_hash, klass);
2837 LeaveCriticalSection (&marshal_mutex);
2841 name = g_strdup_printf ("__stfld_wrapper_%s.%s", klass->name_space, klass->name);
2842 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_STFLD);
2845 mb->method->save_lmf = 1;
2847 sig = mono_metadata_signature_alloc (mono_defaults.corlib, 5);
2848 sig->params [0] = &mono_defaults.object_class->byval_arg;
2849 sig->params [1] = &mono_defaults.int_class->byval_arg;
2850 sig->params [2] = &mono_defaults.int_class->byval_arg;
2851 sig->params [3] = &mono_defaults.int_class->byval_arg;
2852 sig->params [4] = &klass->byval_arg;
2853 sig->ret = &mono_defaults.void_class->byval_arg;
2855 mono_mb_emit_ldarg (mb, 0);
2856 pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
2858 mono_mb_emit_ldarg (mb, 0);
2859 mono_mb_emit_ldarg (mb, 1);
2860 mono_mb_emit_ldarg (mb, 2);
2861 mono_mb_emit_ldarg (mb, 4);
2863 if (klass->valuetype) {
2864 mono_mb_emit_byte (mb, CEE_BOX);
2865 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2868 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
2869 csig->params [0] = &mono_defaults.object_class->byval_arg;
2870 csig->params [1] = &mono_defaults.int_class->byval_arg;
2871 csig->params [2] = &mono_defaults.int_class->byval_arg;
2872 csig->params [3] = &klass->this_arg;
2873 csig->ret = &mono_defaults.void_class->byval_arg;
2876 mono_mb_emit_native_call (mb, csig, mono_store_remote_field_new);
2877 emit_thread_interrupt_checkpoint (mb);
2879 mono_mb_emit_byte (mb, CEE_RET);
2881 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2883 mono_mb_emit_ldarg (mb, 0);
2884 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2885 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2886 mono_mb_emit_ldarg (mb, 3);
2887 mono_mb_emit_byte (mb, CEE_ADD);
2888 mono_mb_emit_ldarg (mb, 4);
2893 case MONO_TYPE_BOOLEAN:
2894 mono_mb_emit_byte (mb, CEE_STIND_I1);
2896 case MONO_TYPE_CHAR:
2899 mono_mb_emit_byte (mb, CEE_STIND_I2);
2903 mono_mb_emit_byte (mb, CEE_STIND_I4);
2907 mono_mb_emit_byte (mb, CEE_STIND_I8);
2910 mono_mb_emit_byte (mb, CEE_STIND_R4);
2913 mono_mb_emit_byte (mb, CEE_STIND_R8);
2915 case MONO_TYPE_ARRAY:
2917 case MONO_TYPE_FNPTR:
2918 case MONO_TYPE_SZARRAY:
2919 case MONO_TYPE_OBJECT:
2920 case MONO_TYPE_CLASS:
2921 case MONO_TYPE_STRING:
2924 mono_mb_emit_byte (mb, CEE_STIND_I);
2926 case MONO_TYPE_VALUETYPE:
2927 g_assert (!klass->enumtype);
2928 mono_mb_emit_byte (mb, CEE_STOBJ);
2929 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2932 g_warning ("type %x not implemented", type->type);
2933 g_assert_not_reached ();
2936 mono_mb_emit_byte (mb, CEE_RET);
2938 res = mono_mb_create_and_cache (stfld_hash, klass,
2939 mb, sig, sig->param_count + 16);
2946 * generates IL code for the icall wrapper (the generated method
2947 * calls the unmanaged code in func)
2950 mono_marshal_get_icall_wrapper (MonoMethodSignature *sig, const char *name, gconstpointer func)
2952 MonoMethodSignature *csig;
2953 MonoMethodBuilder *mb;
2957 g_assert (sig->pinvoke);
2959 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_MANAGED_TO_NATIVE);
2961 mb->method->save_lmf = 1;
2963 /* we copy the signature, so that we can modify it */
2966 mono_mb_emit_byte (mb, CEE_LDARG_0);
2968 for (i = 0; i < sig->param_count; i++)
2969 mono_mb_emit_ldarg (mb, i + sig->hasthis);
2971 mono_mb_emit_native_call (mb, sig, (gpointer) func);
2972 emit_thread_interrupt_checkpoint (mb);
2973 mono_mb_emit_byte (mb, CEE_RET);
2975 csig = mono_metadata_signature_dup (sig);
2978 res = mono_mb_create_method (mb, csig, csig->param_count + 16);
2985 * mono_marshal_get_native_wrapper:
2986 * @method: The MonoMethod to wrap.
2988 * generates IL code for the pinvoke wrapper (the generated method
2989 * calls the unmanaged code in method->addr)
2992 mono_marshal_get_native_wrapper (MonoMethod *method)
2994 MonoMethodSignature *sig, *csig;
2995 MonoMethodPInvoke *piinfo;
2996 MonoMethodBuilder *mb;
2997 MonoMarshalSpec **mspecs;
3001 gboolean pinvoke = FALSE;
3002 int i, pos, argnum, *tmp_locals;
3004 const char *exc_class = "MissingMethodException";
3005 const char *exc_arg = NULL;
3007 g_assert (method != NULL);
3008 g_assert (method->signature->pinvoke);
3010 cache = method->klass->image->native_wrapper_cache;
3011 if ((res = mono_marshal_find_in_cache (cache, method)))
3014 sig = method->signature;
3016 if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
3017 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
3020 if (!method->addr) {
3022 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
3024 method->addr = mono_lookup_internal_call (method);
3027 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_MANAGED_TO_NATIVE);
3029 mb->method->save_lmf = 1;
3031 piinfo = (MonoMethodPInvoke *)method;
3033 if (!method->addr) {
3034 mono_mb_emit_exception (mb, exc_class, exc_arg);
3035 csig = mono_metadata_signature_dup (sig);
3037 res = mono_mb_create_and_cache (cache, method,
3038 mb, csig, csig->param_count + 16);
3043 /* internal calls: we simply push all arguments and call the method (no conversions) */
3044 if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
3046 /* hack - string constructors returns a value */
3047 if (method->string_ctor) {
3048 csig = mono_metadata_signature_dup (sig);
3049 csig->ret = &mono_defaults.string_class->byval_arg;
3054 mono_mb_emit_byte (mb, CEE_LDARG_0);
3056 for (i = 0; i < sig->param_count; i++)
3057 mono_mb_emit_ldarg (mb, i + sig->hasthis);
3059 g_assert (method->addr);
3060 mono_mb_emit_native_call (mb, csig, method->addr);
3061 emit_thread_interrupt_checkpoint (mb);
3062 mono_mb_emit_byte (mb, CEE_RET);
3064 csig = mono_metadata_signature_dup (csig);
3066 res = mono_mb_create_and_cache (cache, method,
3067 mb, csig, csig->param_count + 16);
3074 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
3075 mono_method_get_marshal_info (method, mspecs);
3077 /* pinvoke: we need to convert the arguments if necessary */
3079 /* we copy the signature, so that we can set pinvoke to 0 */
3080 csig = mono_metadata_signature_dup (sig);
3083 /* we allocate local for use with emit_struct_conv() */
3084 /* allocate local 0 (pointer) src_ptr */
3085 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3086 /* allocate local 1 (pointer) dst_ptr */
3087 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3088 /* allocate local 2 (boolean) delete_old */
3089 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
3091 /* delete_old = FALSE */
3092 mono_mb_emit_icon (mb, 0);
3093 mono_mb_emit_byte (mb, CEE_STLOC_2);
3095 if (!MONO_TYPE_IS_VOID(sig->ret)) {
3096 /* allocate local 3 to store the return value */
3097 mono_mb_add_local (mb, sig->ret);
3100 if (mspecs [0] && mspecs [0]->native == MONO_NATIVE_CUSTOM) {
3101 /* Return type custom marshaling */
3103 * Since we can't determine the return type of the unmanaged function,
3104 * we assume it returns a pointer, and pass that pointer to
3105 * MarshalNativeToManaged.
3107 csig->ret = &mono_defaults.int_class->byval_arg;
3110 /* we first do all conversions */
3111 tmp_locals = alloca (sizeof (int) * sig->param_count);
3113 for (i = 0; i < sig->param_count; i ++) {
3114 MonoType *t = sig->params [i];
3115 MonoMarshalSpec *spec = mspecs [i + 1];
3117 argnum = i + sig->hasthis;
3120 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
3123 MonoMethod *marshal_managed_to_native;
3124 MonoMethod *get_instance;
3126 /* FIXME: Call CleanUpNativeData after the call */
3128 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
3129 g_assert (mtype != NULL);
3130 mklass = mono_class_from_mono_type (mtype);
3131 g_assert (mklass != NULL);
3133 marshal_managed_to_native = mono_find_method_by_name (mklass, "MarshalManagedToNative", 1);
3134 g_assert (marshal_managed_to_native);
3135 get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
3136 g_assert (get_instance);
3139 case MONO_TYPE_CLASS:
3140 case MONO_TYPE_OBJECT:
3141 case MONO_TYPE_STRING:
3142 case MONO_TYPE_ARRAY:
3143 case MONO_TYPE_SZARRAY:
3144 case MONO_TYPE_VALUETYPE:
3148 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3150 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
3152 mono_mb_emit_byte (mb, CEE_CALL);
3153 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
3155 mono_mb_emit_ldarg (mb, argnum);
3157 if (t->type == MONO_TYPE_VALUETYPE) {
3159 * Since we can't determine the type of the argument, we
3160 * will assume the unmanaged function takes a pointer.
3162 csig->params [i] = &mono_defaults.int_class->byval_arg;
3164 mono_mb_emit_byte (mb, CEE_BOX);
3165 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (t)));
3168 mono_mb_emit_byte (mb, CEE_CALLVIRT);
3169 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_managed_to_native));
3171 mono_mb_emit_stloc (mb, tmp_locals [i]);
3175 g_warning ("custom marshalling of type %x is currently not supported", t->type);
3176 g_assert_not_reached ();
3182 if (spec && spec->native == MONO_NATIVE_ASANY) {
3183 MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, NULL);
3185 g_assert (t->type == MONO_TYPE_OBJECT);
3186 g_assert (!t->byref);
3188 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3189 mono_mb_emit_ldarg (mb, argnum);
3190 mono_mb_emit_icon (mb, encoding);
3191 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3192 mono_mb_emit_byte (mb, CEE_MONO_FUNC2);
3193 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_ASANY);
3194 mono_mb_emit_stloc (mb, tmp_locals [i]);
3199 case MONO_TYPE_VALUETYPE:
3200 klass = t->data.klass;
3202 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3203 klass->blittable || klass->enumtype)
3206 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3208 /* store the address of the source into local variable 0 */
3210 mono_mb_emit_ldarg (mb, argnum);
3212 mono_mb_emit_ldarg_addr (mb, argnum);
3214 mono_mb_emit_byte (mb, CEE_STLOC_0);
3216 /* allocate space for the native struct and
3217 * store the address into local variable 1 (dest) */
3218 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
3219 mono_mb_emit_byte (mb, CEE_PREFIX1);
3220 mono_mb_emit_byte (mb, CEE_LOCALLOC);
3221 mono_mb_emit_stloc (mb, tmp_locals [i]);
3224 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3225 mono_mb_emit_byte (mb, CEE_BRFALSE);
3227 mono_mb_emit_i4 (mb, 0);
3231 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3232 mono_mb_emit_byte (mb, CEE_STLOC_1);
3234 /* emit valuetype conversion code */
3235 emit_struct_conv (mb, klass, FALSE);
3238 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3240 case MONO_TYPE_STRING: {
3241 MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, spec);
3243 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3244 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3247 if (t->attrs & PARAM_ATTRIBUTE_OUT)
3250 mono_mb_emit_ldarg (mb, argnum);
3251 mono_mb_emit_byte (mb, CEE_LDIND_I);
3253 mono_mb_emit_ldarg (mb, argnum);
3256 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3257 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3260 case MONO_NATIVE_LPWSTR:
3261 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPWSTR);
3263 case MONO_NATIVE_LPSTR:
3264 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
3266 case MONO_NATIVE_LPTSTR:
3267 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPTSTR);
3270 char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding);
3271 MonoException *exc = mono_get_exception_not_implemented (msg);
3274 mono_raise_exception (exc);
3278 mono_mb_emit_stloc (mb, tmp_locals [i]);
3281 case MONO_TYPE_CLASS:
3282 case MONO_TYPE_OBJECT:
3283 klass = t->data.klass;
3285 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3286 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3288 if (klass->delegate) {
3289 g_assert (!t->byref);
3290 mono_mb_emit_ldarg (mb, argnum);
3291 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3292 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3293 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_DEL_FTN);
3294 mono_mb_emit_stloc (mb, tmp_locals [i]);
3295 } else if (klass == mono_defaults.stringbuilder_class) {
3296 MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, spec);
3298 g_assert (!t->byref);
3299 mono_mb_emit_ldarg (mb, argnum);
3300 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3301 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3304 case MONO_NATIVE_LPWSTR:
3305 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_SB_LPWSTR);
3307 case MONO_NATIVE_LPSTR:
3308 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_SB_LPSTR);
3310 case MONO_NATIVE_LPTSTR:
3311 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_SB_LPTSTR);
3314 char *msg = g_strdup_printf ("stringbuilder marshalling conversion %d not implemented", encoding);
3315 MonoException *exc = mono_get_exception_not_implemented (msg);
3318 mono_raise_exception (exc);
3322 mono_mb_emit_stloc (mb, tmp_locals [i]);
3324 mono_mb_emit_byte (mb, CEE_LDNULL);
3325 mono_mb_emit_stloc (mb, tmp_locals [i]);
3328 /* we dont need any conversions for out parameters */
3329 if (t->attrs & PARAM_ATTRIBUTE_OUT)
3332 mono_mb_emit_ldarg (mb, argnum);
3333 mono_mb_emit_byte (mb, CEE_LDIND_I);
3336 mono_mb_emit_ldarg (mb, argnum);
3337 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3338 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
3341 /* store the address of the source into local variable 0 */
3342 mono_mb_emit_byte (mb, CEE_STLOC_0);
3343 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3344 mono_mb_emit_byte (mb, CEE_BRFALSE);
3346 mono_mb_emit_i4 (mb, 0);
3348 /* allocate space for the native struct and store the address */
3349 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
3350 mono_mb_emit_byte (mb, CEE_PREFIX1);
3351 mono_mb_emit_byte (mb, CEE_LOCALLOC);
3352 mono_mb_emit_stloc (mb, tmp_locals [i]);
3354 /* set the src_ptr */
3355 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3356 mono_mb_emit_icon (mb, sizeof (MonoObject));
3357 mono_mb_emit_byte (mb, CEE_ADD);
3358 mono_mb_emit_byte (mb, CEE_STLOC_0);
3361 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3362 mono_mb_emit_byte (mb, CEE_STLOC_1);
3364 /* emit valuetype conversion code */
3365 emit_struct_conv (mb, klass, FALSE);
3367 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3371 case MONO_TYPE_ARRAY:
3372 case MONO_TYPE_SZARRAY:
3376 klass = mono_class_from_mono_type (t);
3378 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3379 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3381 if (klass->element_class == mono_defaults.string_class) {
3382 MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, spec);
3384 mono_mb_emit_ldarg (mb, argnum);
3385 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3386 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3389 case MONO_NATIVE_LPWSTR:
3390 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STRARRAY_STRWLPARRAY);
3392 case MONO_NATIVE_LPSTR:
3393 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STRARRAY_STRLPARRAY);
3396 char *msg = g_strdup_printf ("string array marshalling conversion %d not implemented", encoding);
3397 MonoException *exc = mono_get_exception_not_implemented (msg);
3400 mono_raise_exception (exc);
3403 mono_mb_emit_stloc (mb, tmp_locals [i]);
3405 else if (klass->element_class->blittable) {
3406 mono_mb_emit_ldarg (mb, argnum);
3407 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3408 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3410 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_ARRAY_LPARRAY);
3411 mono_mb_emit_stloc (mb, tmp_locals [i]);
3415 guint32 label1, label2, label3;
3416 int index_var, dest_ptr;
3418 dest_ptr = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3421 mono_mb_emit_ldarg (mb, argnum);
3422 mono_mb_emit_stloc (mb, tmp_locals [i]);
3423 mono_mb_emit_ldarg (mb, argnum);
3424 mono_mb_emit_byte (mb, CEE_BRFALSE);
3426 mono_mb_emit_i4 (mb, 0);
3428 /* allocate space for the native struct and store the address */
3429 eklass = klass->element_class;
3430 mono_mb_emit_icon (mb, mono_class_native_size (eklass, NULL));
3431 mono_mb_emit_ldarg (mb, argnum);
3432 mono_mb_emit_byte (mb, CEE_LDLEN);
3433 mono_mb_emit_byte (mb, CEE_MUL);
3434 mono_mb_emit_byte (mb, CEE_PREFIX1);
3435 mono_mb_emit_byte (mb, CEE_LOCALLOC);
3436 mono_mb_emit_stloc (mb, tmp_locals [i]);
3438 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3439 mono_mb_emit_stloc (mb, dest_ptr);
3441 /* Emit marshalling loop */
3442 index_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3443 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
3444 mono_mb_emit_stloc (mb, index_var);
3446 mono_mb_emit_ldloc (mb, index_var);
3447 mono_mb_emit_ldarg (mb, argnum);
3448 mono_mb_emit_byte (mb, CEE_LDLEN);
3449 mono_mb_emit_byte (mb, CEE_BGE);
3451 mono_mb_emit_i4 (mb, 0);
3453 /* Emit marshalling code */
3455 /* set the src_ptr */
3456 mono_mb_emit_ldarg (mb, argnum);
3457 mono_mb_emit_ldloc (mb, index_var);
3458 mono_mb_emit_byte (mb, CEE_LDELEMA);
3459 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eklass));
3460 mono_mb_emit_byte (mb, CEE_STLOC_0);
3463 mono_mb_emit_ldloc (mb, dest_ptr);
3464 mono_mb_emit_byte (mb, CEE_STLOC_1);
3466 /* emit valuetype conversion code */
3467 emit_struct_conv (mb, eklass, FALSE);
3469 mono_mb_emit_add_to_local (mb, index_var, 1);
3470 mono_mb_emit_add_to_local (mb, dest_ptr, mono_class_native_size (eklass, NULL));
3472 mono_mb_emit_byte (mb, CEE_BR);
3473 mono_mb_emit_i4 (mb, label2 - (mb->pos + 4));
3475 mono_mb_patch_addr (mb, label1, mb->pos - (label1 + 4));
3476 mono_mb_patch_addr (mb, label3, mb->pos - (label3 + 4));
3480 case MONO_TYPE_BOOLEAN: {
3481 MonoType *local_type;
3482 int variant_bool = 0;
3486 local_type = &mono_defaults.int32_class->byval_arg;
3488 switch (spec->native) {
3489 case MONO_NATIVE_I1:
3490 local_type = &mono_defaults.byte_class->byval_arg;
3492 case MONO_NATIVE_VARIANTBOOL:
3493 local_type = &mono_defaults.int16_class->byval_arg;
3497 g_warning ("marshalling bool as native type %x is currently not supported", spec->native);
3501 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3502 tmp_locals [i] = mono_mb_add_local (mb, local_type);
3503 mono_mb_emit_ldarg (mb, argnum);
3504 mono_mb_emit_byte (mb, CEE_LDIND_I1);
3506 mono_mb_emit_byte (mb, CEE_NEG);
3507 mono_mb_emit_stloc (mb, tmp_locals [i]);
3513 /* push all arguments */
3516 mono_mb_emit_byte (mb, CEE_LDARG_0);
3518 for (i = 0; i < sig->param_count; i++) {
3519 MonoType *t = sig->params [i];
3520 MonoMarshalSpec *spec = mspecs [i + 1];
3522 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
3523 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3526 if (spec && spec->native == MONO_NATIVE_ASANY) {
3527 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3530 argnum = i + sig->hasthis;
3533 case MONO_TYPE_BOOLEAN:
3535 g_assert (tmp_locals [i]);
3536 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
3538 mono_mb_emit_ldarg (mb, argnum);
3553 mono_mb_emit_ldarg (mb, argnum);
3555 case MONO_TYPE_VALUETYPE:
3556 klass = sig->params [i]->data.klass;
3557 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3558 klass->blittable || klass->enumtype) {
3559 mono_mb_emit_ldarg (mb, argnum);
3562 g_assert (tmp_locals [i]);
3563 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3565 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3566 mono_mb_emit_byte (mb, CEE_MONO_LDNATIVEOBJ);
3567 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3570 case MONO_TYPE_STRING:
3571 case MONO_TYPE_CLASS:
3572 case MONO_TYPE_OBJECT:
3573 g_assert (tmp_locals [i]);
3575 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
3577 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3579 case MONO_TYPE_CHAR:
3580 /* fixme: dont know how to marshal that. We cant simply
3581 * convert it to a one byte UTF8 character, because an
3582 * unicode character may need more that one byte in UTF8 */
3583 mono_mb_emit_ldarg (mb, argnum);
3585 case MONO_TYPE_ARRAY:
3586 case MONO_TYPE_SZARRAY:
3588 mono_mb_emit_ldarg (mb, argnum);
3590 g_assert (tmp_locals [i]);
3591 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3594 case MONO_TYPE_TYPEDBYREF:
3595 case MONO_TYPE_FNPTR:
3597 g_warning ("type 0x%02x unknown", t->type);
3598 g_assert_not_reached ();
3603 /* call the native method */
3604 mono_mb_emit_native_call (mb, csig, method->addr);
3606 /* Set LastError if needed */
3607 if (piinfo->piflags & PINVOKE_ATTRIBUTE_SUPPORTS_LAST_ERROR) {
3608 MonoMethodSignature *lasterr_sig;
3610 lasterr_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
3611 lasterr_sig->ret = &mono_defaults.void_class->byval_arg;
3612 lasterr_sig->pinvoke = 1;
3614 mono_mb_emit_native_call (mb, lasterr_sig, mono_marshal_set_last_error);
3617 /* convert the result */
3618 if (!sig->ret->byref) {
3619 MonoMarshalSpec *spec = mspecs [0];
3620 type = sig->ret->type;
3622 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
3625 MonoMethod *marshal_native_to_managed;
3626 MonoMethod *get_instance;
3628 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
3629 g_assert (mtype != NULL);
3630 mklass = mono_class_from_mono_type (mtype);
3631 g_assert (mklass != NULL);
3633 marshal_native_to_managed = mono_find_method_by_name (mklass, "MarshalNativeToManaged", 1);
3634 g_assert (marshal_native_to_managed);
3635 get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
3636 g_assert (get_instance);
3639 case MONO_TYPE_CLASS:
3640 case MONO_TYPE_OBJECT:
3641 case MONO_TYPE_STRING:
3642 case MONO_TYPE_ARRAY:
3643 case MONO_TYPE_SZARRAY:
3644 case MONO_TYPE_VALUETYPE:
3645 if (type == MONO_TYPE_VALUETYPE) {
3646 /* local 3 can't hold a pointer */
3647 mono_mb_emit_byte (mb, CEE_STLOC_0);
3650 mono_mb_emit_byte (mb, CEE_STLOC_3);
3652 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
3654 mono_mb_emit_byte (mb, CEE_CALL);
3655 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
3657 if (type == MONO_TYPE_VALUETYPE)
3658 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3660 mono_mb_emit_byte (mb, CEE_LDLOC_3);
3662 mono_mb_emit_byte (mb, CEE_CALLVIRT);
3663 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_native_to_managed));
3665 if (type == MONO_TYPE_VALUETYPE) {
3666 mono_mb_emit_byte (mb, CEE_UNBOX);
3667 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (sig->ret)));
3669 mono_mb_emit_byte (mb, CEE_STLOC_3);
3672 g_warning ("custom marshalling of type %x is currently not supported", type);
3673 g_assert_not_reached ();
3680 case MONO_TYPE_VOID:
3695 /* no conversions necessary */
3696 mono_mb_emit_byte (mb, CEE_STLOC_3);
3698 case MONO_TYPE_BOOLEAN:
3699 /* maybe we need to make sure that it fits within 8 bits */
3700 mono_mb_emit_byte (mb, CEE_STLOC_3);
3702 case MONO_TYPE_VALUETYPE:
3703 klass = sig->ret->data.klass;
3704 if (klass->enumtype) {
3705 type = sig->ret->data.klass->enum_basetype->type;
3709 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3711 mono_mb_emit_byte (mb, CEE_STLOC_3);
3714 /* load pointer to returned value type */
3715 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3716 mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
3717 /* store the address of the source into local variable 0 */
3718 mono_mb_emit_byte (mb, CEE_STLOC_0);
3720 mono_mb_emit_ldloc_addr (mb, 3);
3721 mono_mb_emit_byte (mb, CEE_STLOC_1);
3723 /* emit valuetype conversion code */
3724 emit_struct_conv (mb, sig->ret->data.klass, TRUE);
3726 case MONO_TYPE_STRING:
3727 #ifdef GTK_SHARP_FIXED
3728 mono_mb_emit_byte (mb, CEE_STLOC_0);
3729 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3732 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3733 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3735 switch (spec->native) {
3736 case MONO_NATIVE_LPWSTR:
3737 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPWSTR_STR);
3740 g_warning ("marshalling conversion not implemented");
3741 g_assert_not_reached ();
3744 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
3746 mono_mb_emit_byte (mb, CEE_STLOC_3);
3748 #ifdef GTK_SHARP_FIXED
3749 /* free the string */
3750 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3751 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3752 mono_mb_emit_byte (mb, CEE_MONO_FREE);
3755 case MONO_TYPE_CLASS:
3756 case MONO_TYPE_OBJECT:
3757 klass = sig->ret->data.klass;
3760 mono_mb_emit_byte (mb, CEE_STLOC_0);
3762 mono_mb_emit_byte (mb, CEE_LDNULL);
3763 mono_mb_emit_byte (mb, CEE_STLOC_3);
3766 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3767 mono_mb_emit_byte (mb, CEE_BRFALSE);
3769 mono_mb_emit_i4 (mb, 0);
3771 /* allocate result object */
3773 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3774 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
3775 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3776 mono_mb_emit_byte (mb, CEE_STLOC_3);
3780 mono_mb_emit_byte (mb, CEE_LDLOC_3);
3781 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3782 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
3783 mono_mb_emit_icon (mb, sizeof (MonoObject));
3784 mono_mb_emit_byte (mb, CEE_ADD);
3785 mono_mb_emit_byte (mb, CEE_STLOC_1);
3787 /* emit conversion code */
3788 emit_struct_conv (mb, klass, TRUE);
3790 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3792 case MONO_TYPE_ARRAY:
3793 case MONO_TYPE_SZARRAY:
3794 /* fixme: we need conversions here */
3795 mono_mb_emit_byte (mb, CEE_STLOC_3);
3797 case MONO_TYPE_CHAR:
3798 /* fixme: we need conversions here */
3799 mono_mb_emit_byte (mb, CEE_STLOC_3);
3801 case MONO_TYPE_TYPEDBYREF:
3802 case MONO_TYPE_FNPTR:
3804 g_warning ("return type 0x%02x unknown", sig->ret->type);
3805 g_assert_not_reached ();
3809 mono_mb_emit_byte (mb, CEE_STLOC_3);
3813 * Need to call this after converting the result since MONO_VTADDR needs
3814 * to be adjacent to the call instruction.
3816 emit_thread_interrupt_checkpoint (mb);
3818 /* we need to convert byref arguments back and free string arrays */
3819 for (i = 0; i < sig->param_count; i++) {
3820 MonoType *t = sig->params [i];
3821 MonoMarshalSpec *spec = mspecs [i + 1];
3823 argnum = i + sig->hasthis;
3825 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
3828 MonoMethod *get_instance;
3829 MonoMethod *cleanup_native;
3831 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
3832 g_assert (mtype != NULL);
3833 mklass = mono_class_from_mono_type (mtype);
3834 g_assert (mklass != NULL);
3836 get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
3837 g_assert (get_instance);
3838 cleanup_native = mono_find_method_by_name (mklass, "CleanUpNativeData", 1);
3839 g_assert (get_instance);
3842 case MONO_TYPE_CLASS:
3843 case MONO_TYPE_OBJECT:
3844 case MONO_TYPE_STRING:
3845 case MONO_TYPE_ARRAY:
3846 case MONO_TYPE_SZARRAY:
3847 case MONO_TYPE_VALUETYPE:
3848 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
3850 mono_mb_emit_byte (mb, CEE_CALL);
3851 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
3853 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3855 mono_mb_emit_byte (mb, CEE_CALLVIRT);
3856 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, cleanup_native));
3861 g_warning ("custom marshalling of type %x is currently not supported", t->type);
3862 g_assert_not_reached ();
3868 if (spec && spec->native == MONO_NATIVE_ASANY) {
3869 MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, NULL);
3871 mono_mb_emit_ldarg (mb, argnum);
3872 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3873 mono_mb_emit_icon (mb, encoding);
3874 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3875 mono_mb_emit_byte (mb, CEE_MONO_PROC3);
3876 mono_mb_emit_byte (mb, MONO_MARSHAL_FREE_ASANY);
3881 case MONO_TYPE_STRING:
3882 if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT)) {
3883 mono_mb_emit_ldarg (mb, argnum);
3884 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3885 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3886 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3887 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
3888 mono_mb_emit_byte (mb, CEE_STIND_I);
3890 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3891 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3892 mono_mb_emit_byte (mb, CEE_MONO_FREE);
3895 case MONO_TYPE_CLASS:
3896 case MONO_TYPE_OBJECT:
3897 if (t->data.klass == mono_defaults.stringbuilder_class) {
3898 MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, spec);
3899 gboolean need_free = TRUE;
3901 g_assert (!t->byref);
3902 mono_mb_emit_ldarg (mb, argnum);
3903 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3904 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3905 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
3908 case MONO_NATIVE_LPWSTR:
3909 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPWSTR_SB);
3911 * mono_string_builder_to_utf16 does not allocate a
3912 * new buffer, so no need to free it.
3916 case MONO_NATIVE_LPSTR:
3917 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_SB);
3919 case MONO_NATIVE_LPTSTR:
3920 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPTSTR_SB);
3923 g_assert_not_reached ();
3927 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3928 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3929 mono_mb_emit_byte (mb, CEE_MONO_FREE);
3934 if (!(t->byref || (t->attrs & PARAM_ATTRIBUTE_OUT)))
3937 if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT)) {
3938 /* allocate a new object new object */
3939 mono_mb_emit_ldarg (mb, argnum);
3940 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3941 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
3942 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3943 mono_mb_emit_byte (mb, CEE_STIND_I);
3946 /* dst = *argument */
3947 mono_mb_emit_ldarg (mb, argnum);
3950 mono_mb_emit_byte (mb, CEE_LDIND_I);
3952 mono_mb_emit_byte (mb, CEE_STLOC_1);
3954 mono_mb_emit_byte (mb, CEE_LDLOC_1);
3955 mono_mb_emit_byte (mb, CEE_BRFALSE);
3957 mono_mb_emit_i4 (mb, 0);
3959 mono_mb_emit_byte (mb, CEE_LDLOC_1);
3960 mono_mb_emit_icon (mb, sizeof (MonoObject));
3961 mono_mb_emit_byte (mb, CEE_ADD);
3962 mono_mb_emit_byte (mb, CEE_STLOC_1);
3964 /* src = tmp_locals [i] */
3965 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3966 mono_mb_emit_byte (mb, CEE_STLOC_0);
3968 /* emit valuetype conversion code */
3969 emit_struct_conv (mb, klass, TRUE);
3971 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3973 case MONO_TYPE_VALUETYPE:
3977 klass = t->data.klass;
3978 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3979 klass->blittable || klass->enumtype)
3982 /* dst = argument */
3983 mono_mb_emit_ldarg (mb, argnum);
3984 mono_mb_emit_byte (mb, CEE_STLOC_1);
3986 mono_mb_emit_byte (mb, CEE_LDLOC_1);
3987 mono_mb_emit_byte (mb, CEE_BRFALSE);
3989 mono_mb_emit_i4 (mb, 0);
3991 /* src = tmp_locals [i] */
3992 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3993 mono_mb_emit_byte (mb, CEE_STLOC_0);
3995 /* emit valuetype conversion code */
3996 emit_struct_conv (mb, klass, TRUE);
3998 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
4000 case MONO_TYPE_SZARRAY:
4004 klass = mono_class_from_mono_type (t);
4006 if (klass->element_class == mono_defaults.string_class) {
4007 MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, spec);
4008 g_assert (tmp_locals [i]);
4010 mono_mb_emit_ldarg (mb, argnum);
4011 mono_mb_emit_byte (mb, CEE_BRFALSE);
4013 mono_mb_emit_i4 (mb, 0);
4015 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4018 case MONO_NATIVE_LPWSTR:
4020 * The array elements point to the managed string data so
4021 * they don't need to be freed.
4023 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4024 mono_mb_emit_byte (mb, CEE_MONO_FREE);
4027 mono_mb_emit_ldarg (mb, argnum);
4028 mono_mb_emit_byte (mb, CEE_LDLEN);
4029 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4030 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
4031 mono_mb_emit_byte (mb, MONO_MARSHAL_FREE_ARRAY);
4035 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
4038 /* Character arrays are implicitly marshalled as [Out] */
4039 if ((klass->element_class == mono_defaults.char_class) || (t->attrs & PARAM_ATTRIBUTE_OUT)) {
4040 /* FIXME: Optimize blittable case */
4042 guint32 label1, label2, label3;
4043 int index_var, src_ptr;
4045 eklass = klass->element_class;
4046 src_ptr = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
4049 mono_mb_emit_ldarg (mb, argnum);
4050 mono_mb_emit_byte (mb, CEE_BRFALSE);
4052 mono_mb_emit_i4 (mb, 0);
4054 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4055 mono_mb_emit_stloc (mb, src_ptr);
4057 /* Emit marshalling loop */
4058 index_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
4059 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
4060 mono_mb_emit_stloc (mb, index_var);
4062 mono_mb_emit_ldloc (mb, index_var);
4063 mono_mb_emit_ldarg (mb, argnum);
4064 mono_mb_emit_byte (mb, CEE_LDLEN);
4065 mono_mb_emit_byte (mb, CEE_BGE);
4067 mono_mb_emit_i4 (mb, 0);
4069 /* Emit marshalling code */
4071 /* set the src_ptr */
4072 mono_mb_emit_ldloc (mb, src_ptr);
4073 mono_mb_emit_byte (mb, CEE_STLOC_0);
4076 mono_mb_emit_ldarg (mb, argnum);
4077 mono_mb_emit_ldloc (mb, index_var);
4078 mono_mb_emit_byte (mb, CEE_LDELEMA);
4079 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eklass));
4080 mono_mb_emit_byte (mb, CEE_STLOC_1);
4082 /* emit valuetype conversion code */
4083 emit_struct_conv (mb, eklass, TRUE);
4085 mono_mb_emit_add_to_local (mb, index_var, 1);
4086 mono_mb_emit_add_to_local (mb, src_ptr, mono_class_native_size (eklass, NULL));
4088 mono_mb_emit_byte (mb, CEE_BR);
4089 mono_mb_emit_i4 (mb, label2 - (mb->pos + 4));
4091 mono_mb_patch_addr (mb, label1, mb->pos - (label1 + 4));
4092 mono_mb_patch_addr (mb, label3, mb->pos - (label3 + 4));
4095 case MONO_TYPE_BOOLEAN:
4098 mono_mb_emit_ldarg (mb, argnum);
4099 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4100 if (mspecs [i + 1] != NULL && mspecs [i + 1]->native == MONO_NATIVE_VARIANTBOOL)
4101 mono_mb_emit_byte (mb, CEE_NEG);
4102 mono_mb_emit_byte (mb, CEE_STIND_I1);
4106 if (!MONO_TYPE_IS_VOID(sig->ret))
4107 mono_mb_emit_byte (mb, CEE_LDLOC_3);
4109 mono_mb_emit_byte (mb, CEE_RET);
4111 csig = mono_metadata_signature_dup (sig);
4113 res = mono_mb_create_and_cache (cache, method,
4114 mb, csig, csig->param_count + 16);
4117 for (i = sig->param_count; i >= 0; i--)
4118 g_free (mspecs [i]);
4121 //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));
4127 mono_upgrade_remote_class_wrapper (MonoReflectionType *rtype, MonoTransparentProxy *tproxy);
4129 static MonoReflectionType *
4130 type_from_handle (MonoType *handle)
4132 MonoDomain *domain = mono_domain_get ();
4133 MonoClass *klass = mono_class_from_mono_type (handle);
4135 MONO_ARCH_SAVE_REGS;
4137 mono_class_init (klass);
4138 return mono_type_get_object (domain, handle);
4142 * mono_marshal_get_isinst:
4143 * @klass: the type of the field
4145 * This method generates a function which can be used to check if an object is
4146 * an instance of the given type, icluding the case where the object is a proxy.
4147 * The generated function has the following signature:
4148 * MonoObject* __isinst_wrapper_ (MonoObject *obj)
4151 mono_marshal_get_isinst (MonoClass *klass)
4153 static MonoMethodSignature *isint_sig = NULL;
4154 static GHashTable *isinst_hash = NULL;
4156 int pos_was_ok, pos_failed, pos_end, pos_end2;
4158 MonoMethodBuilder *mb;
4160 EnterCriticalSection (&marshal_mutex);
4162 isinst_hash = g_hash_table_new (NULL, NULL);
4164 res = g_hash_table_lookup (isinst_hash, klass);
4165 LeaveCriticalSection (&marshal_mutex);
4170 isint_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
4171 isint_sig->params [0] = &mono_defaults.object_class->byval_arg;
4172 isint_sig->ret = &mono_defaults.object_class->byval_arg;
4173 isint_sig->pinvoke = 0;
4176 name = g_strdup_printf ("__isinst_wrapper_%s", klass->name);
4177 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_UNKNOWN);
4180 mb->method->save_lmf = 1;
4182 /* check if the object is a proxy that needs special cast */
4183 mono_mb_emit_ldarg (mb, 0);
4184 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4185 mono_mb_emit_byte (mb, CEE_MONO_CISINST);
4186 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
4188 /* The result of MONO_ISINST can be:
4189 0) the type check succeeded
4190 1) the type check did not succeed
4191 2) a CanCastTo call is needed */
4193 mono_mb_emit_byte (mb, CEE_DUP);
4194 pos_was_ok = mono_mb_emit_branch (mb, CEE_BRFALSE);
4196 mono_mb_emit_byte (mb, CEE_LDC_I4_2);
4197 pos_failed = mono_mb_emit_branch (mb, CEE_BNE_UN);
4199 /* get the real proxy from the transparent proxy*/
4201 mono_mb_emit_ldarg (mb, 0);
4202 mono_mb_emit_managed_call (mb, mono_marshal_get_proxy_cancast (klass), NULL);
4203 pos_end = mono_mb_emit_branch (mb, CEE_BR);
4207 mono_mb_patch_addr (mb, pos_failed, mb->pos - (pos_failed + 4));
4208 mono_mb_emit_byte (mb, CEE_LDNULL);
4209 pos_end2 = mono_mb_emit_branch (mb, CEE_BR);
4213 mono_mb_patch_addr (mb, pos_was_ok, mb->pos - (pos_was_ok + 4));
4214 mono_mb_emit_byte (mb, CEE_POP);
4215 mono_mb_emit_ldarg (mb, 0);
4219 mono_mb_patch_addr (mb, pos_end, mb->pos - (pos_end + 4));
4220 mono_mb_patch_addr (mb, pos_end2, mb->pos - (pos_end2 + 4));
4221 mono_mb_emit_byte (mb, CEE_RET);
4223 res = mono_mb_create_and_cache (isinst_hash, klass, mb, isint_sig, isint_sig->param_count + 16);
4230 * mono_marshal_get_castclass:
4231 * @klass: the type of the field
4233 * This method generates a function which can be used to cast an object to
4234 * an instance of the given type, icluding the case where the object is a proxy.
4235 * The generated function has the following signature:
4236 * MonoObject* __castclass_wrapper_ (MonoObject *obj)
4239 mono_marshal_get_castclass (MonoClass *klass)
4241 static MonoMethodSignature *castclass_sig = NULL;
4242 static GHashTable *castclass_hash = NULL;
4244 int pos_was_ok, pos_was_ok2;
4246 MonoMethodBuilder *mb;
4248 EnterCriticalSection (&marshal_mutex);
4249 if (!castclass_hash)
4250 castclass_hash = g_hash_table_new (NULL, NULL);
4252 res = g_hash_table_lookup (castclass_hash, klass);
4253 LeaveCriticalSection (&marshal_mutex);
4257 if (!castclass_sig) {
4258 castclass_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
4259 castclass_sig->params [0] = &mono_defaults.object_class->byval_arg;
4260 castclass_sig->ret = &mono_defaults.object_class->byval_arg;
4261 castclass_sig->pinvoke = 0;
4264 name = g_strdup_printf ("__castclass_wrapper_%s", klass->name);
4265 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_UNKNOWN);
4268 mb->method->save_lmf = 1;
4270 /* check if the object is a proxy that needs special cast */
4271 mono_mb_emit_ldarg (mb, 0);
4272 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4273 mono_mb_emit_byte (mb, CEE_MONO_CCASTCLASS);
4274 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
4276 /* The result of MONO_ISINST can be:
4277 0) the cast is valid
4278 1) cast of unknown proxy type
4279 or an exception if the cast is is invalid
4282 pos_was_ok = mono_mb_emit_branch (mb, CEE_BRFALSE);
4284 /* get the real proxy from the transparent proxy*/
4286 mono_mb_emit_ldarg (mb, 0);
4287 mono_mb_emit_managed_call (mb, mono_marshal_get_proxy_cancast (klass), NULL);
4288 pos_was_ok2 = mono_mb_emit_branch (mb, CEE_BRTRUE);
4291 mono_mb_emit_exception (mb, "InvalidCastException", NULL);
4294 mono_mb_patch_addr (mb, pos_was_ok, mb->pos - (pos_was_ok + 4));
4295 mono_mb_patch_addr (mb, pos_was_ok2, mb->pos - (pos_was_ok2 + 4));
4296 mono_mb_emit_ldarg (mb, 0);
4299 mono_mb_emit_byte (mb, CEE_RET);
4301 res = mono_mb_create_and_cache (castclass_hash, klass, mb, castclass_sig, castclass_sig->param_count + 16);
4308 mono_marshal_get_proxy_cancast (MonoClass *klass)
4310 static MonoMethodSignature *from_handle_sig = NULL;
4311 static MonoMethodSignature *upgrade_proxy_sig = NULL;
4312 static MonoMethodSignature *isint_sig = NULL;
4313 static GHashTable *proxy_isinst_hash = NULL;
4315 int pos_failed, pos_end;
4317 MonoMethod *can_cast_to;
4318 MonoMethodDesc *desc;
4319 MonoMethodBuilder *mb;
4321 EnterCriticalSection (&marshal_mutex);
4322 if (!proxy_isinst_hash)
4323 proxy_isinst_hash = g_hash_table_new (NULL, NULL);
4325 res = g_hash_table_lookup (proxy_isinst_hash, klass);
4326 LeaveCriticalSection (&marshal_mutex);
4331 upgrade_proxy_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
4332 upgrade_proxy_sig->params [0] = &mono_defaults.object_class->byval_arg;
4333 upgrade_proxy_sig->params [1] = &mono_defaults.object_class->byval_arg;
4334 upgrade_proxy_sig->ret = &mono_defaults.void_class->byval_arg;
4335 upgrade_proxy_sig->pinvoke = 1;
4337 from_handle_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
4338 from_handle_sig->params [0] = &mono_defaults.object_class->byval_arg;
4339 from_handle_sig->ret = &mono_defaults.object_class->byval_arg;
4341 isint_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
4342 isint_sig->params [0] = &mono_defaults.object_class->byval_arg;
4343 isint_sig->ret = &mono_defaults.object_class->byval_arg;
4344 isint_sig->pinvoke = 0;
4347 name = g_strdup_printf ("__proxy_isinst_wrapper_%s", klass->name);
4348 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_UNKNOWN);
4351 mb->method->save_lmf = 1;
4353 /* get the real proxy from the transparent proxy*/
4354 mono_mb_emit_ldarg (mb, 0);
4355 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoTransparentProxy, rp));
4356 mono_mb_emit_byte (mb, CEE_LDIND_I);
4358 /* get the refletion type from the type handle */
4359 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4360 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
4361 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, &klass->byval_arg));
4362 mono_mb_emit_native_call (mb, from_handle_sig, type_from_handle);
4364 mono_mb_emit_ldarg (mb, 0);
4366 /* make the call to CanCastTo (type, ob) */
4367 desc = mono_method_desc_new ("IRemotingTypeInfo:CanCastTo", FALSE);
4368 can_cast_to = mono_method_desc_search_in_class (desc, mono_defaults.iremotingtypeinfo_class);
4369 g_assert (can_cast_to);
4370 mono_method_desc_free (desc);
4371 mono_mb_emit_byte (mb, CEE_CALLVIRT);
4372 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, can_cast_to));
4375 pos_failed = mono_mb_emit_branch (mb, CEE_BRFALSE);
4377 /* Upgrade the proxy vtable by calling: mono_upgrade_remote_class_wrapper (type, ob)*/
4378 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4379 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
4380 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, &klass->byval_arg));
4381 mono_mb_emit_native_call (mb, from_handle_sig, type_from_handle);
4382 mono_mb_emit_ldarg (mb, 0);
4384 mono_mb_emit_native_call (mb, upgrade_proxy_sig, mono_upgrade_remote_class_wrapper);
4385 emit_thread_interrupt_checkpoint (mb);
4387 mono_mb_emit_ldarg (mb, 0);
4388 pos_end = mono_mb_emit_branch (mb, CEE_BR);
4392 mono_mb_patch_addr (mb, pos_failed, mb->pos - (pos_failed + 4));
4393 mono_mb_emit_byte (mb, CEE_LDNULL);
4397 mono_mb_patch_addr (mb, pos_end, mb->pos - (pos_end + 4));
4398 mono_mb_emit_byte (mb, CEE_RET);
4400 res = mono_mb_create_and_cache (proxy_isinst_hash, klass, mb, isint_sig, isint_sig->param_count + 16);
4407 mono_upgrade_remote_class_wrapper (MonoReflectionType *rtype, MonoTransparentProxy *tproxy)
4410 klass = mono_class_from_mono_type (rtype->type);
4411 mono_upgrade_remote_class (((MonoObject*)tproxy)->vtable->domain, tproxy->remote_class, klass);
4412 ((MonoObject*)tproxy)->vtable = tproxy->remote_class->vtable;
4416 * mono_marshal_get_struct_to_ptr:
4419 * generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld)
4422 mono_marshal_get_struct_to_ptr (MonoClass *klass)
4424 MonoMethodBuilder *mb;
4425 static MonoMethod *stoptr = NULL;
4428 g_assert (klass != NULL);
4430 if (klass->str_to_ptr)
4431 return klass->str_to_ptr;
4434 stoptr = mono_find_method_by_name (mono_defaults.marshal_class, "StructureToPtr", 3);
4437 mb = mono_mb_new (klass, stoptr->name, MONO_WRAPPER_UNKNOWN);
4439 if (klass->blittable) {
4440 mono_mb_emit_byte (mb, CEE_LDARG_1);
4441 mono_mb_emit_byte (mb, CEE_LDARG_0);
4442 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
4443 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
4444 mono_mb_emit_byte (mb, CEE_PREFIX1);
4445 mono_mb_emit_byte (mb, CEE_CPBLK);
4448 /* allocate local 0 (pointer) src_ptr */
4449 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
4450 /* allocate local 1 (pointer) dst_ptr */
4451 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
4452 /* allocate local 2 (boolean) delete_old */
4453 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
4454 mono_mb_emit_byte (mb, CEE_LDARG_2);
4455 mono_mb_emit_byte (mb, CEE_STLOC_2);
4457 /* initialize src_ptr to point to the start of object data */
4458 mono_mb_emit_byte (mb, CEE_LDARG_0);
4459 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
4460 mono_mb_emit_byte (mb, CEE_STLOC_0);
4462 /* initialize dst_ptr */
4463 mono_mb_emit_byte (mb, CEE_LDARG_1);
4464 mono_mb_emit_byte (mb, CEE_STLOC_1);
4466 emit_struct_conv (mb, klass, FALSE);
4469 mono_mb_emit_byte (mb, CEE_RET);
4471 res = mono_mb_create_method (mb, stoptr->signature, 0);
4474 klass->str_to_ptr = res;
4479 * mono_marshal_get_ptr_to_struct:
4482 * generates IL code for PtrToStructure (IntPtr src, object structure)
4485 mono_marshal_get_ptr_to_struct (MonoClass *klass)
4487 MonoMethodBuilder *mb;
4488 static MonoMethod *ptostr = NULL;
4491 g_assert (klass != NULL);
4493 if (klass->ptr_to_str)
4494 return klass->ptr_to_str;
4497 ptostr = mono_find_method_by_name (mono_defaults.marshal_class, "PtrToStructure", 2);
4500 mb = mono_mb_new (klass, ptostr->name, MONO_WRAPPER_UNKNOWN);
4502 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable) {
4503 mono_mb_emit_byte (mb, CEE_LDARG_1);
4504 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
4505 mono_mb_emit_byte (mb, CEE_LDARG_0);
4506 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
4507 mono_mb_emit_byte (mb, CEE_PREFIX1);
4508 mono_mb_emit_byte (mb, CEE_CPBLK);
4511 /* allocate local 0 (pointer) src_ptr */
4512 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
4513 /* allocate local 1 (pointer) dst_ptr */
4514 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
4516 /* initialize src_ptr to point to the start of object data */
4517 mono_mb_emit_byte (mb, CEE_LDARG_0);
4518 mono_mb_emit_byte (mb, CEE_STLOC_0);
4520 /* initialize dst_ptr */
4521 mono_mb_emit_byte (mb, CEE_LDARG_1);
4522 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
4523 mono_mb_emit_byte (mb, CEE_STLOC_1);
4525 emit_struct_conv (mb, klass, TRUE);
4528 mono_mb_emit_byte (mb, CEE_RET);
4530 res = mono_mb_create_method (mb, ptostr->signature, 0);
4533 klass->ptr_to_str = res;
4538 * generates IL code for the synchronized wrapper: the generated method
4539 * calls METHOD while locking 'this' or the parent type.
4542 mono_marshal_get_synchronized_wrapper (MonoMethod *method)
4544 static MonoMethodSignature *from_handle_sig = NULL;
4545 static MonoMethod *enter_method, *exit_method;
4546 MonoMethodSignature *sig;
4547 MonoExceptionClause *clause;
4548 MonoMethodHeader *header;
4549 MonoMethodBuilder *mb;
4552 int i, pos, this_local, ret_local;
4556 if (method->wrapper_type == MONO_WRAPPER_SYNCHRONIZED)
4559 cache = method->klass->image->synchronized_cache;
4560 if ((res = mono_marshal_find_in_cache (cache, method)))
4563 sig = method->signature;
4565 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_SYNCHRONIZED);
4568 if (!MONO_TYPE_IS_VOID (sig->ret))
4569 ret_local = mono_mb_add_local (mb, sig->ret);
4572 this_local = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
4574 clause = g_new0 (MonoExceptionClause, 1);
4575 clause->flags = MONO_EXCEPTION_CLAUSE_FINALLY;
4577 if (!enter_method) {
4578 MonoMethodDesc *desc;
4580 desc = mono_method_desc_new ("Monitor:Enter", FALSE);
4581 enter_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
4582 g_assert (enter_method);
4583 mono_method_desc_free (desc);
4584 desc = mono_method_desc_new ("Monitor:Exit", FALSE);
4585 exit_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
4586 g_assert (exit_method);
4587 mono_method_desc_free (desc);
4590 * GetTypeFromHandle isn't called as a managed method because it has
4591 * a funky calling sequence, e.g. ldtoken+GetTypeFromHandle gets
4592 * transformed into something else by the JIT.
4594 from_handle_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
4595 from_handle_sig->params [0] = &mono_defaults.object_class->byval_arg;
4596 from_handle_sig->ret = &mono_defaults.object_class->byval_arg;
4599 /* Push this or the type object */
4600 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4601 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4602 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
4603 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, &method->klass->byval_arg));
4604 mono_mb_emit_native_call (mb, from_handle_sig, type_from_handle);
4607 mono_mb_emit_ldarg (mb, 0);
4608 mono_mb_emit_stloc (mb, this_local);
4610 /* Call Monitor::Enter() */
4611 mono_mb_emit_ldloc (mb, this_local);
4612 mono_mb_emit_managed_call (mb, enter_method, NULL);
4614 clause->try_offset = mb->pos;
4616 /* Call the method */
4618 mono_mb_emit_ldarg (mb, 0);
4619 for (i = 0; i < sig->param_count; i++)
4620 mono_mb_emit_ldarg (mb, i + (sig->hasthis == TRUE));
4621 mono_mb_emit_managed_call (mb, method, method->signature);
4622 if (!MONO_TYPE_IS_VOID (sig->ret))
4623 mono_mb_emit_stloc (mb, ret_local);
4625 mono_mb_emit_byte (mb, CEE_LEAVE);
4627 mono_mb_emit_i4 (mb, 0);
4629 clause->try_len = mb->pos - clause->try_offset;
4630 clause->handler_offset = mb->pos;
4632 /* Call Monitor::Exit() */
4633 mono_mb_emit_ldloc (mb, this_local);
4634 // mono_mb_emit_native_call (mb, exit_sig, mono_monitor_exit);
4635 mono_mb_emit_managed_call (mb, exit_method, NULL);
4636 mono_mb_emit_byte (mb, CEE_ENDFINALLY);
4638 clause->handler_len = mb->pos - clause->handler_offset;
4640 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
4641 if (!MONO_TYPE_IS_VOID (sig->ret))
4642 mono_mb_emit_ldloc (mb, ret_local);
4643 mono_mb_emit_byte (mb, CEE_RET);
4645 res = mono_mb_create_and_cache (cache, method,
4646 mb, sig, sig->param_count + 16);
4649 header = ((MonoMethodNormal *)res)->header;
4650 header->num_clauses = 1;
4651 header->clauses = clause;
4656 /* FIXME: on win32 we should probably use GlobalAlloc(). */
4658 mono_marshal_alloc (gpointer size)
4660 MONO_ARCH_SAVE_REGS;
4662 return g_try_malloc ((gulong)size);
4666 mono_marshal_free (gpointer ptr)
4668 MONO_ARCH_SAVE_REGS;
4674 mono_marshal_free_array (gpointer *ptr, int size)
4681 for (i = 0; i < size; i++)
4687 mono_marshal_realloc (gpointer ptr, gpointer size)
4689 MONO_ARCH_SAVE_REGS;
4691 return g_try_realloc (ptr, (gulong)size);
4695 mono_marshal_string_array (MonoArray *array)
4703 len = mono_array_length (array);
4705 result = g_malloc (sizeof (char *) * (len + 1));
4706 for (i = 0; i < len; ++i) {
4707 MonoString *s = (MonoString *)mono_array_get (array, gpointer, i);
4708 result [i] = s ? mono_string_to_utf8 (s): NULL;
4710 /* null terminate the array */
4717 mono_marshal_string_array_to_unicode (MonoArray *array)
4725 len = mono_array_length (array);
4727 result = g_malloc (sizeof (gunichar2 *) * (len + 1));
4728 for (i = 0; i < len; ++i) {
4729 MonoString *s = (MonoString *)mono_array_get (array, gpointer, i);
4730 result [i] = s ? mono_string_chars (s) : NULL;
4732 /* null terminate the array */
4739 * mono_marshal_set_last_error:
4741 * This function is invoked to set the last error value from a P/Invoke call
4742 * which has SetLastError set.
4745 mono_marshal_set_last_error (void)
4748 TlsSetValue (last_error_tls_id, (gpointer)GetLastError ());
4750 TlsSetValue (last_error_tls_id, (gpointer)errno);
4755 ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArray *src, gint32 start_index,
4756 gpointer dest, gint32 length)
4761 MONO_ARCH_SAVE_REGS;
4763 MONO_CHECK_ARG_NULL (src);
4764 MONO_CHECK_ARG_NULL (dest);
4766 g_assert (src->obj.vtable->klass->rank == 1);
4767 g_assert (start_index >= 0);
4768 g_assert (length >= 0);
4769 g_assert (start_index + length <= mono_array_length (src));
4771 element_size = mono_array_element_size (src->obj.vtable->klass);
4773 source_addr = mono_array_addr_with_size (src, element_size, start_index);
4775 memcpy (dest, source_addr, length * element_size);
4779 ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer src, gint32 start_index,
4780 MonoArray *dest, gint32 length)
4785 MONO_ARCH_SAVE_REGS;
4787 MONO_CHECK_ARG_NULL (src);
4788 MONO_CHECK_ARG_NULL (dest);
4790 g_assert (dest->obj.vtable->klass->rank == 1);
4791 g_assert (start_index >= 0);
4792 g_assert (length >= 0);
4793 g_assert (start_index + length <= mono_array_length (dest));
4795 element_size = mono_array_element_size (dest->obj.vtable->klass);
4797 dest_addr = mono_array_addr_with_size (dest, element_size, start_index);
4799 memcpy (dest_addr, src, length * element_size);
4802 #if NO_UNALIGNED_ACCESS
4803 #define RETURN_UNALIGNED(type, addr) \
4806 memcpy(&val, p + offset, sizeof(val)); \
4809 #define WRITE_UNALIGNED(type, addr, val) \
4810 memcpy(addr, &val, sizeof(type))
4812 #define RETURN_UNALIGNED(type, addr) \
4813 return *(type*)(p + offset);
4814 #define WRITE_UNALIGNED(type, addr, val) \
4815 (*(type *)(addr) = (val))
4819 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr, gint32 offset)
4823 MONO_ARCH_SAVE_REGS;
4825 RETURN_UNALIGNED(gpointer, p + offset);
4829 ves_icall_System_Runtime_InteropServices_Marshal_ReadByte (gpointer ptr, gint32 offset)
4833 MONO_ARCH_SAVE_REGS;
4835 return *(unsigned char*)(p + offset);
4839 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt16 (gpointer ptr, gint32 offset)
4843 MONO_ARCH_SAVE_REGS;
4845 RETURN_UNALIGNED(gint16, p + offset);
4849 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt32 (gpointer ptr, gint32 offset)
4853 MONO_ARCH_SAVE_REGS;
4855 RETURN_UNALIGNED(gint32, p + offset);
4859 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt64 (gpointer ptr, gint32 offset)
4863 MONO_ARCH_SAVE_REGS;
4865 RETURN_UNALIGNED(gint64, p + offset);
4869 ves_icall_System_Runtime_InteropServices_Marshal_WriteByte (gpointer ptr, gint32 offset, unsigned char val)
4873 MONO_ARCH_SAVE_REGS;
4875 *(unsigned char*)(p + offset) = val;
4879 ves_icall_System_Runtime_InteropServices_Marshal_WriteIntPtr (gpointer ptr, gint32 offset, gpointer val)
4883 MONO_ARCH_SAVE_REGS;
4885 WRITE_UNALIGNED(gpointer, p + offset, val);
4889 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt16 (gpointer ptr, gint32 offset, gint16 val)
4893 MONO_ARCH_SAVE_REGS;
4895 WRITE_UNALIGNED(gint16, p + offset, val);
4899 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt32 (gpointer ptr, gint32 offset, gint32 val)
4903 MONO_ARCH_SAVE_REGS;
4905 WRITE_UNALIGNED(gint32, p + offset, val);
4909 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt64 (gpointer ptr, gint32 offset, gint64 val)
4913 MONO_ARCH_SAVE_REGS;
4915 WRITE_UNALIGNED(gint64, p + offset, val);
4919 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (char *ptr)
4921 MONO_ARCH_SAVE_REGS;
4924 return mono_string_new (mono_domain_get (), "");
4926 return mono_string_new (mono_domain_get (), ptr);
4930 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len (char *ptr, gint32 len)
4932 MONO_ARCH_SAVE_REGS;
4935 return mono_string_new (mono_domain_get (), "");
4937 return mono_string_new_len (mono_domain_get (), ptr, len);
4941 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni (guint16 *ptr)
4943 MonoDomain *domain = mono_domain_get ();
4947 MONO_ARCH_SAVE_REGS;
4950 return mono_string_new (mono_domain_get (), "");
4955 return mono_string_new_utf16 (domain, ptr, len);
4959 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len (guint16 *ptr, gint32 len)
4961 MonoDomain *domain = mono_domain_get ();
4963 MONO_ARCH_SAVE_REGS;
4966 return mono_string_new (mono_domain_get (), "");
4968 return mono_string_new_utf16 (domain, ptr, len);
4972 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR (gpointer ptr)
4974 MONO_ARCH_SAVE_REGS;
4976 g_warning ("PtrToStringBSTR not implemented");
4977 g_assert_not_reached ();
4983 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
4985 MONO_ARCH_SAVE_REGS;
4987 return ((guint32)TlsGetValue (last_error_tls_id));
4991 ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype)
4997 MONO_ARCH_SAVE_REGS;
4999 MONO_CHECK_ARG_NULL (rtype);
5002 klass = mono_class_from_mono_type (type);
5003 layout = (klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK);
5005 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
5009 msg = g_strdup_printf ("Type %s cannot be marshaled as an unmanaged structure.", klass->name);
5010 exc = mono_get_exception_argument ("t", msg);
5012 mono_raise_exception (exc);
5016 return mono_class_native_size (klass, NULL);
5020 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old)
5025 MONO_ARCH_SAVE_REGS;
5027 MONO_CHECK_ARG_NULL (obj);
5028 MONO_CHECK_ARG_NULL (dst);
5030 method = mono_marshal_get_struct_to_ptr (obj->vtable->klass);
5034 pa [2] = &delete_old;
5036 mono_runtime_invoke (method, NULL, pa, NULL);
5040 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, MonoObject *dst)
5045 MONO_ARCH_SAVE_REGS;
5047 MONO_CHECK_ARG_NULL (src);
5048 MONO_CHECK_ARG_NULL (dst);
5050 method = mono_marshal_get_ptr_to_struct (dst->vtable->klass);
5055 mono_runtime_invoke (method, NULL, pa, NULL);
5059 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer src, MonoReflectionType *type)
5061 MonoDomain *domain = mono_domain_get ();
5064 MONO_ARCH_SAVE_REGS;
5066 MONO_CHECK_ARG_NULL (src);
5067 MONO_CHECK_ARG_NULL (type);
5069 res = mono_object_new (domain, mono_class_from_mono_type (type->type));
5071 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (src, res);
5077 ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *type, MonoString *field_name)
5079 MonoMarshalType *info;
5082 int i, match_index = -1;
5084 MONO_ARCH_SAVE_REGS;
5086 MONO_CHECK_ARG_NULL (type);
5087 MONO_CHECK_ARG_NULL (field_name);
5089 fname = mono_string_to_utf8 (field_name);
5090 klass = mono_class_from_mono_type (type->type);
5092 while(klass && match_index == -1) {
5093 for (i = 0; i < klass->field.count; ++i) {
5094 if (*fname == *klass->fields [i].name && strcmp (fname, klass->fields [i].name) == 0) {
5100 if(match_index == -1)
5101 klass = klass->parent;
5106 if(match_index == -1) {
5110 /* Get back original class instance */
5111 klass = mono_class_from_mono_type (type->type);
5113 tmp = g_strdup_printf ("Field passed in is not a marshaled member of the type %s", klass->name);
5114 exc = mono_get_exception_argument ("fieldName", tmp);
5117 mono_raise_exception ((MonoException*)exc);
5120 info = mono_marshal_load_type_info (klass);
5121 return info->fields [match_index].offset;
5125 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString *string)
5127 MONO_ARCH_SAVE_REGS;
5129 return mono_string_to_utf8 (string);
5133 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni (MonoString *string)
5135 MONO_ARCH_SAVE_REGS;
5140 return g_memdup (mono_string_chars (string), mono_string_length (string)*2);
5144 mono_struct_delete_old (MonoClass *klass, char *ptr)
5146 MonoMarshalType *info;
5149 info = mono_marshal_load_type_info (klass);
5151 for (i = 0; i < info->num_fields; i++) {
5152 MonoMarshalNative ntype;
5153 MonoMarshalConv conv;
5154 MonoType *ftype = info->fields [i].field->type;
5157 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
5160 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE,
5161 klass->unicode, &conv);
5163 cpos = ptr + info->fields [i].offset;
5166 case MONO_MARSHAL_CONV_NONE:
5167 if (MONO_TYPE_ISSTRUCT (ftype)) {
5168 mono_struct_delete_old (ftype->data.klass, cpos);
5172 case MONO_MARSHAL_CONV_STR_LPWSTR:
5173 case MONO_MARSHAL_CONV_STR_LPSTR:
5174 case MONO_MARSHAL_CONV_STR_LPTSTR:
5175 case MONO_MARSHAL_CONV_STR_BSTR:
5176 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
5177 case MONO_MARSHAL_CONV_STR_TBSTR:
5178 g_free (*(gpointer *)cpos);
5187 ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure (gpointer src, MonoReflectionType *type)
5191 MONO_ARCH_SAVE_REGS;
5193 MONO_CHECK_ARG_NULL (src);
5194 MONO_CHECK_ARG_NULL (type);
5196 klass = mono_class_from_mono_type (type->type);
5198 mono_struct_delete_old (klass, (char *)src);
5202 ves_icall_System_Runtime_InteropServices_Marshal_AllocCoTaskMem (int size)
5204 /* FIXME: Call AllocCoTaskMem under windows */
5205 MONO_ARCH_SAVE_REGS;
5207 return g_try_malloc ((gulong)size);
5211 ves_icall_System_Runtime_InteropServices_Marshal_FreeCoTaskMem (void *ptr)
5213 /* FIXME: Call FreeCoTaskMem under windows */
5214 MONO_ARCH_SAVE_REGS;
5220 ves_icall_System_Runtime_InteropServices_Marshal_UnsafeAddrOfPinnedArrayElement (MonoArray *arrayobj, int index)
5222 return mono_array_addr_with_size (arrayobj, mono_array_element_size (arrayobj->obj.vtable->klass), index);
5226 mono_marshal_load_type_info (MonoClass* klass)
5228 int i, j, count = 0, native_size = 0, min_align = 1;
5229 MonoMarshalType *info;
5232 g_assert (klass != NULL);
5234 if (klass->marshal_info)
5235 return klass->marshal_info;
5238 mono_class_init (klass);
5240 for (i = 0; i < klass->field.count; ++i) {
5241 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
5243 if (mono_field_is_deleted (&klass->fields [i]))
5248 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
5250 klass->marshal_info = info = g_malloc0 (sizeof (MonoMarshalType) + sizeof (MonoMarshalField) * count);
5251 info->num_fields = count;
5253 /* Try to find a size for this type in metadata */
5254 mono_metadata_packing_from_typedef (klass->image, klass->type_token, NULL, &native_size);
5256 if (klass->parent) {
5257 int parent_size = mono_class_native_size (klass->parent, NULL);
5259 /* Add parent size to real size */
5260 native_size += parent_size;
5261 info->native_size = parent_size;
5264 for (j = i = 0; i < klass->field.count; ++i) {
5267 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
5270 if (mono_field_is_deleted (&klass->fields [i]))
5272 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL)
5273 mono_metadata_field_info (klass->image, klass->field.first + i,
5274 NULL, NULL, &info->fields [j].mspec);
5276 info->fields [j].field = &klass->fields [i];
5278 if ((klass->field.count == 1) && (klass->instance_size == sizeof (MonoObject)) &&
5279 (strcmp (klass->fields [i].name, "$PRIVATE$") == 0)) {
5280 /* This field is a hack inserted by MCS to empty structures */
5285 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
5286 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
5287 size = mono_marshal_type_size (klass->fields [i].type, info->fields [j].mspec,
5288 &align, TRUE, klass->unicode);
5289 align = klass->packing_size ? MIN (klass->packing_size, align): align;
5290 min_align = MAX (align, min_align);
5291 info->fields [j].offset = info->native_size;
5292 info->fields [j].offset += align - 1;
5293 info->fields [j].offset &= ~(align - 1);
5294 info->native_size = info->fields [j].offset + size;
5296 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
5298 info->fields [j].offset = klass->fields [i].offset - sizeof (MonoObject);
5299 info->native_size = klass->instance_size - sizeof (MonoObject);
5305 if(layout != TYPE_ATTRIBUTE_AUTO_LAYOUT) {
5306 info->native_size = MAX (native_size, info->native_size);
5309 if (info->native_size & (min_align - 1)) {
5310 info->native_size += min_align - 1;
5311 info->native_size &= ~(min_align - 1);
5314 return klass->marshal_info;
5318 * mono_class_native_size:
5321 * Returns: the native size of an object instance (when marshaled
5322 * to unmanaged code)
5325 mono_class_native_size (MonoClass *klass, guint32 *align)
5328 if (!klass->marshal_info)
5329 mono_marshal_load_type_info (klass);
5332 *align = klass->min_align;
5334 return klass->marshal_info->native_size;
5338 * mono_type_native_stack_size:
5339 * @t: the type to return the size it uses on the stack
5341 * Returns: the number of bytes required to hold an instance of this
5342 * type on the native stack
5345 mono_type_native_stack_size (MonoType *t, gint *align)
5349 g_assert (t != NULL);
5360 case MONO_TYPE_BOOLEAN:
5361 case MONO_TYPE_CHAR:
5370 case MONO_TYPE_STRING:
5371 case MONO_TYPE_OBJECT:
5372 case MONO_TYPE_CLASS:
5373 case MONO_TYPE_SZARRAY:
5375 case MONO_TYPE_FNPTR:
5376 case MONO_TYPE_ARRAY:
5377 case MONO_TYPE_TYPEDBYREF:
5388 case MONO_TYPE_VALUETYPE: {
5391 if (t->data.klass->enumtype)
5392 return mono_type_native_stack_size (t->data.klass->enum_basetype, align);
5394 size = mono_class_native_size (t->data.klass, align);
5395 *align = *align + 3;
5405 g_error ("type 0x%02x unknown", t->type);
5410 /* __alignof__ returns the preferred alignment of values not the actual alignment used by
5411 the compiler so is wrong e.g. for Linux where doubles are aligned on a 4 byte boundary
5412 but __alignof__ returns 8 - using G_STRUCT_OFFSET works better */
5413 #define ALIGNMENT(type) G_STRUCT_OFFSET(struct { char c; type x; }, x)
5416 mono_marshal_type_size (MonoType *type, MonoMarshalSpec *mspec, gint32 *align,
5417 gboolean as_field, gboolean unicode)
5419 MonoMarshalNative native_type = mono_type_to_unmanaged (type, mspec, as_field, unicode, NULL);
5422 switch (native_type) {
5423 case MONO_NATIVE_BOOLEAN:
5426 case MONO_NATIVE_I1:
5427 case MONO_NATIVE_U1:
5430 case MONO_NATIVE_I2:
5431 case MONO_NATIVE_U2:
5432 case MONO_NATIVE_VARIANTBOOL:
5435 case MONO_NATIVE_I4:
5436 case MONO_NATIVE_U4:
5437 case MONO_NATIVE_ERROR:
5440 case MONO_NATIVE_I8:
5441 case MONO_NATIVE_U8:
5442 *align = ALIGNMENT(guint64);
5444 case MONO_NATIVE_R4:
5447 case MONO_NATIVE_R8:
5448 *align = ALIGNMENT(double);
5450 case MONO_NATIVE_INT:
5451 case MONO_NATIVE_UINT:
5452 case MONO_NATIVE_LPSTR:
5453 case MONO_NATIVE_LPWSTR:
5454 case MONO_NATIVE_LPTSTR:
5455 case MONO_NATIVE_BSTR:
5456 case MONO_NATIVE_ANSIBSTR:
5457 case MONO_NATIVE_TBSTR:
5458 case MONO_NATIVE_LPARRAY:
5459 case MONO_NATIVE_SAFEARRAY:
5460 case MONO_NATIVE_IUNKNOWN:
5461 case MONO_NATIVE_IDISPATCH:
5462 case MONO_NATIVE_INTERFACE:
5463 case MONO_NATIVE_ASANY:
5464 case MONO_NATIVE_FUNC:
5465 case MONO_NATIVE_LPSTRUCT:
5466 *align = ALIGNMENT(gpointer);
5467 return sizeof (gpointer);
5468 case MONO_NATIVE_STRUCT:
5469 klass = mono_class_from_mono_type (type);
5470 return mono_class_native_size (klass, align);
5471 case MONO_NATIVE_BYVALTSTR: {
5472 int esize = unicode ? 2: 1;
5475 return mspec->data.array_data.num_elem * esize;
5477 case MONO_NATIVE_BYVALARRAY: {
5479 klass = mono_class_from_mono_type (type);
5480 esize = mono_class_native_size (klass->element_class, align);
5482 return mspec->data.array_data.num_elem * esize;
5484 case MONO_NATIVE_CUSTOM:
5485 g_assert_not_reached ();
5487 case MONO_NATIVE_CURRENCY:
5488 case MONO_NATIVE_VBBYREFSTR:
5490 g_error ("native type %02x not implemented", native_type);
5493 g_assert_not_reached ();
5498 mono_marshal_asany (MonoObject *o, MonoMarshalNative string_encoding)
5506 t = &o->vtable->klass->byval_arg;
5513 case MONO_TYPE_BOOLEAN:
5516 case MONO_TYPE_CHAR:
5521 return mono_object_unbox (o);
5523 case MONO_TYPE_STRING:
5524 switch (string_encoding) {
5525 case MONO_NATIVE_LPWSTR:
5526 return mono_string_to_utf16 ((MonoString*)o);
5528 case MONO_NATIVE_LPSTR:
5529 return mono_string_to_utf8 ((MonoString*)o);
5532 g_warning ("marshaling conversion %d not implemented", string_encoding);
5533 g_assert_not_reached ();
5536 case MONO_TYPE_CLASS:
5537 case MONO_TYPE_VALUETYPE: {
5541 MonoBoolean delete_old = FALSE;
5543 klass = t->data.klass;
5545 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT)
5548 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
5549 klass->blittable || klass->enumtype)
5550 return mono_object_unbox (o);
5552 res = g_malloc0 (mono_class_native_size (klass, NULL));
5554 method = mono_marshal_get_struct_to_ptr (o->vtable->klass);
5558 pa [2] = &delete_old;
5560 mono_runtime_invoke (method, NULL, pa, NULL);
5566 mono_raise_exception (mono_get_exception_argument ("", "No PInvoke conversion exists for value passed to Object-typed parameter."));
5572 mono_marshal_free_asany (MonoObject *o, gpointer ptr, MonoMarshalNative string_encoding)
5577 /* FIXME: Free embedded data as well */
5582 t = &o->vtable->klass->byval_arg;
5584 case MONO_TYPE_STRING:
5585 switch (string_encoding) {
5586 case MONO_NATIVE_LPWSTR:
5589 case MONO_NATIVE_LPSTR:
5593 g_warning ("marshaling conversion %d not implemented", string_encoding);
5594 g_assert_not_reached ();
5597 case MONO_TYPE_CLASS:
5598 case MONO_TYPE_VALUETYPE: {
5599 klass = t->data.klass;
5601 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
5602 klass->blittable || klass->enumtype)