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/monitor.h"
23 //#define DEBUG_RUNTIME_CODE
25 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
29 #include "mono/cil/opcode.def"
34 struct _MonoMethodBuilder {
38 guint32 code_size, pos;
43 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object);
46 mono_find_method_by_name (MonoClass *klass, const char *name, int param_count)
48 MonoMethod *res = NULL;
51 for (i = 0; i < klass->method.count; ++i) {
52 if (klass->methods [i]->name[0] == name [0] &&
53 !strcmp (name, klass->methods [i]->name) &&
54 klass->methods [i]->signature->param_count == param_count) {
55 res = klass->methods [i];
62 #ifdef DEBUG_RUNTIME_CODE
64 indenter (MonoDisHelper *dh, MonoMethod *method, guint32 ip_offset)
66 return g_strdup (" ");
69 static MonoDisHelper marshal_dh = {
79 /* This mutex protects the various marshalling related caches in MonoImage */
80 static CRITICAL_SECTION marshal_mutex;
83 mono_marshal_init (void)
85 static gboolean module_initialized = FALSE;
87 if (!module_initialized) {
88 module_initialized = TRUE;
89 InitializeCriticalSection (&marshal_mutex);
94 mono_delegate_to_ftnptr (MonoDelegate *delegate)
96 MonoMethod *method, *wrapper, *invoke;
97 MonoMarshalSpec **mspecs;
104 if (delegate->delegate_trampoline)
105 return delegate->delegate_trampoline;
107 klass = ((MonoObject *)delegate)->vtable->klass;
108 g_assert (klass->delegate);
111 method = delegate->method_info->method;
112 invoke = mono_find_method_by_name (klass, "Invoke", method->signature->param_count);
114 mspecs = g_new (MonoMarshalSpec*, invoke->signature->param_count + 1);
115 mono_method_get_marshal_info (invoke, mspecs);
117 wrapper = mono_marshal_get_managed_wrapper (method, delegate->target, mspecs);
119 for (i = invoke->signature->param_count; i >= 0; i--)
123 delegate->delegate_trampoline = mono_compile_method (wrapper);
125 return delegate->delegate_trampoline;
129 mono_array_to_savearray (MonoArray *array)
134 g_assert_not_reached ();
139 mono_array_to_lparray (MonoArray *array)
144 /* fixme: maybe we need to make a copy */
145 return array->vector;
149 mono_string_utf8_to_builder (MonoStringBuilder *sb, char *text)
151 GError *error = NULL;
161 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
163 if (items_written > sb->capacity)
164 items_written = sb->capacity;
167 memcpy (sb->chars->vector, ut, items_written * 2);
168 sb->length = items_written;
170 g_error_free (error);
176 mono_string_builder_to_utf8 (MonoStringBuilder *sb)
183 res = g_malloc (sb->capacity + 1);
185 /* fixme: copy the content of the string builder? */
192 mono_string_to_ansibstr (MonoString *string_obj)
194 g_error ("implement me");
199 mono_string_to_bstr (MonoString *string_obj)
201 g_error ("implement me");
206 mono_string_to_byvalstr (gpointer dst, MonoString *src, int size)
211 g_assert (dst != NULL);
214 memset (dst, 0, size);
219 s = mono_string_to_utf8 (src);
220 len = MIN (size, strlen (s));
221 memcpy (dst, s, len);
224 *((char *)dst + size - 1) = 0;
228 mono_string_to_byvalwstr (gpointer dst, MonoString *src, int size)
232 g_assert (dst != NULL);
236 memset (dst, 0, size);
240 len = MIN (size, (mono_string_length (src) * 2));
241 memcpy (dst, mono_string_chars (src), len);
243 *((char *)dst + size - 1) = 0;
244 *((char *)dst + size - 2) = 0;
248 mono_mb_free (MonoMethodBuilder *mb)
250 g_list_free (mb->locals_list);
255 mono_mb_new (MonoClass *klass, const char *name, MonoWrapperType type)
257 MonoMethodBuilder *mb;
260 g_assert (klass != NULL);
261 g_assert (name != NULL);
263 mb = g_new0 (MonoMethodBuilder, 1);
265 mb->method = m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
268 m->name = g_strdup (name);
270 m->inline_count = -1;
271 m->wrapper_type = type;
274 mb->code = g_malloc (mb->code_size);
280 mono_mb_add_local (MonoMethodBuilder *mb, MonoType *type)
282 int res = mb->locals;
284 g_assert (mb != NULL);
285 g_assert (type != NULL);
287 mb->locals_list = g_list_append (mb->locals_list, type);
294 mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack)
296 MonoMethodHeader *header;
300 g_assert (mb != NULL);
302 ((MonoMethodNormal *)mb->method)->header = header = (MonoMethodHeader *)
303 g_malloc0 (sizeof (MonoMethodHeader) + mb->locals * sizeof (MonoType *));
308 header->max_stack = max_stack;
310 for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
311 header->locals [i] = (MonoType *)l->data;
314 mb->method->signature = signature;
315 header->code = mb->code;
316 header->code_size = mb->pos;
317 header->num_locals = mb->locals;
319 #ifdef DEBUG_RUNTIME_CODE
320 printf ("RUNTIME CODE FOR %s\n", mono_method_full_name (mb->method, TRUE));
321 printf ("%s\n", mono_disasm_code (&marshal_dh, mb->method, mb->code, mb->code + mb->pos));
328 mono_mb_add_data (MonoMethodBuilder *mb, gpointer data)
330 MonoMethodWrapper *mw;
332 g_assert (mb != NULL);
334 mw = (MonoMethodWrapper *)mb->method;
336 mw->data = g_list_append (mw->data, data);
338 return g_list_length (mw->data);
342 mono_mb_patch_addr (MonoMethodBuilder *mb, int pos, int value)
344 mb->code [pos] = value & 0xff;
345 mb->code [pos + 1] = (value >> 8) & 0xff;
346 mb->code [pos + 2] = (value >> 16) & 0xff;
347 mb->code [pos + 3] = (value >> 24) & 0xff;
351 mono_mb_patch_addr_s (MonoMethodBuilder *mb, int pos, gint8 value)
353 *((gint8 *)(&mb->code [pos])) = value;
357 mono_mb_emit_byte (MonoMethodBuilder *mb, guint8 op)
359 if (mb->pos >= mb->code_size) {
361 mb->code = g_realloc (mb->code, mb->code_size);
364 mb->code [mb->pos++] = op;
368 mono_mb_emit_ldflda (MonoMethodBuilder *mb, gint32 offset)
370 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
371 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
374 mono_mb_emit_icon (mb, offset);
375 mono_mb_emit_byte (mb, CEE_ADD);
380 mono_mb_emit_proxy_check (MonoMethodBuilder *mb, int branch_code)
383 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoObject, vtable));
384 mono_mb_emit_byte (mb, CEE_LDIND_I);
385 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoVTable, klass));
386 mono_mb_emit_byte (mb, CEE_ADD);
387 mono_mb_emit_byte (mb, CEE_LDIND_I);
388 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
389 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
390 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_defaults.transparent_proxy_class));
391 mono_mb_emit_byte (mb, branch_code);
393 mono_mb_emit_i4 (mb, 0);
398 mono_mb_emit_i4 (MonoMethodBuilder *mb, gint32 data)
400 if ((mb->pos + 4) >= mb->code_size) {
402 mb->code = g_realloc (mb->code, mb->code_size);
405 mono_mb_patch_addr (mb, mb->pos, data);
410 mono_mb_emit_i2 (MonoMethodBuilder *mb, gint16 data)
412 if ((mb->pos + 2) >= mb->code_size) {
414 mb->code = g_realloc (mb->code, mb->code_size);
417 mb->code [mb->pos] = data & 0xff;
418 mb->code [mb->pos + 1] = (data >> 8) & 0xff;
423 mono_mb_emit_ldstr (MonoMethodBuilder *mb, char *str)
425 mono_mb_emit_byte (mb, CEE_LDSTR);
426 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, str));
431 mono_mb_emit_ldarg (MonoMethodBuilder *mb, guint argnum)
434 mono_mb_emit_byte (mb, CEE_LDARG_0 + argnum);
435 } else if (argnum < 256) {
436 mono_mb_emit_byte (mb, CEE_LDARG_S);
437 mono_mb_emit_byte (mb, argnum);
439 mono_mb_emit_byte (mb, CEE_PREFIX1);
440 mono_mb_emit_byte (mb, CEE_LDARG);
441 mono_mb_emit_i2 (mb, argnum);
446 mono_mb_emit_ldarg_addr (MonoMethodBuilder *mb, guint argnum)
449 mono_mb_emit_byte (mb, CEE_LDARGA_S);
450 mono_mb_emit_byte (mb, argnum);
452 mono_mb_emit_byte (mb, CEE_PREFIX1);
453 mono_mb_emit_byte (mb, CEE_LDARGA);
454 mono_mb_emit_i2 (mb, argnum);
459 mono_mb_emit_ldloc_addr (MonoMethodBuilder *mb, guint locnum)
462 mono_mb_emit_byte (mb, CEE_LDLOCA_S);
463 mono_mb_emit_byte (mb, locnum);
465 mono_mb_emit_byte (mb, CEE_PREFIX1);
466 mono_mb_emit_byte (mb, CEE_LDLOCA);
467 mono_mb_emit_i2 (mb, locnum);
472 mono_mb_emit_ldloc (MonoMethodBuilder *mb, guint num)
475 mono_mb_emit_byte (mb, CEE_LDLOC_0 + num);
476 } else if (num < 256) {
477 mono_mb_emit_byte (mb, CEE_LDLOC_S);
478 mono_mb_emit_byte (mb, num);
480 mono_mb_emit_byte (mb, CEE_PREFIX1);
481 mono_mb_emit_byte (mb, CEE_LDLOC);
482 mono_mb_emit_i2 (mb, num);
487 mono_mb_emit_stloc (MonoMethodBuilder *mb, guint num)
490 mono_mb_emit_byte (mb, CEE_STLOC_0 + num);
491 } else if (num < 256) {
492 mono_mb_emit_byte (mb, CEE_STLOC_S);
493 mono_mb_emit_byte (mb, num);
495 mono_mb_emit_byte (mb, CEE_PREFIX1);
496 mono_mb_emit_byte (mb, CEE_STLOC);
497 mono_mb_emit_i2 (mb, num);
502 mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value)
504 if (value >= -1 && value < 8) {
505 mono_mb_emit_byte (mb, CEE_LDC_I4_0 + value);
506 } else if (value >= -128 && value <= 127) {
507 mono_mb_emit_byte (mb, CEE_LDC_I4_S);
508 mono_mb_emit_byte (mb, value);
510 mono_mb_emit_byte (mb, CEE_LDC_I4);
511 mono_mb_emit_i4 (mb, value);
516 mono_mb_emit_managed_call (MonoMethodBuilder *mb, MonoMethod *method, MonoMethodSignature *opt_sig)
519 opt_sig = method->signature;
520 mono_mb_emit_byte (mb, CEE_PREFIX1);
521 mono_mb_emit_byte (mb, CEE_LDFTN);
522 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
523 mono_mb_emit_byte (mb, CEE_CALLI);
524 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, opt_sig));
528 mono_mb_emit_native_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, gpointer func)
530 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
531 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
532 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, func));
533 mono_mb_emit_byte (mb, CEE_CALLI);
534 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
538 mono_mb_emit_exception (MonoMethodBuilder *mb)
540 /* fixme: we need a better way to throw exception,
541 * supporting several exception types and messages */
542 static MonoMethod *missing_method_ctor = NULL;
544 if (!missing_method_ctor) {
545 MonoClass *mme = mono_class_from_name (mono_defaults.corlib, "System", "MissingMethodException");
547 mono_class_init (mme);
548 for (i = 0; i < mme->method.count; ++i) {
549 if (strcmp (mme->methods [i]->name, ".ctor") == 0 && mme->methods [i]->signature->param_count == 0) {
550 missing_method_ctor = mme->methods [i];
555 mono_mb_emit_byte (mb, CEE_NEWOBJ);
556 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, missing_method_ctor));
557 mono_mb_emit_byte (mb, CEE_THROW);
562 mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint16 local, gint32 incr)
564 mono_mb_emit_ldloc (mb, local);
565 mono_mb_emit_icon (mb, incr);
566 mono_mb_emit_byte (mb, CEE_ADD);
567 mono_mb_emit_stloc (mb, local);
571 emit_ptr_to_str_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv,
572 int usize, int msize, MonoMarshalSpec *mspec)
575 case MONO_MARSHAL_CONV_BOOL_I4:
576 mono_mb_emit_byte (mb, CEE_LDLOC_0);
577 mono_mb_emit_byte (mb, CEE_LDIND_I);
578 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
579 mono_mb_emit_byte (mb, 5);
580 mono_mb_emit_byte (mb, CEE_LDLOC_1);
581 mono_mb_emit_byte (mb, CEE_LDC_I4_1);
582 mono_mb_emit_byte (mb, CEE_STIND_I1);
583 mono_mb_emit_byte (mb, CEE_BR_S);
584 mono_mb_emit_byte (mb, 3);
585 mono_mb_emit_byte (mb, CEE_LDLOC_1);
586 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
587 mono_mb_emit_byte (mb, CEE_STIND_I1);
589 case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
593 if (type->type == MONO_TYPE_SZARRAY) {
594 eclass = type->data.klass;
596 g_assert_not_reached ();
599 if (eclass->valuetype)
600 esize = mono_class_instance_size (eclass) - sizeof (MonoObject);
602 esize = sizeof (gpointer);
604 /* create a new array */
605 mono_mb_emit_byte (mb, CEE_LDLOC_1);
606 mono_mb_emit_icon (mb, mspec->data.array_data.num_elem);
607 mono_mb_emit_byte (mb, CEE_NEWARR);
608 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eclass));
609 mono_mb_emit_byte (mb, CEE_STIND_I);
611 /* copy the elements */
612 mono_mb_emit_byte (mb, CEE_LDLOC_1);
613 mono_mb_emit_byte (mb, CEE_LDIND_I);
614 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
615 mono_mb_emit_byte (mb, CEE_ADD);
616 mono_mb_emit_byte (mb, CEE_LDLOC_0);
617 mono_mb_emit_icon (mb, mspec->data.array_data.num_elem * esize);
618 mono_mb_emit_byte (mb, CEE_PREFIX1);
619 mono_mb_emit_byte (mb, CEE_CPBLK);
623 case MONO_MARSHAL_CONV_STR_BYVALSTR:
624 mono_mb_emit_byte (mb, CEE_LDLOC_1);
625 mono_mb_emit_byte (mb, CEE_LDLOC_0);
626 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
627 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
628 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
629 mono_mb_emit_byte (mb, CEE_STIND_I);
631 case MONO_MARSHAL_CONV_STR_LPTSTR:
632 case MONO_MARSHAL_CONV_STR_LPSTR:
633 mono_mb_emit_byte (mb, CEE_LDLOC_1);
634 mono_mb_emit_byte (mb, CEE_LDLOC_0);
635 mono_mb_emit_byte (mb, CEE_LDIND_I);
636 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
637 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
638 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
639 mono_mb_emit_byte (mb, CEE_STIND_I);
641 case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
642 MonoClass *klass = mono_class_from_mono_type (type);
643 int src_var, dst_var;
645 src_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
646 dst_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
648 /* *dst = new object */
649 mono_mb_emit_byte (mb, CEE_LDLOC_1);
650 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
651 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
652 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
653 mono_mb_emit_byte (mb, CEE_STIND_I);
655 /* save the old src pointer */
656 mono_mb_emit_byte (mb, CEE_LDLOC_0);
657 mono_mb_emit_stloc (mb, src_var);
658 /* save the old dst pointer */
659 mono_mb_emit_byte (mb, CEE_LDLOC_1);
660 mono_mb_emit_stloc (mb, dst_var);
662 /* dst = pointer to newly created object data */
663 mono_mb_emit_byte (mb, CEE_LDLOC_1);
664 mono_mb_emit_byte (mb, CEE_LDIND_I);
665 mono_mb_emit_icon (mb, sizeof (MonoObject));
666 mono_mb_emit_byte (mb, CEE_ADD);
667 mono_mb_emit_byte (mb, CEE_STLOC_1);
669 emit_struct_conv (mb, klass, TRUE);
671 /* restore the old src pointer */
672 mono_mb_emit_ldloc (mb, src_var);
673 mono_mb_emit_byte (mb, CEE_STLOC_0);
674 /* restore the old dst pointer */
675 mono_mb_emit_ldloc (mb, dst_var);
676 mono_mb_emit_byte (mb, CEE_STLOC_1);
679 case MONO_MARSHAL_CONV_DEL_FTN: {
680 // fixme: we never convert functions back to delegates, dont
681 // know if thats the correct behaviour
684 case MONO_MARSHAL_CONV_STR_LPWSTR:
685 case MONO_MARSHAL_CONV_STR_BSTR:
686 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
687 case MONO_MARSHAL_CONV_STR_TBSTR:
688 case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
689 case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
690 case MONO_MARSHAL_CONV_STR_BYVALWSTR:
691 case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
693 g_warning ("marshaling conversion %d not implemented", conv);
694 g_assert_not_reached ();
699 emit_str_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, int usize, int msize,
700 MonoMarshalSpec *mspec)
705 case MONO_MARSHAL_CONV_BOOL_I4:
706 mono_mb_emit_byte (mb, CEE_LDLOC_1);
707 mono_mb_emit_byte (mb, CEE_LDLOC_0);
708 mono_mb_emit_byte (mb, CEE_LDIND_U1);
709 mono_mb_emit_byte (mb, CEE_STIND_I4);
711 case MONO_MARSHAL_CONV_STR_LPWSTR:
712 case MONO_MARSHAL_CONV_STR_LPSTR:
713 case MONO_MARSHAL_CONV_STR_LPTSTR:
714 case MONO_MARSHAL_CONV_STR_BSTR:
715 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
716 case MONO_MARSHAL_CONV_STR_TBSTR:
717 /* free space if free == true */
718 mono_mb_emit_byte (mb, CEE_LDLOC_2);
719 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
720 mono_mb_emit_byte (mb, 4);
721 mono_mb_emit_byte (mb, CEE_LDLOC_1);
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_FREE);
726 mono_mb_emit_byte (mb, CEE_LDLOC_1);
727 mono_mb_emit_byte (mb, CEE_LDLOC_0);
728 mono_mb_emit_byte (mb, CEE_LDIND_I);
729 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
730 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
731 mono_mb_emit_byte (mb, conv);
732 mono_mb_emit_byte (mb, CEE_STIND_I);
734 case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
735 case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
736 case MONO_MARSHAL_CONV_DEL_FTN:
737 mono_mb_emit_byte (mb, CEE_LDLOC_1);
738 mono_mb_emit_byte (mb, CEE_LDLOC_0);
739 mono_mb_emit_byte (mb, CEE_LDIND_I);
740 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
741 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
742 mono_mb_emit_byte (mb, conv);
743 mono_mb_emit_byte (mb, CEE_STIND_I);
745 case MONO_MARSHAL_CONV_STR_BYVALSTR:
746 case MONO_MARSHAL_CONV_STR_BYVALWSTR: {
750 mono_mb_emit_byte (mb, CEE_LDLOC_1); /* dst */
751 mono_mb_emit_byte (mb, CEE_LDLOC_0);
752 mono_mb_emit_byte (mb, CEE_LDIND_I); /* src String */
753 mono_mb_emit_icon (mb, usize);
754 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
755 mono_mb_emit_byte (mb, CEE_MONO_PROC3);
756 mono_mb_emit_byte (mb, conv);
759 case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
763 if (type->type == MONO_TYPE_SZARRAY) {
764 eclass = type->data.klass;
766 g_assert_not_reached ();
769 if (eclass->valuetype)
770 esize = mono_class_native_size (eclass, NULL);
772 esize = sizeof (gpointer);
777 mono_mb_emit_byte (mb, CEE_LDLOC_0);
778 mono_mb_emit_byte (mb, CEE_LDIND_I);
779 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
781 mono_mb_emit_byte (mb, 0);
783 mono_mb_emit_byte (mb, CEE_LDLOC_1);
784 mono_mb_emit_byte (mb, CEE_LDLOC_0);
785 mono_mb_emit_byte (mb, CEE_LDIND_I);
786 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
787 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
788 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
789 mono_mb_emit_byte (mb, CEE_ADD);
790 mono_mb_emit_icon (mb, mspec->data.array_data.num_elem * esize);
791 mono_mb_emit_byte (mb, CEE_PREFIX1);
792 mono_mb_emit_byte (mb, CEE_CPBLK);
793 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
796 case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
797 int src_var, dst_var;
799 src_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
800 dst_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
802 mono_mb_emit_byte (mb, CEE_LDLOC_0);
803 mono_mb_emit_byte (mb, CEE_LDIND_I);
804 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
806 mono_mb_emit_byte (mb, 0);
808 /* save the old src pointer */
809 mono_mb_emit_byte (mb, CEE_LDLOC_0);
810 mono_mb_emit_stloc (mb, src_var);
811 /* save the old dst pointer */
812 mono_mb_emit_byte (mb, CEE_LDLOC_1);
813 mono_mb_emit_stloc (mb, dst_var);
815 /* src = pointer to object data */
816 mono_mb_emit_byte (mb, CEE_LDLOC_0);
817 mono_mb_emit_byte (mb, CEE_LDIND_I);
818 mono_mb_emit_icon (mb, sizeof (MonoObject));
819 mono_mb_emit_byte (mb, CEE_ADD);
820 mono_mb_emit_byte (mb, CEE_STLOC_0);
822 emit_struct_conv (mb, mono_class_from_mono_type (type), FALSE);
824 /* restore the old src pointer */
825 mono_mb_emit_ldloc (mb, src_var);
826 mono_mb_emit_byte (mb, CEE_STLOC_0);
827 /* restore the old dst pointer */
828 mono_mb_emit_ldloc (mb, dst_var);
829 mono_mb_emit_byte (mb, CEE_STLOC_1);
831 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
834 case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
836 g_warning ("marshalling conversion %d not implemented", conv);
837 g_assert_not_reached ();
842 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
844 MonoMarshalType *info;
848 emit_struct_conv(mb, klass->parent, to_object);
850 info = mono_marshal_load_type_info (klass);
852 if (klass->blittable) {
853 mono_mb_emit_byte (mb, CEE_LDLOC_1);
854 mono_mb_emit_byte (mb, CEE_LDLOC_0);
855 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
856 mono_mb_emit_byte (mb, CEE_PREFIX1);
857 mono_mb_emit_byte (mb, CEE_CPBLK);
861 for (i = 0; i < info->num_fields; i++) {
862 MonoMarshalNative ntype;
863 MonoMarshalConv conv;
864 MonoType *ftype = info->fields [i].field->type;
867 gboolean last_field = i < (info->num_fields -1) ? 0 : 1;
869 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
872 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, klass->unicode, &conv);
875 msize = klass->instance_size - info->fields [i].field->offset;
876 usize = info->native_size - info->fields [i].offset;
878 msize = info->fields [i + 1].field->offset - info->fields [i].field->offset;
879 usize = info->fields [i + 1].offset - info->fields [i].offset;
881 g_assert ((msize >= 0) && (usize >= 0));
884 case MONO_MARSHAL_CONV_NONE: {
887 if (ftype->byref || ftype->type == MONO_TYPE_I ||
888 ftype->type == MONO_TYPE_U) {
889 mono_mb_emit_byte (mb, CEE_LDLOC_1);
890 mono_mb_emit_byte (mb, CEE_LDLOC_0);
891 mono_mb_emit_byte (mb, CEE_LDIND_I);
892 mono_mb_emit_byte (mb, CEE_STIND_I);
901 #if SIZEOF_VOID_P == 4
904 mono_mb_emit_byte (mb, CEE_LDLOC_1);
905 mono_mb_emit_byte (mb, CEE_LDLOC_0);
906 mono_mb_emit_byte (mb, CEE_LDIND_I4);
907 mono_mb_emit_byte (mb, CEE_STIND_I4);
911 case MONO_TYPE_BOOLEAN:
912 mono_mb_emit_byte (mb, CEE_LDLOC_1);
913 mono_mb_emit_byte (mb, CEE_LDLOC_0);
914 mono_mb_emit_byte (mb, CEE_LDIND_I1);
915 mono_mb_emit_byte (mb, CEE_STIND_I1);
919 mono_mb_emit_byte (mb, CEE_LDLOC_1);
920 mono_mb_emit_byte (mb, CEE_LDLOC_0);
921 mono_mb_emit_byte (mb, CEE_LDIND_I2);
922 mono_mb_emit_byte (mb, CEE_STIND_I2);
926 #if SIZEOF_VOID_P == 8
929 mono_mb_emit_byte (mb, CEE_LDLOC_1);
930 mono_mb_emit_byte (mb, CEE_LDLOC_0);
931 mono_mb_emit_byte (mb, CEE_LDIND_I8);
932 mono_mb_emit_byte (mb, CEE_STIND_I8);
935 mono_mb_emit_byte (mb, CEE_LDLOC_1);
936 mono_mb_emit_byte (mb, CEE_LDLOC_0);
937 mono_mb_emit_byte (mb, CEE_LDIND_R4);
938 mono_mb_emit_byte (mb, CEE_STIND_R4);
941 mono_mb_emit_byte (mb, CEE_LDLOC_1);
942 mono_mb_emit_byte (mb, CEE_LDLOC_0);
943 mono_mb_emit_byte (mb, CEE_LDIND_R8);
944 mono_mb_emit_byte (mb, CEE_STIND_R8);
946 case MONO_TYPE_VALUETYPE:
947 if (ftype->data.klass->enumtype) {
948 t = ftype->data.klass->enum_basetype->type;
951 emit_struct_conv (mb, ftype->data.klass, to_object);
954 g_warning ("marshaling type %02x not implemented", ftype->type);
955 g_assert_not_reached ();
961 emit_ptr_to_str_conv (mb, ftype, conv, usize, msize, info->fields [i].mspec);
963 emit_str_to_ptr_conv (mb, ftype, conv, usize, msize, info->fields [i].mspec);
967 mono_mb_emit_add_to_local (mb, 0, usize);
968 mono_mb_emit_add_to_local (mb, 1, msize);
970 mono_mb_emit_add_to_local (mb, 0, msize);
971 mono_mb_emit_add_to_local (mb, 1, usize);
976 static MonoAsyncResult *
977 mono_delegate_begin_invoke (MonoDelegate *delegate, gpointer *params)
979 MonoMethodMessage *msg;
980 MonoDelegate *async_callback;
984 MonoMethod *method = NULL;
989 if (delegate->target && mono_object_class (delegate->target) == mono_defaults.transparent_proxy_class) {
991 MonoTransparentProxy* tp = (MonoTransparentProxy *)delegate->target;
992 if (!tp->klass->contextbound || tp->rp->context != (MonoObject *) mono_context_get ()) {
994 // If the target is a proxy, make a direct call. Is proxy's work
995 // to make the call asynchronous.
997 MonoAsyncResult *ares;
1001 method = delegate->method_info->method;
1003 msg = mono_method_call_message_new (method, params, NULL, &async_callback, &state);
1004 handle = CreateEvent (NULL, TRUE, FALSE, NULL);
1005 ares = mono_async_result_new (mono_domain_get (), handle, state, handle);
1006 ares->async_delegate = (MonoObject *)async_callback;
1007 msg->async_result = ares;
1008 msg->call_type = CallType_BeginInvoke;
1010 mono_remoting_invoke ((MonoObject *)tp->rp, msg, &exc, &out_args);
1015 klass = delegate->object.vtable->klass;
1017 method = mono_get_delegate_invoke (klass);
1018 for (i = 0; i < klass->method.count; ++i) {
1019 if (klass->methods [i]->name[0] == 'B' &&
1020 !strcmp ("BeginInvoke", klass->methods [i]->name)) {
1021 method = klass->methods [i];
1026 g_assert (method != NULL);
1028 im = mono_get_delegate_invoke (method->klass);
1029 msg = mono_method_call_message_new (method, params, im, &async_callback, &state);
1031 return mono_thread_pool_add ((MonoObject *)delegate, msg, async_callback, state);
1035 mono_mb_emit_save_args (MonoMethodBuilder *mb, MonoMethodSignature *sig, gboolean save_this)
1037 int i, params_var, tmp_var;
1039 /* allocate local (pointer) *params[] */
1040 params_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1041 /* allocate local (pointer) tmp */
1042 tmp_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1044 /* alloate space on stack to store an array of pointers to the arguments */
1045 mono_mb_emit_icon (mb, sizeof (gpointer) * (sig->param_count + 1));
1046 mono_mb_emit_byte (mb, CEE_PREFIX1);
1047 mono_mb_emit_byte (mb, CEE_LOCALLOC);
1048 mono_mb_emit_stloc (mb, params_var);
1051 mono_mb_emit_ldloc (mb, params_var);
1052 mono_mb_emit_stloc (mb, tmp_var);
1054 if (save_this && sig->hasthis) {
1055 mono_mb_emit_ldloc (mb, tmp_var);
1056 mono_mb_emit_ldarg_addr (mb, 0);
1057 mono_mb_emit_byte (mb, CEE_STIND_I);
1058 /* tmp = tmp + sizeof (gpointer) */
1059 if (sig->param_count)
1060 mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
1064 for (i = 0; i < sig->param_count; i++) {
1065 mono_mb_emit_ldloc (mb, tmp_var);
1066 mono_mb_emit_ldarg_addr (mb, i + sig->hasthis);
1067 mono_mb_emit_byte (mb, CEE_STIND_I);
1068 /* tmp = tmp + sizeof (gpointer) */
1069 if (i < (sig->param_count - 1))
1070 mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
1077 mono_signature_to_name (MonoMethodSignature *sig, const char *prefix)
1081 GString *res = g_string_new ("");
1084 g_string_append (res, prefix);
1085 g_string_append_c (res, '_');
1088 mono_type_get_desc (res, sig->ret, FALSE);
1090 for (i = 0; i < sig->param_count; ++i) {
1091 g_string_append_c (res, '_');
1092 mono_type_get_desc (res, sig->params [i], FALSE);
1095 g_string_free (res, FALSE);
1099 static inline MonoMethod*
1100 mono_marshal_find_in_cache (GHashTable *cache, gpointer key)
1104 EnterCriticalSection (&marshal_mutex);
1105 res = g_hash_table_lookup (cache, key);
1106 LeaveCriticalSection (&marshal_mutex);
1110 /* Create the method from the builder and place it in the cache */
1111 static inline MonoMethod*
1112 mono_mb_create_and_cache (GHashTable *cache, gpointer key,
1113 MonoMethodBuilder *mb, MonoMethodSignature *sig,
1118 EnterCriticalSection (&marshal_mutex);
1119 res = g_hash_table_lookup (cache, key);
1121 /* This does not acquire any locks */
1122 res = mono_mb_create_method (mb, sig, max_stack);
1123 g_hash_table_insert (cache, key, res);
1126 /* Somebody created it before us */
1128 LeaveCriticalSection (&marshal_mutex);
1134 mono_marshal_get_delegate_begin_invoke (MonoMethod *method)
1136 MonoMethodSignature *sig;
1137 static MonoMethodSignature *csig = NULL;
1138 MonoMethodBuilder *mb;
1144 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1145 !strcmp (method->name, "BeginInvoke"));
1147 sig = method->signature;
1149 cache = method->klass->image->delegate_begin_invoke_cache;
1150 if ((res = mono_marshal_find_in_cache (cache, sig)))
1153 g_assert (sig->hasthis);
1156 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1157 csig = g_malloc0 (sigsize);
1159 /* MonoAsyncResult * begin_invoke (MonoDelegate *delegate, gpointer params[]) */
1160 csig->param_count = 2;
1161 csig->ret = &mono_defaults.object_class->byval_arg;
1162 csig->params [0] = &mono_defaults.object_class->byval_arg;
1163 csig->params [1] = &mono_defaults.int_class->byval_arg;
1166 name = mono_signature_to_name (sig, "begin_invoke");
1167 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_BEGIN_INVOKE);
1170 mb->method->save_lmf = 1;
1172 params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1174 mono_mb_emit_ldarg (mb, 0);
1175 mono_mb_emit_ldloc (mb, params_var);
1176 mono_mb_emit_native_call (mb, csig, mono_delegate_begin_invoke);
1177 mono_mb_emit_byte (mb, CEE_RET);
1179 res = mono_mb_create_and_cache (cache, sig, mb, sig, sig->param_count + 16);
1185 mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params)
1187 MonoDomain *domain = mono_domain_get ();
1188 MonoAsyncResult *ares;
1189 MonoMethod *method = NULL;
1190 MonoMethodSignature *sig;
1191 MonoMethodMessage *msg;
1192 MonoObject *res, *exc;
1193 MonoArray *out_args;
1197 g_assert (delegate);
1199 if (!delegate->method_info || !delegate->method_info->method)
1200 g_assert_not_reached ();
1202 klass = delegate->object.vtable->klass;
1204 for (i = 0; i < klass->method.count; ++i) {
1205 if (klass->methods [i]->name[0] == 'E' &&
1206 !strcmp ("EndInvoke", klass->methods [i]->name)) {
1207 method = klass->methods [i];
1212 g_assert (method != NULL);
1214 sig = method->signature;
1216 msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1218 ares = mono_array_get (msg->args, gpointer, sig->param_count - 1);
1221 if (delegate->target && mono_object_class (delegate->target) == mono_defaults.transparent_proxy_class) {
1222 MonoTransparentProxy* tp = (MonoTransparentProxy *)delegate->target;
1223 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
1224 mono_message_init (domain, msg, delegate->method_info, NULL);
1225 msg->call_type = CallType_EndInvoke;
1226 msg->async_result = ares;
1227 res = mono_remoting_invoke ((MonoObject *)tp->rp, msg, &exc, &out_args);
1230 res = mono_thread_pool_finish (ares, &out_args, &exc);
1233 char *strace = mono_string_to_utf8 (((MonoException*)exc)->stack_trace);
1235 tmp = g_strdup_printf ("%s\nException Rethrown at:\n", strace);
1237 ((MonoException*)exc)->stack_trace = mono_string_new (domain, tmp);
1239 mono_raise_exception ((MonoException*)exc);
1242 mono_method_return_message_restore (method, params, out_args);
1247 mono_mb_emit_restore_result (MonoMethodBuilder *mb, MonoType *return_type)
1249 if (return_type->byref)
1250 return_type = &mono_defaults.int_class->byval_arg;
1251 else if (return_type->type == MONO_TYPE_VALUETYPE && return_type->data.klass->enumtype)
1252 return_type = return_type->data.klass->enum_basetype;
1254 switch (return_type->type) {
1255 case MONO_TYPE_VOID:
1256 g_assert_not_reached ();
1259 case MONO_TYPE_STRING:
1260 case MONO_TYPE_CLASS:
1261 case MONO_TYPE_OBJECT:
1262 case MONO_TYPE_ARRAY:
1263 case MONO_TYPE_SZARRAY:
1267 case MONO_TYPE_BOOLEAN:
1268 mono_mb_emit_byte (mb, CEE_UNBOX);
1269 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1270 mono_mb_emit_byte (mb, CEE_LDIND_U1);
1273 mono_mb_emit_byte (mb, CEE_UNBOX);
1274 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1275 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1278 case MONO_TYPE_CHAR:
1279 mono_mb_emit_byte (mb, CEE_UNBOX);
1280 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1281 mono_mb_emit_byte (mb, CEE_LDIND_U2);
1284 mono_mb_emit_byte (mb, CEE_UNBOX);
1285 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1286 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1290 mono_mb_emit_byte (mb, CEE_UNBOX);
1291 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1292 mono_mb_emit_byte (mb, CEE_LDIND_I);
1295 mono_mb_emit_byte (mb, CEE_UNBOX);
1296 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1297 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1300 mono_mb_emit_byte (mb, CEE_UNBOX);
1301 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1302 mono_mb_emit_byte (mb, CEE_LDIND_U4);
1306 mono_mb_emit_byte (mb, CEE_UNBOX);
1307 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1308 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1311 mono_mb_emit_byte (mb, CEE_UNBOX);
1312 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1313 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1316 mono_mb_emit_byte (mb, CEE_UNBOX);
1317 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1318 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1320 case MONO_TYPE_VALUETYPE: {
1322 mono_mb_emit_byte (mb, CEE_UNBOX);
1323 class = mono_mb_add_data (mb, mono_class_from_mono_type (return_type));
1324 mono_mb_emit_i4 (mb, class);
1325 mono_mb_emit_byte (mb, CEE_LDOBJ);
1326 mono_mb_emit_i4 (mb, class);
1330 g_warning ("type 0x%x not handled", return_type->type);
1331 g_assert_not_reached ();
1334 mono_mb_emit_byte (mb, CEE_RET);
1338 mono_marshal_get_delegate_end_invoke (MonoMethod *method)
1340 MonoMethodSignature *sig;
1341 static MonoMethodSignature *csig = NULL;
1342 MonoMethodBuilder *mb;
1348 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1349 !strcmp (method->name, "EndInvoke"));
1351 sig = method->signature;
1353 cache = method->klass->image->delegate_end_invoke_cache;
1354 if ((res = mono_marshal_find_in_cache (cache, sig)))
1357 g_assert (sig->hasthis);
1360 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1361 csig = g_malloc0 (sigsize);
1363 /* MonoObject *end_invoke (MonoDelegate *delegate, gpointer params[]) */
1364 csig->param_count = 2;
1365 csig->ret = &mono_defaults.object_class->byval_arg;
1366 csig->params [0] = &mono_defaults.object_class->byval_arg;
1367 csig->params [1] = &mono_defaults.int_class->byval_arg;
1370 name = mono_signature_to_name (sig, "end_invoke");
1371 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_END_INVOKE);
1374 mb->method->save_lmf = 1;
1376 params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1378 mono_mb_emit_ldarg (mb, 0);
1379 mono_mb_emit_ldloc (mb, params_var);
1380 mono_mb_emit_native_call (mb, csig, mono_delegate_end_invoke);
1382 if (sig->ret->type == MONO_TYPE_VOID) {
1383 mono_mb_emit_byte (mb, CEE_POP);
1384 mono_mb_emit_byte (mb, CEE_RET);
1386 mono_mb_emit_restore_result (mb, sig->ret);
1388 res = mono_mb_create_and_cache (cache, sig,
1389 mb, sig, sig->param_count + 16);
1396 mono_remoting_wrapper (MonoMethod *method, gpointer *params)
1398 MonoMethodMessage *msg;
1399 MonoTransparentProxy *this;
1400 MonoObject *res, *exc;
1401 MonoArray *out_args;
1403 this = *((MonoTransparentProxy **)params [0]);
1406 g_assert (((MonoObject *)this)->vtable->klass == mono_defaults.transparent_proxy_class);
1408 /* skip the this pointer */
1411 if (this->klass->contextbound && this->rp->context == (MonoObject *) mono_context_get ())
1414 MonoMethodSignature *sig = method->signature;
1415 int count = sig->param_count;
1416 gpointer* mparams = (gpointer*) alloca(count*sizeof(gpointer));
1418 for (i=0; i<count; i++) {
1419 MonoClass *class = mono_class_from_mono_type (sig->params [i]);
1420 if (class->valuetype) {
1421 if (sig->params [i]->byref)
1422 mparams[i] = *((gpointer *)params [i]);
1424 mparams[i] = params [i];
1426 mparams[i] = *((gpointer**)params [i]);
1430 return mono_runtime_invoke (method, this->rp->unwrapped_server, mparams, NULL);
1433 msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1435 res = mono_remoting_invoke ((MonoObject *)this->rp, msg, &exc, &out_args);
1438 mono_raise_exception ((MonoException *)exc);
1440 mono_method_return_message_restore (method, params, out_args);
1446 mono_marshal_get_remoting_invoke (MonoMethod *method)
1448 MonoMethodSignature *sig;
1449 static MonoMethodSignature *csig = NULL;
1450 MonoMethodBuilder *mb;
1457 if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE)
1460 sig = method->signature;
1462 /* we cant remote methods without this pointer */
1466 cache = method->klass->image->remoting_invoke_cache;
1467 if ((res = mono_marshal_find_in_cache (cache, method)))
1471 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
1472 csig->params [0] = &mono_defaults.int_class->byval_arg;
1473 csig->params [1] = &mono_defaults.int_class->byval_arg;
1474 csig->ret = &mono_defaults.object_class->byval_arg;
1478 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE);
1479 mb->method->save_lmf = 1;
1481 params_var = mono_mb_emit_save_args (mb, sig, TRUE);
1483 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1484 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1485 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
1486 mono_mb_emit_ldloc (mb, params_var);
1487 mono_mb_emit_native_call (mb, csig, mono_remoting_wrapper);
1489 if (sig->ret->type == MONO_TYPE_VOID) {
1490 mono_mb_emit_byte (mb, CEE_POP);
1491 mono_mb_emit_byte (mb, CEE_RET);
1493 mono_mb_emit_restore_result (mb, sig->ret);
1496 res = mono_mb_create_and_cache (cache, method, mb, sig, sig->param_count + 16);
1503 mono_marshal_get_remoting_invoke_with_check (MonoMethod *method)
1505 MonoMethodSignature *sig;
1506 MonoMethodBuilder *mb;
1507 MonoMethod *res, *native;
1513 if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)
1516 sig = method->signature;
1518 /* we cant remote methods without this pointer */
1519 g_assert (sig->hasthis);
1521 cache = method->klass->image->remoting_invoke_cache;
1522 if ((res = mono_marshal_find_in_cache (cache, (char *)method + 1)))
1525 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK);
1527 mono_mb_emit_ldarg (mb, 0);
1528 pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
1530 native = mono_marshal_get_remoting_invoke (method);
1532 for (i = 0; i <= sig->param_count; i++)
1533 mono_mb_emit_ldarg (mb, i);
1535 mono_mb_emit_managed_call (mb, native, native->signature);
1536 mono_mb_emit_byte (mb, CEE_RET);
1538 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1540 for (i = 0; i <= sig->param_count; i++)
1541 mono_mb_emit_ldarg (mb, i);
1543 mono_mb_emit_managed_call (mb, method, method->signature);
1544 mono_mb_emit_byte (mb, CEE_RET);
1546 res = mono_mb_create_and_cache (cache, (char*)method + 1,
1547 mb, sig, sig->param_count + 16);
1554 * the returned method invokes all methods in a multicast delegate
1557 mono_marshal_get_delegate_invoke (MonoMethod *method)
1559 MonoMethodSignature *sig, *static_sig;
1561 MonoMethodBuilder *mb;
1567 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1568 !strcmp (method->name, "Invoke"));
1570 sig = method->signature;
1572 cache = method->klass->image->delegate_invoke_cache;
1573 if ((res = mono_marshal_find_in_cache (cache, sig)))
1576 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1577 static_sig = g_memdup (sig, sigsize);
1578 static_sig->hasthis = 0;
1580 name = mono_signature_to_name (sig, "invoke");
1581 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_INVOKE);
1584 /* allocate local 0 (object) */
1585 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1587 g_assert (sig->hasthis);
1591 * prev.Invoke( args .. );
1592 * return this.<target>( args .. );
1595 /* get this->prev */
1596 mono_mb_emit_ldarg (mb, 0);
1597 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoMulticastDelegate, prev));
1598 mono_mb_emit_byte (mb, CEE_LDIND_I );
1599 mono_mb_emit_stloc (mb, 0);
1601 /* if prev != null */
1602 mono_mb_emit_ldloc (mb, 0);
1603 mono_mb_emit_byte (mb, CEE_BRFALSE);
1606 mono_mb_emit_i4 (mb, 0);
1609 mono_mb_emit_ldloc (mb, 0);
1610 for (i = 0; i < sig->param_count; i++)
1611 mono_mb_emit_ldarg (mb, i + 1);
1612 mono_mb_emit_managed_call (mb, method, method->signature);
1613 if (sig->ret->type != MONO_TYPE_VOID)
1614 mono_mb_emit_byte (mb, CEE_POP);
1616 /* continued or prev == null */
1617 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1619 /* get this->target */
1620 mono_mb_emit_ldarg (mb, 0);
1621 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, target));
1622 mono_mb_emit_byte (mb, CEE_LDIND_I );
1623 mono_mb_emit_stloc (mb, 0);
1625 /* if target != null */
1626 mono_mb_emit_ldloc (mb, 0);
1627 mono_mb_emit_byte (mb, CEE_BRFALSE);
1629 mono_mb_emit_i4 (mb, 0);
1631 /* then call this->method_ptr nonstatic */
1632 mono_mb_emit_ldloc (mb, 0);
1633 for (i = 0; i < sig->param_count; ++i)
1634 mono_mb_emit_ldarg (mb, i + 1);
1635 mono_mb_emit_ldarg (mb, 0);
1636 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1637 mono_mb_emit_byte (mb, CEE_LDIND_I );
1638 mono_mb_emit_byte (mb, CEE_CALLI);
1639 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
1641 mono_mb_emit_byte (mb, CEE_BR);
1643 mono_mb_emit_i4 (mb, 0);
1645 /* else [target == null] call this->method_ptr static */
1646 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1648 for (i = 0; i < sig->param_count; ++i)
1649 mono_mb_emit_ldarg (mb, i + 1);
1650 mono_mb_emit_ldarg (mb, 0);
1651 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1652 mono_mb_emit_byte (mb, CEE_LDIND_I );
1653 mono_mb_emit_byte (mb, CEE_CALLI);
1654 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, static_sig));
1657 mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
1658 mono_mb_emit_byte (mb, CEE_RET);
1660 res = mono_mb_create_and_cache (cache, sig,
1661 mb, sig, sig->param_count + 16);
1668 * generates IL code for the runtime invoke function
1669 * MonoObject *runtime_invoke (MonoObject *this, void **params, MonoObject **exc)
1671 * we also catch exceptions if exc != null
1674 mono_marshal_get_runtime_invoke (MonoMethod *method)
1676 MonoMethodSignature *sig, *csig;
1677 MonoExceptionClause *clause;
1678 MonoMethodHeader *header;
1679 MonoMethodBuilder *mb;
1682 static MonoString *string_dummy = NULL;
1683 int i, pos, sigsize;
1687 cache = method->klass->image->runtime_invoke_cache;
1688 if ((res = mono_marshal_find_in_cache (cache, method)))
1691 /* to make it work with our special string constructors */
1693 string_dummy = mono_string_new_wrapper ("dummy");
1695 sig = method->signature;
1697 sigsize = sizeof (MonoMethodSignature) + 3 * sizeof (MonoType *);
1698 csig = g_malloc0 (sigsize);
1700 csig->param_count = 3;
1701 csig->ret = &mono_defaults.object_class->byval_arg;
1702 csig->params [0] = &mono_defaults.object_class->byval_arg;
1703 csig->params [1] = &mono_defaults.int_class->byval_arg;
1704 csig->params [2] = &mono_defaults.int_class->byval_arg;
1706 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_RUNTIME_INVOKE);
1708 /* allocate local 0 (object) tmp */
1709 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1710 /* allocate local 1 (object) exc */
1711 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1713 /* cond set *exc to null */
1714 mono_mb_emit_byte (mb, CEE_LDARG_2);
1715 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
1716 mono_mb_emit_byte (mb, 3);
1717 mono_mb_emit_byte (mb, CEE_LDARG_2);
1718 mono_mb_emit_byte (mb, CEE_LDNULL);
1719 mono_mb_emit_byte (mb, CEE_STIND_I);
1722 if (method->string_ctor) {
1723 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1724 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1725 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, string_dummy));
1727 mono_mb_emit_ldarg (mb, 0);
1728 if (method->klass->valuetype) {
1729 mono_mb_emit_byte (mb, CEE_UNBOX);
1730 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method->klass));
1735 for (i = 0; i < sig->param_count; i++) {
1736 MonoType *t = sig->params [i];
1739 mono_mb_emit_ldarg (mb, 1);
1741 mono_mb_emit_icon (mb, sizeof (gpointer) * i);
1742 mono_mb_emit_byte (mb, CEE_ADD);
1744 mono_mb_emit_byte (mb, CEE_LDIND_I);
1749 type = sig->params [i]->type;
1753 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1755 case MONO_TYPE_BOOLEAN:
1757 mono_mb_emit_byte (mb, CEE_LDIND_U1);
1760 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1763 case MONO_TYPE_CHAR:
1764 mono_mb_emit_byte (mb, CEE_LDIND_U2);
1768 mono_mb_emit_byte (mb, CEE_LDIND_I);
1771 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1774 mono_mb_emit_byte (mb, CEE_LDIND_U4);
1777 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1780 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1784 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1786 case MONO_TYPE_STRING:
1787 case MONO_TYPE_CLASS:
1788 case MONO_TYPE_ARRAY:
1790 case MONO_TYPE_SZARRAY:
1791 case MONO_TYPE_OBJECT:
1794 case MONO_TYPE_VALUETYPE:
1795 if (t->data.klass->enumtype) {
1796 type = t->data.klass->enum_basetype->type;
1799 mono_mb_emit_byte (mb, CEE_LDOBJ);
1800 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, t->data.klass));
1803 g_assert_not_reached ();
1807 if (method->string_ctor) {
1808 MonoMethodSignature *strsig;
1810 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1811 strsig = g_memdup (sig, sigsize);
1812 strsig->ret = &mono_defaults.string_class->byval_arg;
1814 mono_mb_emit_managed_call (mb, method, strsig);
1816 mono_mb_emit_managed_call (mb, method, NULL);
1818 if (sig->ret->byref) {
1820 g_assert_not_reached ();
1824 switch (sig->ret->type) {
1825 case MONO_TYPE_VOID:
1826 if (!method->string_ctor)
1827 mono_mb_emit_byte (mb, CEE_LDNULL);
1829 case MONO_TYPE_BOOLEAN:
1830 case MONO_TYPE_CHAR:
1843 case MONO_TYPE_VALUETYPE:
1844 /* box value types */
1845 mono_mb_emit_byte (mb, CEE_BOX);
1846 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (sig->ret)));
1848 case MONO_TYPE_STRING:
1849 case MONO_TYPE_CLASS:
1850 case MONO_TYPE_ARRAY:
1851 case MONO_TYPE_SZARRAY:
1852 case MONO_TYPE_OBJECT:
1857 g_assert_not_reached ();
1860 mono_mb_emit_stloc (mb, 0);
1862 mono_mb_emit_byte (mb, CEE_LEAVE);
1864 mono_mb_emit_i4 (mb, 0);
1866 clause = g_new0 (MonoExceptionClause, 1);
1867 clause->flags = MONO_EXCEPTION_CLAUSE_FILTER;
1868 clause->try_len = mb->pos;
1871 clause->token_or_filter = mb->pos;
1873 mono_mb_emit_byte (mb, CEE_POP);
1874 mono_mb_emit_byte (mb, CEE_LDARG_2);
1875 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
1876 mono_mb_emit_byte (mb, CEE_PREFIX1);
1877 mono_mb_emit_byte (mb, CEE_CGT_UN);
1878 mono_mb_emit_byte (mb, CEE_PREFIX1);
1879 mono_mb_emit_byte (mb, CEE_ENDFILTER);
1881 clause->handler_offset = mb->pos;
1884 /* store exception */
1885 mono_mb_emit_stloc (mb, 1);
1887 mono_mb_emit_byte (mb, CEE_LDARG_2);
1888 mono_mb_emit_ldloc (mb, 1);
1889 mono_mb_emit_byte (mb, CEE_STIND_I);
1891 mono_mb_emit_byte (mb, CEE_LEAVE);
1892 mono_mb_emit_i4 (mb, 0);
1894 clause->handler_len = mb->pos - clause->handler_offset;
1897 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1898 mono_mb_emit_ldloc (mb, 0);
1899 mono_mb_emit_byte (mb, CEE_RET);
1901 res = mono_mb_create_and_cache (cache, method,
1902 mb, csig, sig->param_count + 16);
1905 header = ((MonoMethodNormal *)res)->header;
1906 header->num_clauses = 1;
1907 header->clauses = clause;
1913 * generates IL code to call managed methods from unmanaged code
1916 mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this, MonoMarshalSpec **mspecs)
1918 MonoMethodSignature *sig, *csig;
1919 MonoMethodBuilder *mb;
1923 int i, pos, sigsize, *tmp_locals;
1925 g_assert (method != NULL);
1926 g_assert (!method->signature->pinvoke);
1928 cache = method->klass->image->managed_wrapper_cache;
1929 if (!this && (res = mono_marshal_find_in_cache (cache, method)))
1933 /* fime: howto free that memory ? */
1936 sig = method->signature;
1938 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_NATIVE_TO_MANAGED);
1940 /* allocate local 0 (pointer) src_ptr */
1941 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1942 /* allocate local 1 (pointer) dst_ptr */
1943 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1944 /* allocate local 2 (boolean) delete_old */
1945 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
1947 mono_mb_emit_byte (mb, CEE_LDNULL);
1948 mono_mb_emit_byte (mb, CEE_STLOC_2);
1950 /* we copy the signature, so that we can modify it */
1951 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1952 csig = g_memdup (sig, sigsize);
1956 /* fixme: howto handle this ? */
1960 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1961 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1962 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, this));
1967 g_assert_not_reached ();
1972 /* we first do all conversions */
1973 tmp_locals = alloca (sizeof (int) * sig->param_count);
1974 for (i = 0; i < sig->param_count; i ++) {
1975 MonoType *t = sig->params [i];
1976 MonoMarshalSpec *spec = mspecs [i + 1];
1980 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
1983 MonoMethod *marshal_native_to_managed;
1984 MonoMethod *get_instance;
1986 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
1987 g_assert (mtype != NULL);
1988 mklass = mono_class_from_mono_type (mtype);
1989 g_assert (mklass != NULL);
1991 marshal_native_to_managed = mono_find_method_by_name (mklass, "MarshalNativeToManaged", 1);
1992 g_assert (marshal_native_to_managed);
1993 get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
1994 g_assert (get_instance);
1997 case MONO_TYPE_CLASS:
1998 case MONO_TYPE_OBJECT:
1999 case MONO_TYPE_STRING:
2000 case MONO_TYPE_ARRAY:
2001 case MONO_TYPE_SZARRAY:
2005 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2007 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
2009 mono_mb_emit_byte (mb, CEE_CALL);
2010 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
2012 mono_mb_emit_ldarg (mb, i);
2014 mono_mb_emit_byte (mb, CEE_CALLVIRT);
2015 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_native_to_managed));
2017 mono_mb_emit_stloc (mb, tmp_locals [i]);
2020 g_warning ("custom marshalling of type %x is currently not supported", t->type);
2021 g_assert_not_reached ();
2028 case MONO_TYPE_VALUETYPE:
2030 klass = sig->params [i]->data.klass;
2031 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2032 klass->blittable || klass->enumtype)
2035 tmp_locals [i] = mono_mb_add_local (mb, &klass->byval_arg);
2038 mono_mb_emit_ldarg (mb, i);
2040 mono_mb_emit_ldarg_addr (mb, i);
2041 mono_mb_emit_byte (mb, CEE_STLOC_0);
2044 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2045 mono_mb_emit_byte (mb, CEE_BRFALSE);
2047 mono_mb_emit_i4 (mb, 0);
2050 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2051 mono_mb_emit_byte (mb, CEE_STLOC_1);
2053 /* emit valuetype convnversion code code */
2054 emit_struct_conv (mb, klass, TRUE);
2057 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2059 case MONO_TYPE_STRING:
2063 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2064 csig->params [i] = &mono_defaults.int_class->byval_arg;
2066 mono_mb_emit_ldarg (mb, i);
2067 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2068 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2069 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
2070 mono_mb_emit_stloc (mb, tmp_locals [i]);
2072 case MONO_TYPE_ARRAY:
2073 case MONO_TYPE_SZARRAY:
2077 klass = mono_class_from_mono_type (t);
2079 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2080 csig->params [i] = &mono_defaults.int_class->byval_arg;
2082 g_warning ("array marshaling not implemented");
2083 g_assert_not_reached ();
2088 for (i = 0; i < sig->param_count; i++) {
2089 MonoType *t = sig->params [i];
2092 case MONO_TYPE_BOOLEAN:
2106 mono_mb_emit_ldarg (mb, i);
2108 case MONO_TYPE_STRING:
2110 mono_mb_emit_ldarg (mb, i);
2112 g_assert (tmp_locals [i]);
2113 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2116 case MONO_TYPE_CLASS:
2117 case MONO_TYPE_ARRAY:
2118 case MONO_TYPE_SZARRAY:
2119 case MONO_TYPE_OBJECT:
2121 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2123 mono_mb_emit_ldarg (mb, i);
2125 case MONO_TYPE_VALUETYPE:
2126 klass = sig->params [i]->data.klass;
2127 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2128 klass->blittable || klass->enumtype) {
2129 mono_mb_emit_ldarg (mb, i);
2133 g_assert (tmp_locals [i]);
2135 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2137 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2140 g_warning ("type 0x%02x unknown", t->type);
2141 g_assert_not_reached ();
2145 mono_mb_emit_managed_call (mb, method, NULL);
2147 if (!sig->ret->byref) {
2148 switch (sig->ret->type) {
2149 case MONO_TYPE_VOID:
2150 case MONO_TYPE_BOOLEAN:
2164 case MONO_TYPE_OBJECT:
2165 mono_mb_emit_byte (mb, CEE_RET);
2167 case MONO_TYPE_STRING:
2168 csig->ret = &mono_defaults.int_class->byval_arg;
2170 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2171 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2172 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
2173 mono_mb_emit_byte (mb, CEE_RET);
2175 case MONO_TYPE_VALUETYPE: {
2177 klass = sig->ret->data.klass;
2178 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2179 klass->blittable || klass->enumtype)
2182 /* load pointer to returned value type */
2183 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2184 mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
2186 /* store the address of the source into local variable 0 */
2187 mono_mb_emit_byte (mb, CEE_STLOC_0);
2188 /* allocate space for the native struct and
2189 * store the address into dst_ptr */
2190 tmp = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2192 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2193 mono_mb_emit_byte (mb, CEE_PREFIX1);
2194 mono_mb_emit_byte (mb, CEE_LOCALLOC);
2195 mono_mb_emit_byte (mb, CEE_STLOC_1);
2196 mono_mb_emit_byte (mb, CEE_LDLOC_1);
2197 mono_mb_emit_stloc (mb, tmp);
2199 /* emit valuetype conversion code */
2200 emit_struct_conv (mb, klass, FALSE);
2201 mono_mb_emit_ldloc (mb, tmp);
2202 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2203 mono_mb_emit_byte (mb, CEE_MONO_RETOBJ);
2204 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2208 g_warning ("return type 0x%02x unknown", sig->ret->type);
2209 g_assert_not_reached ();
2212 mono_mb_emit_byte (mb, CEE_RET);
2216 res = mono_mb_create_and_cache (cache, method,
2217 mb, csig, sig->param_count + 16);
2219 res = mono_mb_create_method (mb, csig, sig->param_count + 16);
2226 * mono_marshal_get_ldfld_wrapper:
2227 * @type: the type of the field
2229 * This method generates a function which can be use to load a field with type
2230 * @type from an object. The generated function has the following signature:
2231 * <@type> ldfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset)
2234 mono_marshal_get_ldfld_wrapper (MonoType *type)
2236 MonoMethodSignature *sig, *csig;
2237 MonoMethodBuilder *mb;
2240 static GHashTable *ldfld_hash = NULL;
2247 if (type->type == MONO_TYPE_SZARRAY) {
2248 klass = mono_defaults.array_class;
2249 } else if (type->type == MONO_TYPE_VALUETYPE) {
2250 klass = type->data.klass;
2251 if (klass->enumtype) {
2252 t = klass->enum_basetype->type;
2253 klass = mono_class_from_mono_type (klass->enum_basetype);
2255 } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
2256 t == MONO_TYPE_CLASS) {
2257 klass = mono_defaults.object_class;
2258 } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
2259 klass = mono_defaults.int_class;
2261 klass = mono_class_from_mono_type (type);
2264 klass = mono_defaults.int_class;
2267 EnterCriticalSection (&marshal_mutex);
2269 ldfld_hash = g_hash_table_new (NULL, NULL);
2270 res = g_hash_table_lookup (ldfld_hash, klass);
2271 LeaveCriticalSection (&marshal_mutex);
2275 name = g_strdup_printf ("__ldfld_wrapper_%s.%s", klass->name_space, klass->name);
2276 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_LDFLD);
2279 mb->method->save_lmf = 1;
2281 sig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
2282 sig->params [0] = &mono_defaults.object_class->byval_arg;
2283 sig->params [1] = &mono_defaults.int_class->byval_arg;
2284 sig->params [2] = &mono_defaults.int_class->byval_arg;
2285 sig->params [3] = &mono_defaults.int_class->byval_arg;
2286 sig->ret = &klass->byval_arg;
2288 mono_mb_emit_ldarg (mb, 0);
2289 pos0 = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
2291 mono_mb_emit_ldarg (mb, 0);
2292 mono_mb_emit_ldarg (mb, 1);
2293 mono_mb_emit_ldarg (mb, 2);
2295 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
2296 csig->params [0] = &mono_defaults.object_class->byval_arg;
2297 csig->params [1] = &mono_defaults.int_class->byval_arg;
2298 csig->params [2] = &mono_defaults.int_class->byval_arg;
2299 csig->ret = &klass->this_arg;
2302 mono_mb_emit_native_call (mb, csig, mono_load_remote_field_new);
2304 if (klass->valuetype) {
2305 mono_mb_emit_byte (mb, CEE_UNBOX);
2306 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2307 mono_mb_emit_byte (mb, CEE_BR);
2309 mono_mb_emit_i4 (mb, 0);
2311 mono_mb_emit_byte (mb, CEE_RET);
2315 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
2317 mono_mb_emit_ldarg (mb, 0);
2318 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2319 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2320 mono_mb_emit_ldarg (mb, 3);
2321 mono_mb_emit_byte (mb, CEE_ADD);
2323 if (klass->valuetype)
2324 mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
2329 case MONO_TYPE_BOOLEAN:
2330 mono_mb_emit_byte (mb, CEE_LDIND_I1);
2332 case MONO_TYPE_CHAR:
2335 mono_mb_emit_byte (mb, CEE_LDIND_I2);
2339 mono_mb_emit_byte (mb, CEE_LDIND_I4);
2343 mono_mb_emit_byte (mb, CEE_LDIND_I8);
2346 mono_mb_emit_byte (mb, CEE_LDIND_R4);
2349 mono_mb_emit_byte (mb, CEE_LDIND_R8);
2351 case MONO_TYPE_ARRAY:
2353 case MONO_TYPE_FNPTR:
2354 case MONO_TYPE_SZARRAY:
2355 case MONO_TYPE_OBJECT:
2356 case MONO_TYPE_CLASS:
2357 case MONO_TYPE_STRING:
2360 mono_mb_emit_byte (mb, CEE_LDIND_I);
2362 case MONO_TYPE_VALUETYPE:
2363 g_assert (!klass->enumtype);
2364 mono_mb_emit_byte (mb, CEE_LDOBJ);
2365 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2368 g_warning ("type %x not implemented", type->type);
2369 g_assert_not_reached ();
2372 mono_mb_emit_byte (mb, CEE_RET);
2374 res = mono_mb_create_and_cache (ldfld_hash, klass,
2375 mb, sig, sig->param_count + 16);
2382 * mono_marshal_get_stfld_wrapper:
2383 * @type: the type of the field
2385 * This method generates a function which can be use to store a field with type
2386 * @type. The generated function has the following signature:
2387 * void stfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset, <@type> val)
2390 mono_marshal_get_stfld_wrapper (MonoType *type)
2392 MonoMethodSignature *sig, *csig;
2393 MonoMethodBuilder *mb;
2396 static GHashTable *stfld_hash = NULL;
2403 if (type->type == MONO_TYPE_SZARRAY) {
2404 klass = mono_defaults.array_class;
2405 } else if (type->type == MONO_TYPE_VALUETYPE) {
2406 klass = type->data.klass;
2407 if (klass->enumtype) {
2408 t = klass->enum_basetype->type;
2409 klass = mono_class_from_mono_type (klass->enum_basetype);
2411 } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
2412 t == MONO_TYPE_CLASS) {
2413 klass = mono_defaults.object_class;
2414 } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
2415 klass = mono_defaults.int_class;
2417 klass = mono_class_from_mono_type (type);
2420 klass = mono_defaults.int_class;
2423 EnterCriticalSection (&marshal_mutex);
2425 stfld_hash = g_hash_table_new (NULL, NULL);
2426 res = g_hash_table_lookup (stfld_hash, klass);
2427 LeaveCriticalSection (&marshal_mutex);
2431 name = g_strdup_printf ("__stfld_wrapper_%s.%s", klass->name_space, klass->name);
2432 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_STFLD);
2435 mb->method->save_lmf = 1;
2437 sig = mono_metadata_signature_alloc (mono_defaults.corlib, 5);
2438 sig->params [0] = &mono_defaults.object_class->byval_arg;
2439 sig->params [1] = &mono_defaults.int_class->byval_arg;
2440 sig->params [2] = &mono_defaults.int_class->byval_arg;
2441 sig->params [3] = &mono_defaults.int_class->byval_arg;
2442 sig->params [4] = &klass->byval_arg;
2443 sig->ret = &mono_defaults.void_class->byval_arg;
2445 mono_mb_emit_ldarg (mb, 0);
2446 pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
2448 mono_mb_emit_ldarg (mb, 0);
2449 mono_mb_emit_ldarg (mb, 1);
2450 mono_mb_emit_ldarg (mb, 2);
2451 mono_mb_emit_ldarg (mb, 4);
2453 if (klass->valuetype) {
2454 mono_mb_emit_byte (mb, CEE_BOX);
2455 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2458 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
2459 csig->params [0] = &mono_defaults.object_class->byval_arg;
2460 csig->params [1] = &mono_defaults.int_class->byval_arg;
2461 csig->params [2] = &mono_defaults.int_class->byval_arg;
2462 csig->params [3] = &klass->this_arg;
2463 csig->ret = &mono_defaults.void_class->byval_arg;
2466 mono_mb_emit_native_call (mb, csig, mono_store_remote_field_new);
2468 mono_mb_emit_byte (mb, CEE_RET);
2470 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2472 mono_mb_emit_ldarg (mb, 0);
2473 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2474 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2475 mono_mb_emit_ldarg (mb, 3);
2476 mono_mb_emit_byte (mb, CEE_ADD);
2477 mono_mb_emit_ldarg (mb, 4);
2482 case MONO_TYPE_BOOLEAN:
2483 mono_mb_emit_byte (mb, CEE_STIND_I1);
2485 case MONO_TYPE_CHAR:
2488 mono_mb_emit_byte (mb, CEE_STIND_I2);
2492 mono_mb_emit_byte (mb, CEE_STIND_I4);
2496 mono_mb_emit_byte (mb, CEE_STIND_I8);
2499 mono_mb_emit_byte (mb, CEE_STIND_R4);
2502 mono_mb_emit_byte (mb, CEE_STIND_R8);
2504 case MONO_TYPE_ARRAY:
2506 case MONO_TYPE_FNPTR:
2507 case MONO_TYPE_SZARRAY:
2508 case MONO_TYPE_OBJECT:
2509 case MONO_TYPE_CLASS:
2510 case MONO_TYPE_STRING:
2513 mono_mb_emit_byte (mb, CEE_STIND_I);
2515 case MONO_TYPE_VALUETYPE:
2516 g_assert (!klass->enumtype);
2517 mono_mb_emit_byte (mb, CEE_STOBJ);
2518 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2521 g_warning ("type %x not implemented", type->type);
2522 g_assert_not_reached ();
2525 mono_mb_emit_byte (mb, CEE_RET);
2527 res = mono_mb_create_and_cache (stfld_hash, klass,
2528 mb, sig, sig->param_count + 16);
2535 * generates IL code for the icall wrapper (the generated method
2536 * calls the unamnaged code in func)
2539 mono_marshal_get_icall_wrapper (MonoMethodSignature *sig, const char *name, gconstpointer func)
2541 MonoMethodSignature *csig;
2542 MonoMethodBuilder *mb;
2546 g_assert (sig->pinvoke);
2548 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_MANAGED_TO_NATIVE);
2550 mb->method->save_lmf = 1;
2552 /* we copy the signature, so that we can modify it */
2553 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
2556 mono_mb_emit_byte (mb, CEE_LDARG_0);
2558 for (i = 0; i < sig->param_count; i++)
2559 mono_mb_emit_ldarg (mb, i + sig->hasthis);
2561 mono_mb_emit_native_call (mb, sig, (gpointer) func);
2563 mono_mb_emit_byte (mb, CEE_RET);
2565 csig = g_memdup (sig, sigsize);
2568 res = mono_mb_create_method (mb, csig, csig->param_count + 16);
2575 * generates IL code for the pinvoke wrapper (the generated method
2576 * calls the unmanaged code in method->addr)
2579 mono_marshal_get_native_wrapper (MonoMethod *method)
2581 MonoMethodSignature *sig, *csig;
2582 MonoMethodPInvoke *piinfo;
2583 MonoMethodBuilder *mb;
2584 MonoMarshalSpec **mspecs;
2588 gboolean pinvoke = FALSE;
2589 int i, pos, argnum, *tmp_locals;
2592 g_assert (method != NULL);
2593 g_assert (method->signature->pinvoke);
2595 cache = method->klass->image->native_wrapper_cache;
2596 if ((res = mono_marshal_find_in_cache (cache, method)))
2599 sig = method->signature;
2600 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
2602 if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
2603 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2606 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_MANAGED_TO_NATIVE);
2608 mb->method->save_lmf = 1;
2610 if (pinvoke && !method->addr)
2611 mono_lookup_pinvoke_call (method);
2613 piinfo = (MonoMethodPInvoke *)method;
2615 if (!method->addr) {
2616 mono_mb_emit_exception (mb);
2617 csig = g_memdup (sig, sigsize);
2619 res = mono_mb_create_and_cache (cache, method,
2620 mb, csig, csig->param_count + 16);
2625 /* internal calls: we simply push all arguments and call the method (no conversions) */
2626 if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
2628 /* hack - string constructors returns a value */
2629 if (method->string_ctor) {
2630 csig = g_memdup (sig, sigsize);
2631 csig->ret = &mono_defaults.string_class->byval_arg;
2636 mono_mb_emit_byte (mb, CEE_LDARG_0);
2638 for (i = 0; i < sig->param_count; i++)
2639 mono_mb_emit_ldarg (mb, i + sig->hasthis);
2641 g_assert (method->addr);
2642 mono_mb_emit_native_call (mb, csig, method->addr);
2644 mono_mb_emit_byte (mb, CEE_RET);
2646 csig = g_memdup (csig, sigsize);
2648 res = mono_mb_create_and_cache (cache, method,
2649 mb, csig, csig->param_count + 16);
2656 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
2657 mono_method_get_marshal_info (method, mspecs);
2659 /* pinvoke: we need to convert the arguments if necessary */
2661 /* we copy the signature, so that we can set pinvoke to 0 */
2662 csig = g_memdup (sig, sigsize);
2665 /* we allocate local for use with emit_struct_conv() */
2666 /* allocate local 0 (pointer) src_ptr */
2667 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2668 /* allocate local 1 (pointer) dst_ptr */
2669 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2670 /* allocate local 2 (boolean) delete_old */
2671 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2673 /* delete_old = FALSE */
2674 mono_mb_emit_icon (mb, 0);
2675 mono_mb_emit_byte (mb, CEE_STLOC_2);
2677 if (!MONO_TYPE_IS_VOID(sig->ret)) {
2678 /* allocate local 3 to store the return value */
2679 mono_mb_add_local (mb, sig->ret);
2682 /* we first do all conversions */
2683 tmp_locals = alloca (sizeof (int) * sig->param_count);
2685 for (i = 0; i < sig->param_count; i ++) {
2686 MonoType *t = sig->params [i];
2687 MonoMarshalSpec *spec = mspecs [i + 1];
2689 argnum = i + sig->hasthis;
2692 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
2695 MonoMethod *marshal_managed_to_native;
2696 MonoMethod *get_instance;
2698 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
2699 g_assert (mtype != NULL);
2700 mklass = mono_class_from_mono_type (mtype);
2701 g_assert (mklass != NULL);
2703 marshal_managed_to_native = mono_find_method_by_name (mklass, "MarshalManagedToNative", 1);
2704 g_assert (marshal_managed_to_native);
2705 get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
2706 g_assert (get_instance);
2709 case MONO_TYPE_CLASS:
2710 case MONO_TYPE_OBJECT:
2711 case MONO_TYPE_STRING:
2712 case MONO_TYPE_ARRAY:
2713 case MONO_TYPE_SZARRAY:
2717 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2719 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
2721 mono_mb_emit_byte (mb, CEE_CALL);
2722 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
2724 mono_mb_emit_ldarg (mb, argnum);
2726 mono_mb_emit_byte (mb, CEE_CALLVIRT);
2727 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_managed_to_native));
2729 mono_mb_emit_stloc (mb, tmp_locals [i]);
2732 g_warning ("custom marshalling of type %x is currently not supported", t->type);
2733 g_assert_not_reached ();
2741 case MONO_TYPE_VALUETYPE:
2742 klass = t->data.klass;
2744 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2745 klass->blittable || klass->enumtype)
2748 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2750 /* store the address of the source into local variable 0 */
2752 mono_mb_emit_ldarg (mb, argnum);
2754 mono_mb_emit_ldarg_addr (mb, argnum);
2756 mono_mb_emit_byte (mb, CEE_STLOC_0);
2758 /* allocate space for the native struct and
2759 * store the address into local variable 1 (dest) */
2760 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2761 mono_mb_emit_byte (mb, CEE_PREFIX1);
2762 mono_mb_emit_byte (mb, CEE_LOCALLOC);
2763 mono_mb_emit_stloc (mb, tmp_locals [i]);
2766 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2767 mono_mb_emit_byte (mb, CEE_BRFALSE);
2769 mono_mb_emit_i4 (mb, 0);
2773 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2774 mono_mb_emit_byte (mb, CEE_STLOC_1);
2776 /* emit valuetype conversion code */
2777 emit_struct_conv (mb, klass, FALSE);
2780 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2782 case MONO_TYPE_STRING:
2783 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2784 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2787 if (t->attrs & PARAM_ATTRIBUTE_OUT)
2790 mono_mb_emit_ldarg (mb, argnum);
2791 mono_mb_emit_byte (mb, CEE_LDIND_I);
2793 mono_mb_emit_ldarg (mb, argnum);
2796 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2797 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2800 switch (spec->native) {
2801 case MONO_NATIVE_LPWSTR:
2802 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPWSTR);
2804 case MONO_NATIVE_LPSTR:
2805 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
2808 g_warning ("marshalling conversion %d not implemented", spec->native);
2809 g_assert_not_reached ();
2812 switch (piinfo->piflags & PINVOKE_ATTRIBUTE_CHAR_SET_MASK) {
2813 case PINVOKE_ATTRIBUTE_CHAR_SET_ANSI:
2814 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
2816 case PINVOKE_ATTRIBUTE_CHAR_SET_UNICODE:
2817 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPWSTR);
2819 case PINVOKE_ATTRIBUTE_CHAR_SET_AUTO:
2820 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPTSTR);
2823 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
2828 mono_mb_emit_stloc (mb, tmp_locals [i]);
2830 case MONO_TYPE_CLASS:
2831 case MONO_TYPE_OBJECT:
2832 klass = t->data.klass;
2834 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2835 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2837 if (klass->delegate) {
2838 g_assert (!t->byref);
2839 mono_mb_emit_ldarg (mb, argnum);
2840 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2841 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2842 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_DEL_FTN);
2843 mono_mb_emit_stloc (mb, tmp_locals [i]);
2844 } else if (klass == mono_defaults.stringbuilder_class) {
2845 g_assert (!t->byref);
2846 mono_mb_emit_ldarg (mb, argnum);
2847 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2848 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2849 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_SB_LPSTR);
2850 mono_mb_emit_stloc (mb, tmp_locals [i]);
2852 mono_mb_emit_byte (mb, CEE_LDNULL);
2853 mono_mb_emit_stloc (mb, tmp_locals [i]);
2856 /* we dont need any conversions for out parameters */
2857 if (t->attrs & PARAM_ATTRIBUTE_OUT)
2860 mono_mb_emit_ldarg (mb, argnum);
2861 mono_mb_emit_byte (mb, CEE_LDIND_I);
2864 mono_mb_emit_ldarg (mb, argnum);
2865 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2866 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2869 /* store the address of the source into local variable 0 */
2870 mono_mb_emit_byte (mb, CEE_STLOC_0);
2871 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2872 mono_mb_emit_byte (mb, CEE_BRFALSE);
2874 mono_mb_emit_i4 (mb, 0);
2876 /* allocate space for the native struct and store the address */
2877 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2878 mono_mb_emit_byte (mb, CEE_PREFIX1);
2879 mono_mb_emit_byte (mb, CEE_LOCALLOC);
2880 mono_mb_emit_stloc (mb, tmp_locals [i]);
2882 /* set the src_ptr */
2883 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2884 mono_mb_emit_icon (mb, sizeof (MonoObject));
2885 mono_mb_emit_byte (mb, CEE_ADD);
2886 mono_mb_emit_byte (mb, CEE_STLOC_0);
2889 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2890 mono_mb_emit_byte (mb, CEE_STLOC_1);
2892 /* emit valuetype conversion code */
2893 emit_struct_conv (mb, klass, FALSE);
2895 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2899 case MONO_TYPE_ARRAY:
2900 case MONO_TYPE_SZARRAY:
2904 klass = mono_class_from_mono_type (t);
2906 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2907 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2909 mono_mb_emit_ldarg (mb, argnum);
2910 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2911 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2912 if (klass->element_class == mono_defaults.string_class)
2913 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STRARRAY_STRLPARRAY);
2915 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_ARRAY_LPARRAY);
2916 mono_mb_emit_stloc (mb, tmp_locals [i]);
2921 /* push all arguments */
2924 mono_mb_emit_byte (mb, CEE_LDARG_0);
2926 for (i = 0; i < sig->param_count; i++) {
2927 MonoType *t = sig->params [i];
2929 argnum = i + sig->hasthis;
2932 case MONO_TYPE_BOOLEAN:
2934 g_warning ("byref boolean marshalling not inplemented");
2935 mono_mb_emit_ldarg (mb, argnum);
2950 mono_mb_emit_ldarg (mb, argnum);
2952 case MONO_TYPE_VALUETYPE:
2953 klass = sig->params [i]->data.klass;
2954 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2955 klass->blittable || klass->enumtype) {
2956 mono_mb_emit_ldarg (mb, argnum);
2959 g_assert (tmp_locals [i]);
2960 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2962 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2963 mono_mb_emit_byte (mb, CEE_MONO_LDNATIVEOBJ);
2964 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2967 case MONO_TYPE_STRING:
2968 case MONO_TYPE_CLASS:
2969 case MONO_TYPE_OBJECT:
2970 g_assert (tmp_locals [i]);
2972 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2974 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2976 case MONO_TYPE_CHAR:
2977 /* fixme: dont know how to marshal that. We cant simply
2978 * convert it to a one byte UTF8 character, because an
2979 * unicode character may need more that one byte in UTF8 */
2980 mono_mb_emit_ldarg (mb, argnum);
2982 case MONO_TYPE_ARRAY:
2983 case MONO_TYPE_SZARRAY:
2985 mono_mb_emit_ldarg (mb, argnum);
2987 g_assert (tmp_locals [i]);
2988 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2991 case MONO_TYPE_TYPEDBYREF:
2992 case MONO_TYPE_FNPTR:
2994 g_warning ("type 0x%02x unknown", t->type);
2995 g_assert_not_reached ();
2999 /* call the native method */
3000 mono_mb_emit_native_call (mb, csig, method->addr);
3002 /* convert the result */
3003 if (!sig->ret->byref) {
3004 MonoMarshalSpec *spec = mspecs [0];
3005 type = sig->ret->type;
3007 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
3010 MonoMethod *marshal_native_to_managed;
3011 MonoMethod *get_instance;
3013 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
3014 g_assert (mtype != NULL);
3015 mklass = mono_class_from_mono_type (mtype);
3016 g_assert (mklass != NULL);
3018 marshal_native_to_managed = mono_find_method_by_name (mklass, "MarshalNativeToManaged", 1);
3019 g_assert (marshal_native_to_managed);
3020 get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
3021 g_assert (get_instance);
3024 case MONO_TYPE_CLASS:
3025 case MONO_TYPE_OBJECT:
3026 case MONO_TYPE_STRING:
3027 case MONO_TYPE_ARRAY:
3028 case MONO_TYPE_SZARRAY:
3029 mono_mb_emit_byte (mb, CEE_STLOC_3);
3031 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
3033 mono_mb_emit_byte (mb, CEE_CALL);
3034 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
3036 mono_mb_emit_byte (mb, CEE_LDLOC_3);
3038 mono_mb_emit_byte (mb, CEE_CALLVIRT);
3039 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_native_to_managed));
3041 mono_mb_emit_byte (mb, CEE_STLOC_3);
3044 g_warning ("custom marshalling of type %x is currently not supported", type);
3045 g_assert_not_reached ();
3052 case MONO_TYPE_VOID:
3067 /* no conversions necessary */
3068 mono_mb_emit_byte (mb, CEE_STLOC_3);
3070 case MONO_TYPE_BOOLEAN:
3071 /* maybe we need to make sure that it fits within 8 bits */
3072 mono_mb_emit_byte (mb, CEE_STLOC_3);
3074 case MONO_TYPE_VALUETYPE:
3075 klass = sig->ret->data.klass;
3076 if (klass->enumtype) {
3077 type = sig->ret->data.klass->enum_basetype->type;
3081 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3083 mono_mb_emit_byte (mb, CEE_STLOC_3);
3086 /* load pointer to returned value type */
3087 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3088 mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
3089 /* store the address of the source into local variable 0 */
3090 mono_mb_emit_byte (mb, CEE_STLOC_0);
3092 mono_mb_emit_ldloc_addr (mb, 3);
3093 mono_mb_emit_byte (mb, CEE_STLOC_1);
3095 /* emit valuetype conversion code */
3096 emit_struct_conv (mb, sig->ret->data.klass, TRUE);
3098 case MONO_TYPE_STRING:
3099 #ifdef GTK_SHARP_FIXED
3100 mono_mb_emit_byte (mb, CEE_STLOC_0);
3101 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3104 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3105 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3107 switch (spec->native) {
3108 case MONO_NATIVE_LPWSTR:
3109 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPWSTR_STR);
3112 g_warning ("marshalling conversion not implemented");
3113 g_assert_not_reached ();
3116 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
3118 mono_mb_emit_byte (mb, CEE_STLOC_3);
3120 #ifdef GTK_SHARP_FIXED
3121 /* free the string */
3122 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3123 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3124 mono_mb_emit_byte (mb, CEE_MONO_FREE);
3127 case MONO_TYPE_CLASS:
3128 case MONO_TYPE_OBJECT:
3129 klass = sig->ret->data.klass;
3132 mono_mb_emit_byte (mb, CEE_STLOC_0);
3134 mono_mb_emit_byte (mb, CEE_LDNULL);
3135 mono_mb_emit_byte (mb, CEE_STLOC_3);
3138 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3139 mono_mb_emit_byte (mb, CEE_BRFALSE);
3141 mono_mb_emit_i4 (mb, 0);
3143 /* allocate result object */
3145 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3146 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
3147 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3148 mono_mb_emit_byte (mb, CEE_STLOC_3);
3152 mono_mb_emit_byte (mb, CEE_LDLOC_3);
3153 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3154 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
3155 mono_mb_emit_icon (mb, sizeof (MonoObject));
3156 mono_mb_emit_byte (mb, CEE_ADD);
3157 mono_mb_emit_byte (mb, CEE_STLOC_1);
3159 /* emit conversion code */
3160 emit_struct_conv (mb, klass, TRUE);
3162 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3164 case MONO_TYPE_ARRAY:
3165 case MONO_TYPE_SZARRAY:
3166 /* fixme: we need conversions here */
3167 mono_mb_emit_byte (mb, CEE_STLOC_3);
3169 case MONO_TYPE_CHAR:
3170 /* fixme: we need conversions here */
3171 mono_mb_emit_byte (mb, CEE_STLOC_3);
3173 case MONO_TYPE_TYPEDBYREF:
3174 case MONO_TYPE_FNPTR:
3176 g_warning ("return type 0x%02x unknown", sig->ret->type);
3177 g_assert_not_reached ();
3181 mono_mb_emit_byte (mb, CEE_STLOC_3);
3184 /* we need to convert byref arguments back and free string arrays */
3185 for (i = 0; i < sig->param_count; i++) {
3186 MonoType *t = sig->params [i];
3188 argnum = i + sig->hasthis;
3191 case MONO_TYPE_STRING:
3192 if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT)) {
3193 mono_mb_emit_ldarg (mb, argnum);
3194 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3195 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3196 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3197 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
3198 mono_mb_emit_byte (mb, CEE_STIND_I);
3200 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3201 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3202 mono_mb_emit_byte (mb, CEE_MONO_FREE);
3205 case MONO_TYPE_CLASS:
3206 case MONO_TYPE_OBJECT:
3207 if (t->data.klass == mono_defaults.stringbuilder_class) {
3208 g_assert (!t->byref);
3209 mono_mb_emit_ldarg (mb, argnum);
3210 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3211 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3212 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
3213 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_SB);
3214 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3215 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3216 mono_mb_emit_byte (mb, CEE_MONO_FREE);
3220 if (!(t->byref || (t->attrs & PARAM_ATTRIBUTE_OUT)))
3223 if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT)) {
3224 /* allocate a new object new object */
3225 mono_mb_emit_ldarg (mb, argnum);
3226 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3227 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
3228 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3229 mono_mb_emit_byte (mb, CEE_STIND_I);
3232 /* dst = *argument */
3233 mono_mb_emit_ldarg (mb, argnum);
3236 mono_mb_emit_byte (mb, CEE_LDIND_I);
3238 mono_mb_emit_byte (mb, CEE_STLOC_1);
3240 mono_mb_emit_byte (mb, CEE_LDLOC_1);
3241 mono_mb_emit_byte (mb, CEE_BRFALSE);
3243 mono_mb_emit_i4 (mb, 0);
3245 mono_mb_emit_byte (mb, CEE_LDLOC_1);
3246 mono_mb_emit_icon (mb, sizeof (MonoObject));
3247 mono_mb_emit_byte (mb, CEE_ADD);
3248 mono_mb_emit_byte (mb, CEE_STLOC_1);
3250 /* src = tmp_locals [i] */
3251 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3252 mono_mb_emit_byte (mb, CEE_STLOC_0);
3254 /* emit valuetype conversion code */
3255 emit_struct_conv (mb, klass, TRUE);
3257 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3259 case MONO_TYPE_VALUETYPE:
3263 klass = t->data.klass;
3264 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3265 klass->blittable || klass->enumtype)
3268 /* dst = argument */
3269 mono_mb_emit_ldarg (mb, argnum);
3270 mono_mb_emit_byte (mb, CEE_STLOC_1);
3272 mono_mb_emit_byte (mb, CEE_LDLOC_1);
3273 mono_mb_emit_byte (mb, CEE_BRFALSE);
3275 mono_mb_emit_i4 (mb, 0);
3277 /* src = tmp_locals [i] */
3278 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3279 mono_mb_emit_byte (mb, CEE_STLOC_0);
3281 /* emit valuetype conversion code */
3282 emit_struct_conv (mb, klass, TRUE);
3284 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3286 case MONO_TYPE_SZARRAY:
3290 klass = mono_class_from_mono_type (t);
3292 if (klass->element_class == mono_defaults.string_class) {
3293 g_assert (tmp_locals [i]);
3295 mono_mb_emit_ldarg (mb, argnum);
3296 mono_mb_emit_byte (mb, CEE_BRFALSE);
3298 mono_mb_emit_i4 (mb, 0);
3300 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3301 mono_mb_emit_ldarg (mb, argnum);
3302 mono_mb_emit_byte (mb, CEE_LDLEN);
3303 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3304 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
3305 mono_mb_emit_byte (mb, MONO_MARSHAL_FREE_ARRAY);
3307 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3315 if (!MONO_TYPE_IS_VOID(sig->ret))
3316 mono_mb_emit_byte (mb, CEE_LDLOC_3);
3318 mono_mb_emit_byte (mb, CEE_RET);
3320 csig = g_memdup (sig, sigsize);
3322 res = mono_mb_create_and_cache (cache, method,
3323 mb, csig, csig->param_count + 16);
3326 for (i = sig->param_count; i >= 0; i--)
3327 g_free (mspecs [i]);
3334 * generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld)
3337 mono_marshal_get_struct_to_ptr (MonoClass *klass)
3339 MonoMethodBuilder *mb;
3340 static MonoMethod *stoptr = NULL;
3343 g_assert (klass != NULL);
3345 if (klass->str_to_ptr)
3346 return klass->str_to_ptr;
3349 stoptr = mono_find_method_by_name (mono_defaults.marshal_class, "StructureToPtr", 3);
3352 mb = mono_mb_new (klass, stoptr->name, MONO_WRAPPER_UNKNOWN);
3354 if (klass->blittable) {
3355 mono_mb_emit_byte (mb, CEE_LDARG_1);
3356 mono_mb_emit_byte (mb, CEE_LDARG_0);
3357 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3358 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
3359 mono_mb_emit_byte (mb, CEE_PREFIX1);
3360 mono_mb_emit_byte (mb, CEE_CPBLK);
3363 /* allocate local 0 (pointer) src_ptr */
3364 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3365 /* allocate local 1 (pointer) dst_ptr */
3366 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3367 /* allocate local 2 (boolean) delete_old */
3368 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
3369 mono_mb_emit_byte (mb, CEE_LDARG_2);
3370 mono_mb_emit_byte (mb, CEE_STLOC_2);
3372 /* initialize src_ptr to point to the start of object data */
3373 mono_mb_emit_byte (mb, CEE_LDARG_0);
3374 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3375 mono_mb_emit_byte (mb, CEE_STLOC_0);
3377 /* initialize dst_ptr */
3378 mono_mb_emit_byte (mb, CEE_LDARG_1);
3379 mono_mb_emit_byte (mb, CEE_STLOC_1);
3381 emit_struct_conv (mb, klass, FALSE);
3384 mono_mb_emit_byte (mb, CEE_RET);
3386 res = mono_mb_create_method (mb, stoptr->signature, 0);
3389 klass->str_to_ptr = res;
3394 * generates IL code for PtrToStructure (IntPtr src, object structure)
3397 mono_marshal_get_ptr_to_struct (MonoClass *klass)
3399 MonoMethodBuilder *mb;
3400 static MonoMethod *ptostr = NULL;
3403 g_assert (klass != NULL);
3405 if (klass->ptr_to_str)
3406 return klass->ptr_to_str;
3409 ptostr = mono_find_method_by_name (mono_defaults.marshal_class, "PtrToStructure", 2);
3412 mb = mono_mb_new (klass, ptostr->name, MONO_WRAPPER_UNKNOWN);
3414 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable) {
3415 mono_mb_emit_byte (mb, CEE_LDARG_1);
3416 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3417 mono_mb_emit_byte (mb, CEE_LDARG_0);
3418 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
3419 mono_mb_emit_byte (mb, CEE_PREFIX1);
3420 mono_mb_emit_byte (mb, CEE_CPBLK);
3423 /* allocate local 0 (pointer) src_ptr */
3424 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3425 /* allocate local 1 (pointer) dst_ptr */
3426 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3428 /* initialize src_ptr to point to the start of object data */
3429 mono_mb_emit_byte (mb, CEE_LDARG_0);
3430 mono_mb_emit_byte (mb, CEE_STLOC_0);
3432 /* initialize dst_ptr */
3433 mono_mb_emit_byte (mb, CEE_LDARG_1);
3434 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3435 mono_mb_emit_byte (mb, CEE_STLOC_1);
3437 emit_struct_conv (mb, klass, TRUE);
3440 mono_mb_emit_byte (mb, CEE_RET);
3442 res = mono_mb_create_method (mb, ptostr->signature, 0);
3445 klass->ptr_to_str = res;
3449 static MonoReflectionType *
3450 type_from_handle (MonoType *handle)
3452 MonoDomain *domain = mono_domain_get ();
3453 MonoClass *klass = mono_class_from_mono_type (handle);
3455 MONO_ARCH_SAVE_REGS;
3457 mono_class_init (klass);
3458 return mono_type_get_object (domain, handle);
3462 * generates IL code for the synchronized wrapper: the generated method
3463 * calls METHOD while locking 'this' or the parent type.
3466 mono_marshal_get_synchronized_wrapper (MonoMethod *method)
3468 static MonoMethodSignature *from_handle_sig = NULL;
3469 static MonoMethod *enter_method, *exit_method;
3470 MonoMethodSignature *sig;
3471 MonoExceptionClause *clause;
3472 MonoMethodHeader *header;
3473 MonoMethodBuilder *mb;
3476 int i, pos, this_local, ret_local;
3480 if (method->wrapper_type == MONO_WRAPPER_SYNCHRONIZED)
3483 cache = method->klass->image->synchronized_cache;
3484 if ((res = mono_marshal_find_in_cache (cache, method)))
3487 sig = method->signature;
3489 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_SYNCHRONIZED);
3492 if (!MONO_TYPE_IS_VOID (sig->ret))
3493 ret_local = mono_mb_add_local (mb, sig->ret);
3496 this_local = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
3498 clause = g_new0 (MonoExceptionClause, 1);
3499 clause->flags = MONO_EXCEPTION_CLAUSE_FINALLY;
3501 if (!enter_method) {
3502 MonoMethodDesc *desc;
3504 desc = mono_method_desc_new ("Monitor:Enter", FALSE);
3505 enter_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
3506 g_assert (enter_method);
3507 mono_method_desc_free (desc);
3508 desc = mono_method_desc_new ("Monitor:Exit", FALSE);
3509 exit_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
3510 g_assert (exit_method);
3511 mono_method_desc_free (desc);
3514 * GetTypeFromHandle isn't called as a managed method because it has
3515 * a funky calling sequence, e.g. ldtoken+GetTypeFromHandle gets
3516 * transformed into something else by the JIT.
3518 from_handle_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
3519 from_handle_sig->params [0] = &mono_defaults.object_class->byval_arg;
3520 from_handle_sig->ret = &mono_defaults.object_class->byval_arg;
3523 /* Push this or the type object */
3524 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3525 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3526 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
3527 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, &method->klass->byval_arg));
3528 mono_mb_emit_native_call (mb, from_handle_sig, type_from_handle);
3531 mono_mb_emit_ldarg (mb, 0);
3532 mono_mb_emit_stloc (mb, this_local);
3534 /* Call Monitor::Enter() */
3535 mono_mb_emit_ldloc (mb, this_local);
3536 mono_mb_emit_managed_call (mb, enter_method, NULL);
3538 clause->try_offset = mb->pos;
3540 /* Call the method */
3542 mono_mb_emit_ldarg (mb, 0);
3543 for (i = 0; i < sig->param_count; i++)
3544 mono_mb_emit_ldarg (mb, i + (sig->hasthis == TRUE));
3545 mono_mb_emit_managed_call (mb, method, method->signature);
3546 if (!MONO_TYPE_IS_VOID (sig->ret))
3547 mono_mb_emit_stloc (mb, ret_local);
3549 mono_mb_emit_byte (mb, CEE_LEAVE);
3551 mono_mb_emit_i4 (mb, 0);
3553 clause->try_len = mb->pos - clause->try_offset;
3554 clause->handler_offset = mb->pos;
3556 /* Call Monitor::Exit() */
3557 mono_mb_emit_ldloc (mb, this_local);
3558 // mono_mb_emit_native_call (mb, exit_sig, mono_monitor_exit);
3559 mono_mb_emit_managed_call (mb, exit_method, NULL);
3560 mono_mb_emit_byte (mb, CEE_ENDFINALLY);
3562 clause->handler_len = mb->pos - clause->handler_offset;
3564 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3565 if (!MONO_TYPE_IS_VOID (sig->ret))
3566 mono_mb_emit_ldloc (mb, ret_local);
3567 mono_mb_emit_byte (mb, CEE_RET);
3569 res = mono_mb_create_and_cache (cache, method,
3570 mb, sig, sig->param_count + 16);
3573 header = ((MonoMethodNormal *)res)->header;
3574 header->num_clauses = 1;
3575 header->clauses = clause;
3580 /* FIXME: on win32 we should probably use GlobalAlloc(). */
3582 mono_marshal_alloc (gpointer size)
3584 MONO_ARCH_SAVE_REGS;
3586 return g_try_malloc ((gulong)size);
3590 mono_marshal_free (gpointer ptr)
3592 MONO_ARCH_SAVE_REGS;
3598 mono_marshal_free_array (gpointer *ptr, int size)
3605 for (i = 0; i < size; i++)
3611 mono_marshal_realloc (gpointer ptr, gpointer size)
3613 MONO_ARCH_SAVE_REGS;
3615 return g_try_realloc (ptr, (gulong)size);
3619 mono_marshal_string_array (MonoArray *array)
3627 len = mono_array_length (array);
3629 result = g_malloc (sizeof (char *) * (len + 1));
3630 for (i = 0; i < len; ++i) {
3631 MonoString *s = (MonoString *)mono_array_get (array, gpointer, i);
3632 result [i] = s ? mono_string_to_utf8 (s): NULL;
3634 /* null terminate the array */
3641 ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArray *src, gint32 start_index,
3642 gpointer dest, gint32 length)
3647 MONO_ARCH_SAVE_REGS;
3649 MONO_CHECK_ARG_NULL (src);
3650 MONO_CHECK_ARG_NULL (dest);
3652 g_assert (src->obj.vtable->klass->rank == 1);
3653 g_assert (start_index >= 0);
3654 g_assert (length >= 0);
3655 g_assert (start_index + length <= mono_array_length (src));
3657 element_size = mono_array_element_size (src->obj.vtable->klass);
3659 source_addr = mono_array_addr_with_size (src, element_size, start_index);
3661 memcpy (dest, source_addr, length * element_size);
3665 ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer src, gint32 start_index,
3666 MonoArray *dest, gint32 length)
3671 MONO_ARCH_SAVE_REGS;
3673 MONO_CHECK_ARG_NULL (src);
3674 MONO_CHECK_ARG_NULL (dest);
3676 g_assert (dest->obj.vtable->klass->rank == 1);
3677 g_assert (start_index >= 0);
3678 g_assert (length >= 0);
3679 g_assert (start_index + length <= mono_array_length (dest));
3681 element_size = mono_array_element_size (dest->obj.vtable->klass);
3683 dest_addr = mono_array_addr_with_size (dest, element_size, start_index);
3685 memcpy (dest_addr, src, length * element_size);
3689 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr, gint32 offset)
3693 MONO_ARCH_SAVE_REGS;
3695 return *(gpointer*)(p + offset);
3699 ves_icall_System_Runtime_InteropServices_Marshal_ReadByte (gpointer ptr, gint32 offset)
3703 MONO_ARCH_SAVE_REGS;
3705 return *(unsigned char*)(p + offset);
3709 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt16 (gpointer ptr, gint32 offset)
3713 MONO_ARCH_SAVE_REGS;
3715 return *(gint16*)(p + offset);
3719 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt32 (gpointer ptr, gint32 offset)
3723 MONO_ARCH_SAVE_REGS;
3725 return *(gint32*)(p + offset);
3729 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt64 (gpointer ptr, gint32 offset)
3733 MONO_ARCH_SAVE_REGS;
3735 return *(gint64*)(p + offset);
3739 ves_icall_System_Runtime_InteropServices_Marshal_WriteByte (gpointer ptr, gint32 offset, unsigned char val)
3743 MONO_ARCH_SAVE_REGS;
3745 *(unsigned char*)(p + offset) = val;
3749 ves_icall_System_Runtime_InteropServices_Marshal_WriteIntPtr (gpointer ptr, gint32 offset, gpointer val)
3753 MONO_ARCH_SAVE_REGS;
3755 *(gpointer*)(p + offset) = val;
3759 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt16 (gpointer ptr, gint32 offset, gint16 val)
3763 MONO_ARCH_SAVE_REGS;
3765 *(gint16*)(p + offset) = val;
3769 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt32 (gpointer ptr, gint32 offset, gint32 val)
3773 MONO_ARCH_SAVE_REGS;
3775 *(gint32*)(p + offset) = val;
3779 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt64 (gpointer ptr, gint32 offset, gint64 val)
3783 MONO_ARCH_SAVE_REGS;
3785 *(gint64*)(p + offset) = val;
3789 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (char *ptr)
3791 MONO_ARCH_SAVE_REGS;
3793 return mono_string_new (mono_domain_get (), ptr);
3797 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len (char *ptr, gint32 len)
3799 MONO_ARCH_SAVE_REGS;
3801 return mono_string_new_len (mono_domain_get (), ptr, len);
3805 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni (guint16 *ptr)
3807 MonoDomain *domain = mono_domain_get ();
3811 MONO_ARCH_SAVE_REGS;
3816 return mono_string_new_utf16 (domain, ptr, len);
3820 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len (guint16 *ptr, gint32 len)
3822 MonoDomain *domain = mono_domain_get ();
3824 MONO_ARCH_SAVE_REGS;
3826 return mono_string_new_utf16 (domain, ptr, len);
3830 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR (gpointer ptr)
3832 MONO_ARCH_SAVE_REGS;
3834 g_warning ("PtrToStringBSTR not implemented");
3835 g_assert_not_reached ();
3841 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
3843 MONO_ARCH_SAVE_REGS;
3845 return (GetLastError ());
3849 ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype)
3853 MONO_ARCH_SAVE_REGS;
3855 MONO_CHECK_ARG_NULL (rtype);
3857 klass = mono_class_from_mono_type (rtype->type);
3859 return mono_class_native_size (klass, NULL);
3863 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old)
3868 MONO_ARCH_SAVE_REGS;
3870 MONO_CHECK_ARG_NULL (obj);
3871 MONO_CHECK_ARG_NULL (dst);
3873 method = mono_marshal_get_struct_to_ptr (obj->vtable->klass);
3877 pa [2] = &delete_old;
3879 mono_runtime_invoke (method, NULL, pa, NULL);
3883 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, MonoObject *dst)
3888 MONO_ARCH_SAVE_REGS;
3890 MONO_CHECK_ARG_NULL (src);
3891 MONO_CHECK_ARG_NULL (dst);
3893 method = mono_marshal_get_ptr_to_struct (dst->vtable->klass);
3898 mono_runtime_invoke (method, NULL, pa, NULL);
3902 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer src, MonoReflectionType *type)
3904 MonoDomain *domain = mono_domain_get ();
3907 MONO_ARCH_SAVE_REGS;
3909 MONO_CHECK_ARG_NULL (src);
3910 MONO_CHECK_ARG_NULL (type);
3912 res = mono_object_new (domain, mono_class_from_mono_type (type->type));
3914 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (src, res);
3920 ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *type, MonoString *field_name)
3922 MonoMarshalType *info;
3925 int i, match_index = -1;
3927 MONO_ARCH_SAVE_REGS;
3929 MONO_CHECK_ARG_NULL (type);
3930 MONO_CHECK_ARG_NULL (field_name);
3932 fname = mono_string_to_utf8 (field_name);
3933 klass = mono_class_from_mono_type (type->type);
3935 while(klass && match_index == -1) {
3936 for (i = 0; i < klass->field.count; ++i) {
3937 if (*fname == *klass->fields [i].name && strcmp (fname, klass->fields [i].name) == 0) {
3943 if(match_index == -1)
3944 klass = klass->parent;
3949 if(match_index == -1) {
3953 /* Get back original class instance */
3954 klass = mono_class_from_mono_type (type->type);
3956 tmp = g_strdup_printf ("Field passed in is not a marshaled member of the type %s", klass->name);
3957 exc = mono_get_exception_argument ("fieldName", tmp);
3960 mono_raise_exception ((MonoException*)exc);
3963 info = mono_marshal_load_type_info (klass);
3964 return info->fields [match_index].offset;
3968 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString *string)
3970 MONO_ARCH_SAVE_REGS;
3972 return mono_string_to_utf8 (string);
3976 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni (MonoString *string)
3978 MONO_ARCH_SAVE_REGS;
3980 return g_memdup (mono_string_chars (string), mono_string_length (string)*2);
3984 mono_struct_delete_old (MonoClass *klass, char *ptr)
3986 MonoMarshalType *info;
3989 info = mono_marshal_load_type_info (klass);
3991 for (i = 0; i < info->num_fields; i++) {
3992 MonoMarshalNative ntype;
3993 MonoMarshalConv conv;
3994 MonoType *ftype = info->fields [i].field->type;
3997 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
4000 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE,
4001 klass->unicode, &conv);
4003 cpos = ptr + info->fields [i].offset;
4006 case MONO_MARSHAL_CONV_NONE:
4007 if (MONO_TYPE_ISSTRUCT (ftype)) {
4008 mono_struct_delete_old (ftype->data.klass, cpos);
4012 case MONO_MARSHAL_CONV_STR_LPWSTR:
4013 case MONO_MARSHAL_CONV_STR_LPSTR:
4014 case MONO_MARSHAL_CONV_STR_LPTSTR:
4015 case MONO_MARSHAL_CONV_STR_BSTR:
4016 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
4017 case MONO_MARSHAL_CONV_STR_TBSTR:
4018 g_free (*(gpointer *)cpos);
4027 ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure (gpointer src, MonoReflectionType *type)
4031 MONO_ARCH_SAVE_REGS;
4033 MONO_CHECK_ARG_NULL (src);
4034 MONO_CHECK_ARG_NULL (type);
4036 klass = mono_class_from_mono_type (type->type);
4038 mono_struct_delete_old (klass, (char *)src);
4042 mono_marshal_load_type_info (MonoClass* klass)
4044 int i, j, count = 0, native_size = 0;
4045 MonoMarshalType *info;
4048 g_assert (klass != NULL);
4050 if (klass->marshal_info)
4051 return klass->marshal_info;
4054 mono_class_init (klass);
4056 for (i = 0; i < klass->field.count; ++i) {
4057 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
4062 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
4064 klass->marshal_info = info = g_malloc0 (sizeof (MonoMarshalType) + sizeof (MonoMarshalField) * count);
4065 info->num_fields = count;
4067 /* Try to find a size for this type in metadata */
4068 mono_metadata_packing_from_typedef (klass->image, klass->type_token, NULL, &native_size);
4070 if (klass->parent) {
4071 int parent_size = mono_class_native_size (klass->parent, NULL);
4073 /* Add parent size to real size */
4074 native_size += parent_size;
4075 info->native_size = parent_size;
4078 for (j = i = 0; i < klass->field.count; ++i) {
4081 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
4084 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL)
4085 mono_metadata_field_info (klass->image, klass->field.first + i,
4086 NULL, NULL, &info->fields [j].mspec);
4088 info->fields [j].field = &klass->fields [i];
4090 if ((klass->field.count == 1) && (klass->instance_size == sizeof (MonoObject)) &&
4091 (strcmp (klass->fields [i].name, "$PRIVATE$") == 0)) {
4092 /* This field is a hack inserted by MCS to empty structures */
4097 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
4098 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
4099 size = mono_marshal_type_size (klass->fields [i].type, info->fields [j].mspec,
4100 &align, TRUE, klass->unicode);
4101 align = klass->packing_size ? MIN (klass->packing_size, align): align;
4102 info->fields [j].offset = info->native_size;
4103 info->fields [j].offset += align - 1;
4104 info->fields [j].offset &= ~(align - 1);
4105 info->native_size = info->fields [j].offset + size;
4107 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
4109 info->fields [j].offset = klass->fields [i].offset - sizeof (MonoObject);
4110 info->native_size = klass->instance_size - sizeof (MonoObject);
4116 if(layout != TYPE_ATTRIBUTE_AUTO_LAYOUT) {
4117 info->native_size = MAX (native_size, info->native_size);
4120 if (info->native_size & (klass->min_align - 1)) {
4121 info->native_size += klass->min_align - 1;
4122 info->native_size &= ~(klass->min_align - 1);
4125 return klass->marshal_info;
4129 * mono_class_native_size:
4132 * Returns: the native size of an object instance (when marshaled
4133 * to unmanaged code)
4136 mono_class_native_size (MonoClass *klass, guint32 *align)
4139 if (!klass->marshal_info)
4140 mono_marshal_load_type_info (klass);
4143 *align = klass->min_align;
4145 return klass->marshal_info->native_size;
4149 * mono_type_native_stack_size:
4150 * @t: the type to return the size it uses on the stack
4152 * Returns: the number of bytes required to hold an instance of this
4153 * type on the native stack
4156 mono_type_native_stack_size (MonoType *t, gint *align)
4160 g_assert (t != NULL);
4171 case MONO_TYPE_BOOLEAN:
4172 case MONO_TYPE_CHAR:
4181 case MONO_TYPE_STRING:
4182 case MONO_TYPE_OBJECT:
4183 case MONO_TYPE_CLASS:
4184 case MONO_TYPE_SZARRAY:
4186 case MONO_TYPE_FNPTR:
4187 case MONO_TYPE_ARRAY:
4188 case MONO_TYPE_TYPEDBYREF:
4199 case MONO_TYPE_VALUETYPE: {
4202 if (t->data.klass->enumtype)
4203 return mono_type_native_stack_size (t->data.klass->enum_basetype, align);
4205 size = mono_class_native_size (t->data.klass, align);
4206 *align = *align + 3;
4216 g_error ("type 0x%02x unknown", t->type);
4222 mono_marshal_type_size (MonoType *type, MonoMarshalSpec *mspec, gint32 *align,
4223 gboolean as_field, gboolean unicode)
4225 MonoMarshalNative native_type = mono_type_to_unmanaged (type, mspec, as_field, unicode, NULL);
4228 switch (native_type) {
4229 case MONO_NATIVE_BOOLEAN:
4232 case MONO_NATIVE_I1:
4233 case MONO_NATIVE_U1:
4236 case MONO_NATIVE_I2:
4237 case MONO_NATIVE_U2:
4240 case MONO_NATIVE_I4:
4241 case MONO_NATIVE_U4:
4242 case MONO_NATIVE_ERROR:
4245 case MONO_NATIVE_I8:
4246 case MONO_NATIVE_U8:
4249 case MONO_NATIVE_R4:
4252 case MONO_NATIVE_R8:
4255 case MONO_NATIVE_INT:
4256 case MONO_NATIVE_UINT:
4257 case MONO_NATIVE_LPSTR:
4258 case MONO_NATIVE_LPWSTR:
4259 case MONO_NATIVE_LPTSTR:
4260 case MONO_NATIVE_BSTR:
4261 case MONO_NATIVE_ANSIBSTR:
4262 case MONO_NATIVE_TBSTR:
4263 case MONO_NATIVE_LPARRAY:
4264 case MONO_NATIVE_SAFEARRAY:
4265 case MONO_NATIVE_IUNKNOWN:
4266 case MONO_NATIVE_IDISPATCH:
4267 case MONO_NATIVE_INTERFACE:
4268 case MONO_NATIVE_ASANY:
4269 case MONO_NATIVE_VARIANTBOOL:
4270 case MONO_NATIVE_FUNC:
4271 case MONO_NATIVE_LPSTRUCT:
4273 return sizeof (gpointer);
4274 case MONO_NATIVE_STRUCT:
4275 klass = mono_class_from_mono_type (type);
4276 return mono_class_native_size (klass, align);
4277 case MONO_NATIVE_BYVALTSTR: {
4278 int esize = unicode ? 2: 1;
4281 return mspec->data.array_data.num_elem * esize;
4283 case MONO_NATIVE_BYVALARRAY: {
4285 klass = mono_class_from_mono_type (type);
4286 esize = mono_class_native_size (klass->element_class, align);
4288 return mspec->data.array_data.num_elem * esize;
4290 case MONO_NATIVE_CUSTOM:
4291 g_assert_not_reached ();
4293 case MONO_NATIVE_CURRENCY:
4294 case MONO_NATIVE_VBBYREFSTR:
4296 g_error ("native type %02x not implemented", native_type);
4299 g_assert_not_reached ();