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 = {
80 mono_delegate_to_ftnptr (MonoDelegate *delegate)
82 MonoMethod *method, *wrapper, *invoke;
83 MonoMarshalSpec **mspecs;
90 if (delegate->delegate_trampoline)
91 return delegate->delegate_trampoline;
93 klass = ((MonoObject *)delegate)->vtable->klass;
94 g_assert (klass->delegate);
97 method = delegate->method_info->method;
98 invoke = mono_find_method_by_name (klass, "Invoke", method->signature->param_count);
100 mspecs = g_new (MonoMarshalSpec*, invoke->signature->param_count + 1);
101 mono_method_get_marshal_info (invoke, mspecs);
103 wrapper = mono_marshal_get_managed_wrapper (method, delegate->target, mspecs);
105 for (i = invoke->signature->param_count; i >= 0; i--)
109 delegate->delegate_trampoline = mono_compile_method (wrapper);
111 return delegate->delegate_trampoline;
115 mono_array_to_savearray (MonoArray *array)
120 g_assert_not_reached ();
125 mono_array_to_lparray (MonoArray *array)
130 /* fixme: maybe we need to make a copy */
131 return array->vector;
135 mono_string_utf8_to_builder (MonoStringBuilder *sb, char *text)
137 GError *error = NULL;
147 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
149 if (items_written > sb->capacity)
150 items_written = sb->capacity;
153 memcpy (sb->chars->vector, ut, items_written * 2);
154 sb->length = items_written;
156 g_error_free (error);
162 mono_string_builder_to_utf8 (MonoStringBuilder *sb)
169 res = g_malloc (sb->capacity + 1);
171 /* fixme: copy the content of the string builder? */
178 mono_string_to_ansibstr (MonoString *string_obj)
180 g_error ("implement me");
185 mono_string_to_bstr (MonoString *string_obj)
187 g_error ("implement me");
192 mono_string_to_byvalstr (gpointer dst, MonoString *src, int size)
197 g_assert (dst != NULL);
200 memset (dst, 0, size);
205 s = mono_string_to_utf8 (src);
206 len = MIN (size, strlen (s));
207 memcpy (dst, s, len);
210 *((char *)dst + size - 1) = 0;
214 mono_string_to_byvalwstr (gpointer dst, MonoString *src, int size)
218 g_assert (dst != NULL);
222 memset (dst, 0, size);
226 len = MIN (size, (mono_string_length (src) * 2));
227 memcpy (dst, mono_string_chars (src), len);
229 *((char *)dst + size - 1) = 0;
230 *((char *)dst + size - 2) = 0;
234 mono_mb_free (MonoMethodBuilder *mb)
236 g_list_free (mb->locals_list);
241 mono_mb_new (MonoClass *klass, const char *name, MonoWrapperType type)
243 MonoMethodBuilder *mb;
246 g_assert (klass != NULL);
247 g_assert (name != NULL);
249 mb = g_new0 (MonoMethodBuilder, 1);
251 mb->method = m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
254 m->name = g_strdup (name);
256 m->inline_count = -1;
257 m->wrapper_type = type;
260 mb->code = g_malloc (mb->code_size);
266 mono_mb_add_local (MonoMethodBuilder *mb, MonoType *type)
268 int res = mb->locals;
270 g_assert (mb != NULL);
271 g_assert (type != NULL);
273 mb->locals_list = g_list_append (mb->locals_list, type);
280 mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack)
282 MonoMethodHeader *header;
286 g_assert (mb != NULL);
288 ((MonoMethodNormal *)mb->method)->header = header = (MonoMethodHeader *)
289 g_malloc0 (sizeof (MonoMethodHeader) + mb->locals * sizeof (MonoType *));
294 header->max_stack = max_stack;
296 for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
297 header->locals [i] = (MonoType *)l->data;
300 mb->method->signature = signature;
301 header->code = mb->code;
302 header->code_size = mb->pos;
303 header->num_locals = mb->locals;
305 #ifdef DEBUG_RUNTIME_CODE
306 printf ("RUNTIME CODE FOR %s\n", mono_method_full_name (mb->method, TRUE));
307 printf ("%s\n", mono_disasm_code (&marshal_dh, mb->method, mb->code, mb->code + mb->pos));
314 mono_mb_add_data (MonoMethodBuilder *mb, gpointer data)
316 MonoMethodWrapper *mw;
318 g_assert (mb != NULL);
320 mw = (MonoMethodWrapper *)mb->method;
322 mw->data = g_list_append (mw->data, data);
324 return g_list_length (mw->data);
328 mono_mb_patch_addr (MonoMethodBuilder *mb, int pos, int value)
330 mb->code [pos] = value & 0xff;
331 mb->code [pos + 1] = (value >> 8) & 0xff;
332 mb->code [pos + 2] = (value >> 16) & 0xff;
333 mb->code [pos + 3] = (value >> 24) & 0xff;
337 mono_mb_patch_addr_s (MonoMethodBuilder *mb, int pos, gint8 value)
339 *((gint8 *)(&mb->code [pos])) = value;
343 mono_mb_emit_byte (MonoMethodBuilder *mb, guint8 op)
345 if (mb->pos >= mb->code_size) {
347 mb->code = g_realloc (mb->code, mb->code_size);
350 mb->code [mb->pos++] = op;
354 mono_mb_emit_ldflda (MonoMethodBuilder *mb, gint32 offset)
356 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
357 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
360 mono_mb_emit_icon (mb, offset);
361 mono_mb_emit_byte (mb, CEE_ADD);
366 mono_mb_emit_proxy_check (MonoMethodBuilder *mb, int branch_code)
369 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoObject, vtable));
370 mono_mb_emit_byte (mb, CEE_LDIND_I);
371 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoVTable, klass));
372 mono_mb_emit_byte (mb, CEE_ADD);
373 mono_mb_emit_byte (mb, CEE_LDIND_I);
374 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
375 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
376 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_defaults.transparent_proxy_class));
377 mono_mb_emit_byte (mb, branch_code);
379 mono_mb_emit_i4 (mb, 0);
384 mono_mb_emit_i4 (MonoMethodBuilder *mb, gint32 data)
386 if ((mb->pos + 4) >= mb->code_size) {
388 mb->code = g_realloc (mb->code, mb->code_size);
391 mono_mb_patch_addr (mb, mb->pos, data);
396 mono_mb_emit_i2 (MonoMethodBuilder *mb, gint16 data)
398 if ((mb->pos + 2) >= mb->code_size) {
400 mb->code = g_realloc (mb->code, mb->code_size);
403 mb->code [mb->pos] = data & 0xff;
404 mb->code [mb->pos + 1] = (data >> 8) & 0xff;
409 mono_mb_emit_ldstr (MonoMethodBuilder *mb, char *str)
411 mono_mb_emit_byte (mb, CEE_LDSTR);
412 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, str));
417 mono_mb_emit_ldarg (MonoMethodBuilder *mb, guint argnum)
420 mono_mb_emit_byte (mb, CEE_LDARG_0 + argnum);
421 } else if (argnum < 256) {
422 mono_mb_emit_byte (mb, CEE_LDARG_S);
423 mono_mb_emit_byte (mb, argnum);
425 mono_mb_emit_byte (mb, CEE_PREFIX1);
426 mono_mb_emit_byte (mb, CEE_LDARG);
427 mono_mb_emit_i2 (mb, argnum);
432 mono_mb_emit_ldarg_addr (MonoMethodBuilder *mb, guint argnum)
435 mono_mb_emit_byte (mb, CEE_LDARGA_S);
436 mono_mb_emit_byte (mb, argnum);
438 mono_mb_emit_byte (mb, CEE_PREFIX1);
439 mono_mb_emit_byte (mb, CEE_LDARGA);
440 mono_mb_emit_i2 (mb, argnum);
445 mono_mb_emit_ldloc_addr (MonoMethodBuilder *mb, guint locnum)
448 mono_mb_emit_byte (mb, CEE_LDLOCA_S);
449 mono_mb_emit_byte (mb, locnum);
451 mono_mb_emit_byte (mb, CEE_PREFIX1);
452 mono_mb_emit_byte (mb, CEE_LDLOCA);
453 mono_mb_emit_i2 (mb, locnum);
458 mono_mb_emit_ldloc (MonoMethodBuilder *mb, guint num)
461 mono_mb_emit_byte (mb, CEE_LDLOC_0 + num);
462 } else if (num < 256) {
463 mono_mb_emit_byte (mb, CEE_LDLOC_S);
464 mono_mb_emit_byte (mb, num);
466 mono_mb_emit_byte (mb, CEE_PREFIX1);
467 mono_mb_emit_byte (mb, CEE_LDLOC);
468 mono_mb_emit_i2 (mb, num);
473 mono_mb_emit_stloc (MonoMethodBuilder *mb, guint num)
476 mono_mb_emit_byte (mb, CEE_STLOC_0 + num);
477 } else if (num < 256) {
478 mono_mb_emit_byte (mb, CEE_STLOC_S);
479 mono_mb_emit_byte (mb, num);
481 mono_mb_emit_byte (mb, CEE_PREFIX1);
482 mono_mb_emit_byte (mb, CEE_STLOC);
483 mono_mb_emit_i2 (mb, num);
488 mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value)
490 if (value >= -1 && value < 8) {
491 mono_mb_emit_byte (mb, CEE_LDC_I4_0 + value);
492 } else if (value >= -128 && value <= 127) {
493 mono_mb_emit_byte (mb, CEE_LDC_I4_S);
494 mono_mb_emit_byte (mb, value);
496 mono_mb_emit_byte (mb, CEE_LDC_I4);
497 mono_mb_emit_i4 (mb, value);
502 mono_mb_emit_managed_call (MonoMethodBuilder *mb, MonoMethod *method, MonoMethodSignature *opt_sig)
505 opt_sig = method->signature;
506 mono_mb_emit_byte (mb, CEE_PREFIX1);
507 mono_mb_emit_byte (mb, CEE_LDFTN);
508 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
509 mono_mb_emit_byte (mb, CEE_CALLI);
510 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, opt_sig));
514 mono_mb_emit_native_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, gpointer func)
516 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
517 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
518 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, func));
519 mono_mb_emit_byte (mb, CEE_CALLI);
520 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
524 mono_mb_emit_exception (MonoMethodBuilder *mb)
526 /* fixme: we need a better way to throw exception,
527 * supporting several exception types and messages */
528 static MonoMethod *missing_method_ctor = NULL;
530 if (!missing_method_ctor) {
531 MonoClass *mme = mono_class_from_name (mono_defaults.corlib, "System", "MissingMethodException");
533 mono_class_init (mme);
534 for (i = 0; i < mme->method.count; ++i) {
535 if (strcmp (mme->methods [i]->name, ".ctor") == 0 && mme->methods [i]->signature->param_count == 0) {
536 missing_method_ctor = mme->methods [i];
541 mono_mb_emit_byte (mb, CEE_NEWOBJ);
542 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, missing_method_ctor));
543 mono_mb_emit_byte (mb, CEE_THROW);
548 mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint16 local, gint32 incr)
550 mono_mb_emit_ldloc (mb, local);
551 mono_mb_emit_icon (mb, incr);
552 mono_mb_emit_byte (mb, CEE_ADD);
553 mono_mb_emit_stloc (mb, local);
557 emit_ptr_to_str_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv,
558 int usize, int msize, MonoMarshalSpec *mspec)
561 case MONO_MARSHAL_CONV_BOOL_I4:
562 mono_mb_emit_byte (mb, CEE_LDLOC_0);
563 mono_mb_emit_byte (mb, CEE_LDIND_I);
564 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
565 mono_mb_emit_byte (mb, 5);
566 mono_mb_emit_byte (mb, CEE_LDLOC_1);
567 mono_mb_emit_byte (mb, CEE_LDC_I4_1);
568 mono_mb_emit_byte (mb, CEE_STIND_I1);
569 mono_mb_emit_byte (mb, CEE_BR_S);
570 mono_mb_emit_byte (mb, 3);
571 mono_mb_emit_byte (mb, CEE_LDLOC_1);
572 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
573 mono_mb_emit_byte (mb, CEE_STIND_I1);
575 case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
579 if (type->type == MONO_TYPE_SZARRAY) {
580 eclass = type->data.klass;
582 g_assert_not_reached ();
585 if (eclass->valuetype)
586 esize = mono_class_instance_size (eclass) - sizeof (MonoObject);
588 esize = sizeof (gpointer);
590 /* create a new array */
591 mono_mb_emit_byte (mb, CEE_LDLOC_1);
592 mono_mb_emit_icon (mb, mspec->data.array_data.num_elem);
593 mono_mb_emit_byte (mb, CEE_NEWARR);
594 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eclass));
595 mono_mb_emit_byte (mb, CEE_STIND_I);
597 /* copy the elements */
598 mono_mb_emit_byte (mb, CEE_LDLOC_1);
599 mono_mb_emit_byte (mb, CEE_LDIND_I);
600 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
601 mono_mb_emit_byte (mb, CEE_ADD);
602 mono_mb_emit_byte (mb, CEE_LDLOC_0);
603 mono_mb_emit_icon (mb, mspec->data.array_data.num_elem * esize);
604 mono_mb_emit_byte (mb, CEE_PREFIX1);
605 mono_mb_emit_byte (mb, CEE_CPBLK);
609 case MONO_MARSHAL_CONV_STR_BYVALSTR:
610 mono_mb_emit_byte (mb, CEE_LDLOC_1);
611 mono_mb_emit_byte (mb, CEE_LDLOC_0);
612 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
613 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
614 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
615 mono_mb_emit_byte (mb, CEE_STIND_I);
617 case MONO_MARSHAL_CONV_STR_LPTSTR:
618 case MONO_MARSHAL_CONV_STR_LPSTR:
619 mono_mb_emit_byte (mb, CEE_LDLOC_1);
620 mono_mb_emit_byte (mb, CEE_LDLOC_0);
621 mono_mb_emit_byte (mb, CEE_LDIND_I);
622 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
623 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
624 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
625 mono_mb_emit_byte (mb, CEE_STIND_I);
627 case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
628 MonoClass *klass = mono_class_from_mono_type (type);
629 int src_var, dst_var;
631 src_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
632 dst_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
634 /* *dst = new object */
635 mono_mb_emit_byte (mb, CEE_LDLOC_1);
636 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
637 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
638 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
639 mono_mb_emit_byte (mb, CEE_STIND_I);
641 /* save the old src pointer */
642 mono_mb_emit_byte (mb, CEE_LDLOC_0);
643 mono_mb_emit_stloc (mb, src_var);
644 /* save the old dst pointer */
645 mono_mb_emit_byte (mb, CEE_LDLOC_1);
646 mono_mb_emit_stloc (mb, dst_var);
648 /* dst = pointer to newly created object data */
649 mono_mb_emit_byte (mb, CEE_LDLOC_1);
650 mono_mb_emit_byte (mb, CEE_LDIND_I);
651 mono_mb_emit_icon (mb, sizeof (MonoObject));
652 mono_mb_emit_byte (mb, CEE_ADD);
653 mono_mb_emit_byte (mb, CEE_STLOC_1);
655 emit_struct_conv (mb, klass, TRUE);
657 /* restore the old src pointer */
658 mono_mb_emit_ldloc (mb, src_var);
659 mono_mb_emit_byte (mb, CEE_STLOC_0);
660 /* restore the old dst pointer */
661 mono_mb_emit_ldloc (mb, dst_var);
662 mono_mb_emit_byte (mb, CEE_STLOC_1);
665 case MONO_MARSHAL_CONV_DEL_FTN: {
666 // fixme: we never convert functions back to delegates, dont
667 // know if thats the correct behaviour
670 case MONO_MARSHAL_CONV_STR_LPWSTR:
671 case MONO_MARSHAL_CONV_STR_BSTR:
672 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
673 case MONO_MARSHAL_CONV_STR_TBSTR:
674 case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
675 case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
676 case MONO_MARSHAL_CONV_STR_BYVALWSTR:
677 case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
679 g_warning ("marshaling conversion %d not implemented", conv);
680 g_assert_not_reached ();
685 emit_str_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, int usize, int msize,
686 MonoMarshalSpec *mspec)
691 case MONO_MARSHAL_CONV_BOOL_I4:
692 mono_mb_emit_byte (mb, CEE_LDLOC_1);
693 mono_mb_emit_byte (mb, CEE_LDLOC_0);
694 mono_mb_emit_byte (mb, CEE_LDIND_U1);
695 mono_mb_emit_byte (mb, CEE_STIND_I4);
697 case MONO_MARSHAL_CONV_STR_LPWSTR:
698 case MONO_MARSHAL_CONV_STR_LPSTR:
699 case MONO_MARSHAL_CONV_STR_LPTSTR:
700 case MONO_MARSHAL_CONV_STR_BSTR:
701 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
702 case MONO_MARSHAL_CONV_STR_TBSTR:
703 /* free space if free == true */
704 mono_mb_emit_byte (mb, CEE_LDLOC_2);
705 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
706 mono_mb_emit_byte (mb, 4);
707 mono_mb_emit_byte (mb, CEE_LDLOC_1);
708 mono_mb_emit_byte (mb, CEE_LDIND_I);
709 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
710 mono_mb_emit_byte (mb, CEE_MONO_FREE);
712 mono_mb_emit_byte (mb, CEE_LDLOC_1);
713 mono_mb_emit_byte (mb, CEE_LDLOC_0);
714 mono_mb_emit_byte (mb, CEE_LDIND_I);
715 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
716 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
717 mono_mb_emit_byte (mb, conv);
718 mono_mb_emit_byte (mb, CEE_STIND_I);
720 case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
721 case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
722 case MONO_MARSHAL_CONV_DEL_FTN:
723 mono_mb_emit_byte (mb, CEE_LDLOC_1);
724 mono_mb_emit_byte (mb, CEE_LDLOC_0);
725 mono_mb_emit_byte (mb, CEE_LDIND_I);
726 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
727 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
728 mono_mb_emit_byte (mb, conv);
729 mono_mb_emit_byte (mb, CEE_STIND_I);
731 case MONO_MARSHAL_CONV_STR_BYVALSTR:
732 case MONO_MARSHAL_CONV_STR_BYVALWSTR: {
736 mono_mb_emit_byte (mb, CEE_LDLOC_1); /* dst */
737 mono_mb_emit_byte (mb, CEE_LDLOC_0);
738 mono_mb_emit_byte (mb, CEE_LDIND_I); /* src String */
739 mono_mb_emit_icon (mb, usize);
740 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
741 mono_mb_emit_byte (mb, CEE_MONO_PROC3);
742 mono_mb_emit_byte (mb, conv);
745 case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
749 if (type->type == MONO_TYPE_SZARRAY) {
750 eclass = type->data.klass;
752 g_assert_not_reached ();
755 if (eclass->valuetype)
756 esize = mono_class_native_size (eclass, NULL);
758 esize = sizeof (gpointer);
763 mono_mb_emit_byte (mb, CEE_LDLOC_0);
764 mono_mb_emit_byte (mb, CEE_LDIND_I);
765 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
767 mono_mb_emit_byte (mb, 0);
769 mono_mb_emit_byte (mb, CEE_LDLOC_1);
770 mono_mb_emit_byte (mb, CEE_LDLOC_0);
771 mono_mb_emit_byte (mb, CEE_LDIND_I);
772 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
773 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
774 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
775 mono_mb_emit_byte (mb, CEE_ADD);
776 mono_mb_emit_icon (mb, mspec->data.array_data.num_elem * esize);
777 mono_mb_emit_byte (mb, CEE_PREFIX1);
778 mono_mb_emit_byte (mb, CEE_CPBLK);
779 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
782 case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
783 int src_var, dst_var;
785 src_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
786 dst_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
788 mono_mb_emit_byte (mb, CEE_LDLOC_0);
789 mono_mb_emit_byte (mb, CEE_LDIND_I);
790 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
792 mono_mb_emit_byte (mb, 0);
794 /* save the old src pointer */
795 mono_mb_emit_byte (mb, CEE_LDLOC_0);
796 mono_mb_emit_stloc (mb, src_var);
797 /* save the old dst pointer */
798 mono_mb_emit_byte (mb, CEE_LDLOC_1);
799 mono_mb_emit_stloc (mb, dst_var);
801 /* src = pointer to object data */
802 mono_mb_emit_byte (mb, CEE_LDLOC_0);
803 mono_mb_emit_byte (mb, CEE_LDIND_I);
804 mono_mb_emit_icon (mb, sizeof (MonoObject));
805 mono_mb_emit_byte (mb, CEE_ADD);
806 mono_mb_emit_byte (mb, CEE_STLOC_0);
808 emit_struct_conv (mb, mono_class_from_mono_type (type), FALSE);
810 /* restore the old src pointer */
811 mono_mb_emit_ldloc (mb, src_var);
812 mono_mb_emit_byte (mb, CEE_STLOC_0);
813 /* restore the old dst pointer */
814 mono_mb_emit_ldloc (mb, dst_var);
815 mono_mb_emit_byte (mb, CEE_STLOC_1);
817 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
820 case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
822 g_warning ("marshalling conversion %d not implemented", conv);
823 g_assert_not_reached ();
828 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
830 MonoMarshalType *info;
834 emit_struct_conv(mb, klass->parent, to_object);
836 info = mono_marshal_load_type_info (klass);
838 if (klass->blittable) {
839 mono_mb_emit_byte (mb, CEE_LDLOC_1);
840 mono_mb_emit_byte (mb, CEE_LDLOC_0);
841 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
842 mono_mb_emit_byte (mb, CEE_PREFIX1);
843 mono_mb_emit_byte (mb, CEE_CPBLK);
847 for (i = 0; i < info->num_fields; i++) {
848 MonoMarshalNative ntype;
849 MonoMarshalConv conv;
850 MonoType *ftype = info->fields [i].field->type;
853 gboolean last_field = i < (info->num_fields -1) ? 0 : 1;
855 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
858 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, klass->unicode, &conv);
861 msize = klass->instance_size - info->fields [i].field->offset;
862 usize = info->native_size - info->fields [i].offset;
864 msize = info->fields [i + 1].field->offset - info->fields [i].field->offset;
865 usize = info->fields [i + 1].offset - info->fields [i].offset;
867 g_assert ((msize >= 0) && (usize >= 0));
870 case MONO_MARSHAL_CONV_NONE: {
873 if (ftype->byref || ftype->type == MONO_TYPE_I ||
874 ftype->type == MONO_TYPE_U) {
875 mono_mb_emit_byte (mb, CEE_LDLOC_1);
876 mono_mb_emit_byte (mb, CEE_LDLOC_0);
877 mono_mb_emit_byte (mb, CEE_LDIND_I);
878 mono_mb_emit_byte (mb, CEE_STIND_I);
887 #if SIZEOF_VOID_P == 4
890 mono_mb_emit_byte (mb, CEE_LDLOC_1);
891 mono_mb_emit_byte (mb, CEE_LDLOC_0);
892 mono_mb_emit_byte (mb, CEE_LDIND_I4);
893 mono_mb_emit_byte (mb, CEE_STIND_I4);
897 case MONO_TYPE_BOOLEAN:
898 mono_mb_emit_byte (mb, CEE_LDLOC_1);
899 mono_mb_emit_byte (mb, CEE_LDLOC_0);
900 mono_mb_emit_byte (mb, CEE_LDIND_I1);
901 mono_mb_emit_byte (mb, CEE_STIND_I1);
905 mono_mb_emit_byte (mb, CEE_LDLOC_1);
906 mono_mb_emit_byte (mb, CEE_LDLOC_0);
907 mono_mb_emit_byte (mb, CEE_LDIND_I2);
908 mono_mb_emit_byte (mb, CEE_STIND_I2);
912 #if SIZEOF_VOID_P == 8
915 mono_mb_emit_byte (mb, CEE_LDLOC_1);
916 mono_mb_emit_byte (mb, CEE_LDLOC_0);
917 mono_mb_emit_byte (mb, CEE_LDIND_I8);
918 mono_mb_emit_byte (mb, CEE_STIND_I8);
921 mono_mb_emit_byte (mb, CEE_LDLOC_1);
922 mono_mb_emit_byte (mb, CEE_LDLOC_0);
923 mono_mb_emit_byte (mb, CEE_LDIND_R4);
924 mono_mb_emit_byte (mb, CEE_STIND_R4);
927 mono_mb_emit_byte (mb, CEE_LDLOC_1);
928 mono_mb_emit_byte (mb, CEE_LDLOC_0);
929 mono_mb_emit_byte (mb, CEE_LDIND_R8);
930 mono_mb_emit_byte (mb, CEE_STIND_R8);
932 case MONO_TYPE_VALUETYPE:
933 if (ftype->data.klass->enumtype) {
934 t = ftype->data.klass->enum_basetype->type;
937 emit_struct_conv (mb, ftype->data.klass, to_object);
940 g_warning ("marshaling type %02x not implemented", ftype->type);
941 g_assert_not_reached ();
947 emit_ptr_to_str_conv (mb, ftype, conv, usize, msize, info->fields [i].mspec);
949 emit_str_to_ptr_conv (mb, ftype, conv, usize, msize, info->fields [i].mspec);
953 mono_mb_emit_add_to_local (mb, 0, usize);
954 mono_mb_emit_add_to_local (mb, 1, msize);
956 mono_mb_emit_add_to_local (mb, 0, msize);
957 mono_mb_emit_add_to_local (mb, 1, usize);
962 static MonoAsyncResult *
963 mono_delegate_begin_invoke (MonoDelegate *delegate, gpointer *params)
965 MonoMethodMessage *msg;
966 MonoDelegate *async_callback;
970 MonoMethod *method = NULL;
975 klass = delegate->object.vtable->klass;
977 method = mono_get_delegate_invoke (klass);
978 for (i = 0; i < klass->method.count; ++i) {
979 if (klass->methods [i]->name[0] == 'B' &&
980 !strcmp ("BeginInvoke", klass->methods [i]->name)) {
981 method = klass->methods [i];
986 g_assert (method != NULL);
988 im = mono_get_delegate_invoke (method->klass);
990 msg = mono_method_call_message_new (method, params, im, &async_callback, &state);
992 return mono_thread_pool_add ((MonoObject *)delegate, msg, async_callback, state);
996 mono_mb_emit_save_args (MonoMethodBuilder *mb, MonoMethodSignature *sig, gboolean save_this)
998 int i, params_var, tmp_var;
1000 /* allocate local (pointer) *params[] */
1001 params_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1002 /* allocate local (pointer) tmp */
1003 tmp_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1005 /* alloate space on stack to store an array of pointers to the arguments */
1006 mono_mb_emit_icon (mb, sizeof (gpointer) * (sig->param_count + 1));
1007 mono_mb_emit_byte (mb, CEE_PREFIX1);
1008 mono_mb_emit_byte (mb, CEE_LOCALLOC);
1009 mono_mb_emit_stloc (mb, params_var);
1012 mono_mb_emit_ldloc (mb, params_var);
1013 mono_mb_emit_stloc (mb, tmp_var);
1015 if (save_this && sig->hasthis) {
1016 mono_mb_emit_ldloc (mb, tmp_var);
1017 mono_mb_emit_ldarg_addr (mb, 0);
1018 mono_mb_emit_byte (mb, CEE_STIND_I);
1019 /* tmp = tmp + sizeof (gpointer) */
1020 if (sig->param_count)
1021 mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
1025 for (i = 0; i < sig->param_count; i++) {
1026 mono_mb_emit_ldloc (mb, tmp_var);
1027 mono_mb_emit_ldarg_addr (mb, i + sig->hasthis);
1028 mono_mb_emit_byte (mb, CEE_STIND_I);
1029 /* tmp = tmp + sizeof (gpointer) */
1030 if (i < (sig->param_count - 1))
1031 mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
1038 mono_signature_to_name (MonoMethodSignature *sig, const char *prefix)
1042 GString *res = g_string_new ("");
1045 g_string_append (res, prefix);
1046 g_string_append_c (res, '_');
1049 mono_type_get_desc (res, sig->ret, FALSE);
1051 for (i = 0; i < sig->param_count; ++i) {
1052 g_string_append_c (res, '_');
1053 mono_type_get_desc (res, sig->params [i], FALSE);
1056 g_string_free (res, FALSE);
1061 mono_marshal_get_delegate_begin_invoke (MonoMethod *method)
1063 MonoMethodSignature *sig;
1064 static MonoMethodSignature *csig = NULL;
1065 MonoMethodBuilder *mb;
1071 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1072 !strcmp (method->name, "BeginInvoke"));
1074 sig = method->signature;
1076 cache = method->klass->image->delegate_begin_invoke_cache;
1077 if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1080 g_assert (sig->hasthis);
1083 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1084 csig = g_malloc0 (sigsize);
1086 /* MonoAsyncResult * begin_invoke (MonoDelegate *delegate, gpointer params[]) */
1087 csig->param_count = 2;
1088 csig->ret = &mono_defaults.object_class->byval_arg;
1089 csig->params [0] = &mono_defaults.object_class->byval_arg;
1090 csig->params [1] = &mono_defaults.int_class->byval_arg;
1093 name = mono_signature_to_name (sig, "begin_invoke");
1094 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_BEGIN_INVOKE);
1097 mb->method->save_lmf = 1;
1099 params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1101 mono_mb_emit_ldarg (mb, 0);
1102 mono_mb_emit_ldloc (mb, params_var);
1103 mono_mb_emit_native_call (mb, csig, mono_delegate_begin_invoke);
1104 mono_mb_emit_byte (mb, CEE_RET);
1106 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1108 g_hash_table_insert (cache, sig, res);
1113 mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params)
1115 MonoDomain *domain = mono_domain_get ();
1116 MonoAsyncResult *ares;
1117 MonoMethod *method = NULL;
1118 MonoMethodSignature *sig;
1119 MonoMethodMessage *msg;
1120 MonoObject *res, *exc;
1121 MonoArray *out_args;
1125 g_assert (delegate);
1127 if (!delegate->method_info || !delegate->method_info->method)
1128 g_assert_not_reached ();
1130 klass = delegate->object.vtable->klass;
1132 for (i = 0; i < klass->method.count; ++i) {
1133 if (klass->methods [i]->name[0] == 'E' &&
1134 !strcmp ("EndInvoke", klass->methods [i]->name)) {
1135 method = klass->methods [i];
1140 g_assert (method != NULL);
1142 sig = method->signature;
1144 msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1146 ares = mono_array_get (msg->args, gpointer, sig->param_count - 1);
1149 res = mono_thread_pool_finish (ares, &out_args, &exc);
1152 char *strace = mono_string_to_utf8 (((MonoException*)exc)->stack_trace);
1154 tmp = g_strdup_printf ("%s\nException Rethrown at:\n", strace);
1156 ((MonoException*)exc)->stack_trace = mono_string_new (domain, tmp);
1158 mono_raise_exception ((MonoException*)exc);
1161 mono_method_return_message_restore (method, params, out_args);
1166 mono_mb_emit_restore_result (MonoMethodBuilder *mb, MonoType *return_type)
1168 if (return_type->byref)
1169 return_type = &mono_defaults.int_class->byval_arg;
1170 else if (return_type->type == MONO_TYPE_VALUETYPE && return_type->data.klass->enumtype)
1171 return_type = return_type->data.klass->enum_basetype;
1173 switch (return_type->type) {
1174 case MONO_TYPE_VOID:
1175 g_assert_not_reached ();
1178 case MONO_TYPE_STRING:
1179 case MONO_TYPE_CLASS:
1180 case MONO_TYPE_OBJECT:
1181 case MONO_TYPE_ARRAY:
1182 case MONO_TYPE_SZARRAY:
1186 case MONO_TYPE_BOOLEAN:
1187 mono_mb_emit_byte (mb, CEE_UNBOX);
1188 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1189 mono_mb_emit_byte (mb, CEE_LDIND_U1);
1192 mono_mb_emit_byte (mb, CEE_UNBOX);
1193 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1194 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1197 case MONO_TYPE_CHAR:
1198 mono_mb_emit_byte (mb, CEE_UNBOX);
1199 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1200 mono_mb_emit_byte (mb, CEE_LDIND_U2);
1203 mono_mb_emit_byte (mb, CEE_UNBOX);
1204 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1205 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1209 mono_mb_emit_byte (mb, CEE_UNBOX);
1210 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1211 mono_mb_emit_byte (mb, CEE_LDIND_I);
1214 mono_mb_emit_byte (mb, CEE_UNBOX);
1215 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1216 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1219 mono_mb_emit_byte (mb, CEE_UNBOX);
1220 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1221 mono_mb_emit_byte (mb, CEE_LDIND_U4);
1225 mono_mb_emit_byte (mb, CEE_UNBOX);
1226 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1227 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1230 mono_mb_emit_byte (mb, CEE_UNBOX);
1231 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1232 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1235 mono_mb_emit_byte (mb, CEE_UNBOX);
1236 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1237 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1239 case MONO_TYPE_VALUETYPE: {
1241 mono_mb_emit_byte (mb, CEE_UNBOX);
1242 class = mono_mb_add_data (mb, mono_class_from_mono_type (return_type));
1243 mono_mb_emit_i4 (mb, class);
1244 mono_mb_emit_byte (mb, CEE_LDOBJ);
1245 mono_mb_emit_i4 (mb, class);
1249 g_warning ("type 0x%x not handled", return_type->type);
1250 g_assert_not_reached ();
1253 mono_mb_emit_byte (mb, CEE_RET);
1257 mono_marshal_get_delegate_end_invoke (MonoMethod *method)
1259 MonoMethodSignature *sig;
1260 static MonoMethodSignature *csig = NULL;
1261 MonoMethodBuilder *mb;
1267 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1268 !strcmp (method->name, "EndInvoke"));
1270 sig = method->signature;
1272 cache = method->klass->image->delegate_end_invoke_cache;
1273 if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1276 g_assert (sig->hasthis);
1279 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1280 csig = g_malloc0 (sigsize);
1282 /* MonoObject *end_invoke (MonoDelegate *delegate, gpointer params[]) */
1283 csig->param_count = 2;
1284 csig->ret = &mono_defaults.object_class->byval_arg;
1285 csig->params [0] = &mono_defaults.object_class->byval_arg;
1286 csig->params [1] = &mono_defaults.int_class->byval_arg;
1289 name = mono_signature_to_name (sig, "end_invoke");
1290 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_END_INVOKE);
1293 mb->method->save_lmf = 1;
1295 params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1297 mono_mb_emit_ldarg (mb, 0);
1298 mono_mb_emit_ldloc (mb, params_var);
1299 mono_mb_emit_native_call (mb, csig, mono_delegate_end_invoke);
1301 if (sig->ret->type == MONO_TYPE_VOID) {
1302 mono_mb_emit_byte (mb, CEE_POP);
1303 mono_mb_emit_byte (mb, CEE_RET);
1305 mono_mb_emit_restore_result (mb, sig->ret);
1307 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1309 g_hash_table_insert (cache, sig, res);
1315 mono_remoting_wrapper (MonoMethod *method, gpointer *params)
1317 MonoMethodMessage *msg;
1318 MonoTransparentProxy *this;
1319 MonoObject *res, *exc;
1320 MonoArray *out_args;
1322 this = *((MonoTransparentProxy **)params [0]);
1325 g_assert (((MonoObject *)this)->vtable->klass == mono_defaults.transparent_proxy_class);
1327 /* skip the this pointer */
1330 if (this->klass->contextbound && this->rp->context == (MonoObject *) mono_context_get ())
1333 MonoMethodSignature *sig = method->signature;
1334 int count = sig->param_count;
1335 gpointer* mparams = (gpointer*) alloca(count*sizeof(gpointer));
1337 for (i=0; i<count; i++) {
1338 MonoClass *class = mono_class_from_mono_type (sig->params [i]);
1339 if (class->valuetype) {
1340 if (sig->params [i]->byref)
1341 mparams[i] = *((gpointer *)params [i]);
1343 mparams[i] = params [i];
1345 mparams[i] = *((gpointer**)params [i]);
1349 return mono_runtime_invoke (method, this->rp->unwrapped_server, mparams, NULL);
1352 msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1354 res = mono_remoting_invoke ((MonoObject *)this->rp, msg, &exc, &out_args);
1357 mono_raise_exception ((MonoException *)exc);
1359 mono_method_return_message_restore (method, params, out_args);
1365 mono_marshal_get_remoting_invoke (MonoMethod *method)
1367 MonoMethodSignature *sig;
1368 static MonoMethodSignature *csig = NULL;
1369 MonoMethodBuilder *mb;
1376 if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE)
1379 sig = method->signature;
1381 /* we cant remote methods without this pointer */
1385 cache = method->klass->image->remoting_invoke_cache;
1386 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1390 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
1391 csig->params [0] = &mono_defaults.int_class->byval_arg;
1392 csig->params [1] = &mono_defaults.int_class->byval_arg;
1393 csig->ret = &mono_defaults.object_class->byval_arg;
1397 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE);
1398 mb->method->save_lmf = 1;
1400 params_var = mono_mb_emit_save_args (mb, sig, TRUE);
1402 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1403 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1404 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
1405 mono_mb_emit_ldloc (mb, params_var);
1406 mono_mb_emit_native_call (mb, csig, mono_remoting_wrapper);
1408 if (sig->ret->type == MONO_TYPE_VOID) {
1409 mono_mb_emit_byte (mb, CEE_POP);
1410 mono_mb_emit_byte (mb, CEE_RET);
1412 mono_mb_emit_restore_result (mb, sig->ret);
1415 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1417 g_hash_table_insert (cache, method, res);
1422 mono_marshal_get_remoting_invoke_with_check (MonoMethod *method)
1424 MonoMethodSignature *sig;
1425 MonoMethodBuilder *mb;
1426 MonoMethod *res, *native;
1432 if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)
1435 sig = method->signature;
1437 /* we cant remote methods without this pointer */
1438 g_assert (sig->hasthis);
1440 cache = method->klass->image->remoting_invoke_cache;
1441 if ((res = (MonoMethod *)g_hash_table_lookup (cache, (char *)method + 1)))
1444 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK);
1446 mono_mb_emit_ldarg (mb, 0);
1447 pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
1449 native = mono_marshal_get_remoting_invoke (method);
1451 for (i = 0; i <= sig->param_count; i++)
1452 mono_mb_emit_ldarg (mb, i);
1454 mono_mb_emit_managed_call (mb, native, native->signature);
1455 mono_mb_emit_byte (mb, CEE_RET);
1457 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1459 for (i = 0; i <= sig->param_count; i++)
1460 mono_mb_emit_ldarg (mb, i);
1462 mono_mb_emit_managed_call (mb, method, method->signature);
1463 mono_mb_emit_byte (mb, CEE_RET);
1465 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1467 g_hash_table_insert (cache, (char *)method + 1, res);
1472 * the returned method invokes all methods in a multicast delegate
1475 mono_marshal_get_delegate_invoke (MonoMethod *method)
1477 MonoMethodSignature *sig, *static_sig;
1479 MonoMethodBuilder *mb;
1485 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1486 !strcmp (method->name, "Invoke"));
1488 sig = method->signature;
1490 cache = method->klass->image->delegate_invoke_cache;
1491 if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1494 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1495 static_sig = g_memdup (sig, sigsize);
1496 static_sig->hasthis = 0;
1498 name = mono_signature_to_name (sig, "invoke");
1499 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_INVOKE);
1502 /* allocate local 0 (object) */
1503 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1505 g_assert (sig->hasthis);
1509 * prev.Invoke( args .. );
1510 * return this.<target>( args .. );
1513 /* get this->prev */
1514 mono_mb_emit_ldarg (mb, 0);
1515 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoMulticastDelegate, prev));
1516 mono_mb_emit_byte (mb, CEE_LDIND_I );
1517 mono_mb_emit_stloc (mb, 0);
1519 /* if prev != null */
1520 mono_mb_emit_ldloc (mb, 0);
1521 mono_mb_emit_byte (mb, CEE_BRFALSE);
1524 mono_mb_emit_i4 (mb, 0);
1527 mono_mb_emit_ldloc (mb, 0);
1528 for (i = 0; i < sig->param_count; i++)
1529 mono_mb_emit_ldarg (mb, i + 1);
1530 mono_mb_emit_managed_call (mb, method, method->signature);
1531 if (sig->ret->type != MONO_TYPE_VOID)
1532 mono_mb_emit_byte (mb, CEE_POP);
1534 /* continued or prev == null */
1535 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1537 /* get this->target */
1538 mono_mb_emit_ldarg (mb, 0);
1539 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, target));
1540 mono_mb_emit_byte (mb, CEE_LDIND_I );
1541 mono_mb_emit_stloc (mb, 0);
1543 /* if target != null */
1544 mono_mb_emit_ldloc (mb, 0);
1545 mono_mb_emit_byte (mb, CEE_BRFALSE);
1547 mono_mb_emit_i4 (mb, 0);
1549 /* then call this->method_ptr nonstatic */
1550 mono_mb_emit_ldloc (mb, 0);
1551 for (i = 0; i < sig->param_count; ++i)
1552 mono_mb_emit_ldarg (mb, i + 1);
1553 mono_mb_emit_ldarg (mb, 0);
1554 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1555 mono_mb_emit_byte (mb, CEE_LDIND_I );
1556 mono_mb_emit_byte (mb, CEE_CALLI);
1557 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
1559 mono_mb_emit_byte (mb, CEE_BR);
1561 mono_mb_emit_i4 (mb, 0);
1563 /* else [target == null] call this->method_ptr static */
1564 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1566 for (i = 0; i < sig->param_count; ++i)
1567 mono_mb_emit_ldarg (mb, i + 1);
1568 mono_mb_emit_ldarg (mb, 0);
1569 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1570 mono_mb_emit_byte (mb, CEE_LDIND_I );
1571 mono_mb_emit_byte (mb, CEE_CALLI);
1572 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, static_sig));
1575 mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
1576 mono_mb_emit_byte (mb, CEE_RET);
1578 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1581 g_hash_table_insert (cache, sig, res);
1587 * generates IL code for the runtime invoke function
1588 * MonoObject *runtime_invoke (MonoObject *this, void **params, MonoObject **exc)
1590 * we also catch exceptions if exc != null
1593 mono_marshal_get_runtime_invoke (MonoMethod *method)
1595 MonoMethodSignature *sig, *csig;
1596 MonoExceptionClause *clause;
1597 MonoMethodHeader *header;
1598 MonoMethodBuilder *mb;
1601 static MonoString *string_dummy = NULL;
1602 int i, pos, sigsize;
1606 cache = method->klass->image->runtime_invoke_cache;
1607 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1610 /* to make it work with our special string constructors */
1612 string_dummy = mono_string_new_wrapper ("dummy");
1614 sig = method->signature;
1616 sigsize = sizeof (MonoMethodSignature) + 3 * sizeof (MonoType *);
1617 csig = g_malloc0 (sigsize);
1619 csig->param_count = 3;
1620 csig->ret = &mono_defaults.object_class->byval_arg;
1621 csig->params [0] = &mono_defaults.object_class->byval_arg;
1622 csig->params [1] = &mono_defaults.int_class->byval_arg;
1623 csig->params [2] = &mono_defaults.int_class->byval_arg;
1625 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_RUNTIME_INVOKE);
1627 /* allocate local 0 (object) tmp */
1628 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1629 /* allocate local 1 (object) exc */
1630 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1632 /* cond set *exc to null */
1633 mono_mb_emit_byte (mb, CEE_LDARG_2);
1634 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
1635 mono_mb_emit_byte (mb, 3);
1636 mono_mb_emit_byte (mb, CEE_LDARG_2);
1637 mono_mb_emit_byte (mb, CEE_LDNULL);
1638 mono_mb_emit_byte (mb, CEE_STIND_I);
1641 if (method->string_ctor) {
1642 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1643 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1644 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, string_dummy));
1646 mono_mb_emit_ldarg (mb, 0);
1647 if (method->klass->valuetype) {
1648 mono_mb_emit_byte (mb, CEE_UNBOX);
1649 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method->klass));
1654 for (i = 0; i < sig->param_count; i++) {
1655 MonoType *t = sig->params [i];
1658 mono_mb_emit_ldarg (mb, 1);
1660 mono_mb_emit_icon (mb, sizeof (gpointer) * i);
1661 mono_mb_emit_byte (mb, CEE_ADD);
1663 mono_mb_emit_byte (mb, CEE_LDIND_I);
1668 type = sig->params [i]->type;
1672 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1674 case MONO_TYPE_BOOLEAN:
1676 mono_mb_emit_byte (mb, CEE_LDIND_U1);
1679 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1682 case MONO_TYPE_CHAR:
1683 mono_mb_emit_byte (mb, CEE_LDIND_U2);
1687 mono_mb_emit_byte (mb, CEE_LDIND_I);
1690 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1693 mono_mb_emit_byte (mb, CEE_LDIND_U4);
1696 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1699 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1703 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1705 case MONO_TYPE_STRING:
1706 case MONO_TYPE_CLASS:
1707 case MONO_TYPE_ARRAY:
1709 case MONO_TYPE_SZARRAY:
1710 case MONO_TYPE_OBJECT:
1713 case MONO_TYPE_VALUETYPE:
1714 if (t->data.klass->enumtype) {
1715 type = t->data.klass->enum_basetype->type;
1718 mono_mb_emit_byte (mb, CEE_LDOBJ);
1719 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, t->data.klass));
1722 g_assert_not_reached ();
1726 if (method->string_ctor) {
1727 MonoMethodSignature *strsig;
1729 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1730 strsig = g_memdup (sig, sigsize);
1731 strsig->ret = &mono_defaults.string_class->byval_arg;
1733 mono_mb_emit_managed_call (mb, method, strsig);
1735 mono_mb_emit_managed_call (mb, method, NULL);
1737 if (sig->ret->byref) {
1739 g_assert_not_reached ();
1743 switch (sig->ret->type) {
1744 case MONO_TYPE_VOID:
1745 if (!method->string_ctor)
1746 mono_mb_emit_byte (mb, CEE_LDNULL);
1748 case MONO_TYPE_BOOLEAN:
1749 case MONO_TYPE_CHAR:
1762 case MONO_TYPE_VALUETYPE:
1763 /* box value types */
1764 mono_mb_emit_byte (mb, CEE_BOX);
1765 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (sig->ret)));
1767 case MONO_TYPE_STRING:
1768 case MONO_TYPE_CLASS:
1769 case MONO_TYPE_ARRAY:
1770 case MONO_TYPE_SZARRAY:
1771 case MONO_TYPE_OBJECT:
1776 g_assert_not_reached ();
1779 mono_mb_emit_stloc (mb, 0);
1781 mono_mb_emit_byte (mb, CEE_LEAVE);
1783 mono_mb_emit_i4 (mb, 0);
1785 clause = g_new0 (MonoExceptionClause, 1);
1786 clause->flags = MONO_EXCEPTION_CLAUSE_FILTER;
1787 clause->try_len = mb->pos;
1790 clause->token_or_filter = mb->pos;
1792 mono_mb_emit_byte (mb, CEE_POP);
1793 mono_mb_emit_byte (mb, CEE_LDARG_2);
1794 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
1795 mono_mb_emit_byte (mb, CEE_PREFIX1);
1796 mono_mb_emit_byte (mb, CEE_CGT_UN);
1797 mono_mb_emit_byte (mb, CEE_PREFIX1);
1798 mono_mb_emit_byte (mb, CEE_ENDFILTER);
1800 clause->handler_offset = mb->pos;
1803 /* store exception */
1804 mono_mb_emit_stloc (mb, 1);
1806 mono_mb_emit_byte (mb, CEE_LDARG_2);
1807 mono_mb_emit_ldloc (mb, 1);
1808 mono_mb_emit_byte (mb, CEE_STIND_I);
1810 mono_mb_emit_byte (mb, CEE_LEAVE);
1811 mono_mb_emit_i4 (mb, 0);
1813 clause->handler_len = mb->pos - clause->handler_offset;
1816 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1817 mono_mb_emit_ldloc (mb, 0);
1818 mono_mb_emit_byte (mb, CEE_RET);
1820 res = mono_mb_create_method (mb, csig, sig->param_count + 16);
1823 header = ((MonoMethodNormal *)res)->header;
1824 header->num_clauses = 1;
1825 header->clauses = clause;
1827 g_hash_table_insert (cache, method, res);
1833 * generates IL code to call managed methods from unmanaged code
1836 mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this, MonoMarshalSpec **mspecs)
1838 MonoMethodSignature *sig, *csig;
1839 MonoMethodBuilder *mb;
1843 int i, pos, sigsize, *tmp_locals;
1845 g_assert (method != NULL);
1846 g_assert (!method->signature->pinvoke);
1848 cache = method->klass->image->managed_wrapper_cache;
1849 if (!this && (res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1853 /* fime: howto free that memory ? */
1856 sig = method->signature;
1858 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_NATIVE_TO_MANAGED);
1860 /* allocate local 0 (pointer) src_ptr */
1861 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1862 /* allocate local 1 (pointer) dst_ptr */
1863 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1864 /* allocate local 2 (boolean) delete_old */
1865 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
1867 mono_mb_emit_byte (mb, CEE_LDNULL);
1868 mono_mb_emit_byte (mb, CEE_STLOC_2);
1870 /* we copy the signature, so that we can modify it */
1871 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1872 csig = g_memdup (sig, sigsize);
1876 /* fixme: howto handle this ? */
1880 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1881 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1882 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, this));
1887 g_assert_not_reached ();
1892 /* we first do all conversions */
1893 tmp_locals = alloca (sizeof (int) * sig->param_count);
1894 for (i = 0; i < sig->param_count; i ++) {
1895 MonoType *t = sig->params [i];
1896 MonoMarshalSpec *spec = mspecs [i + 1];
1900 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
1903 MonoMethod *marshal_native_to_managed;
1904 MonoMethod *get_instance;
1906 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
1907 g_assert (mtype != NULL);
1908 mklass = mono_class_from_mono_type (mtype);
1909 g_assert (mklass != NULL);
1911 marshal_native_to_managed = mono_find_method_by_name (mklass, "MarshalNativeToManaged", 1);
1912 g_assert (marshal_native_to_managed);
1913 get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
1914 g_assert (get_instance);
1917 case MONO_TYPE_CLASS:
1918 case MONO_TYPE_OBJECT:
1919 case MONO_TYPE_STRING:
1920 case MONO_TYPE_ARRAY:
1921 case MONO_TYPE_SZARRAY:
1925 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1927 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
1929 mono_mb_emit_byte (mb, CEE_CALL);
1930 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
1932 mono_mb_emit_ldarg (mb, i);
1934 mono_mb_emit_byte (mb, CEE_CALLVIRT);
1935 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_native_to_managed));
1937 mono_mb_emit_stloc (mb, tmp_locals [i]);
1940 g_warning ("custom marshalling of type %x is currently not supported", t->type);
1941 g_assert_not_reached ();
1948 case MONO_TYPE_VALUETYPE:
1950 klass = sig->params [i]->data.klass;
1951 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
1952 klass->blittable || klass->enumtype)
1955 tmp_locals [i] = mono_mb_add_local (mb, &klass->byval_arg);
1958 mono_mb_emit_ldarg (mb, i);
1960 mono_mb_emit_ldarg_addr (mb, i);
1961 mono_mb_emit_byte (mb, CEE_STLOC_0);
1964 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1965 mono_mb_emit_byte (mb, CEE_BRFALSE);
1967 mono_mb_emit_i4 (mb, 0);
1970 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
1971 mono_mb_emit_byte (mb, CEE_STLOC_1);
1973 /* emit valuetype convnversion code code */
1974 emit_struct_conv (mb, klass, TRUE);
1977 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1979 case MONO_TYPE_STRING:
1983 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1984 csig->params [i] = &mono_defaults.int_class->byval_arg;
1986 mono_mb_emit_ldarg (mb, i);
1987 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1988 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1989 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
1990 mono_mb_emit_stloc (mb, tmp_locals [i]);
1992 case MONO_TYPE_ARRAY:
1993 case MONO_TYPE_SZARRAY:
1997 klass = mono_class_from_mono_type (t);
1999 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2000 csig->params [i] = &mono_defaults.int_class->byval_arg;
2002 g_warning ("array marshaling not implemented");
2003 g_assert_not_reached ();
2008 for (i = 0; i < sig->param_count; i++) {
2009 MonoType *t = sig->params [i];
2012 case MONO_TYPE_BOOLEAN:
2026 mono_mb_emit_ldarg (mb, i);
2028 case MONO_TYPE_STRING:
2030 mono_mb_emit_ldarg (mb, i);
2032 g_assert (tmp_locals [i]);
2033 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2036 case MONO_TYPE_CLASS:
2037 case MONO_TYPE_ARRAY:
2038 case MONO_TYPE_SZARRAY:
2039 case MONO_TYPE_OBJECT:
2041 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2043 mono_mb_emit_ldarg (mb, i);
2045 case MONO_TYPE_VALUETYPE:
2046 klass = sig->params [i]->data.klass;
2047 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2048 klass->blittable || klass->enumtype) {
2049 mono_mb_emit_ldarg (mb, i);
2053 g_assert (tmp_locals [i]);
2055 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2057 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2060 g_warning ("type 0x%02x unknown", t->type);
2061 g_assert_not_reached ();
2065 mono_mb_emit_managed_call (mb, method, NULL);
2067 if (!sig->ret->byref) {
2068 switch (sig->ret->type) {
2069 case MONO_TYPE_VOID:
2070 case MONO_TYPE_BOOLEAN:
2084 case MONO_TYPE_OBJECT:
2085 mono_mb_emit_byte (mb, CEE_RET);
2087 case MONO_TYPE_STRING:
2088 csig->ret = &mono_defaults.int_class->byval_arg;
2090 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2091 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2092 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
2093 mono_mb_emit_byte (mb, CEE_RET);
2095 case MONO_TYPE_VALUETYPE: {
2097 klass = sig->ret->data.klass;
2098 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2099 klass->blittable || klass->enumtype)
2102 /* load pointer to returned value type */
2103 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2104 mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
2106 /* store the address of the source into local variable 0 */
2107 mono_mb_emit_byte (mb, CEE_STLOC_0);
2108 /* allocate space for the native struct and
2109 * store the address into dst_ptr */
2110 tmp = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2112 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2113 mono_mb_emit_byte (mb, CEE_PREFIX1);
2114 mono_mb_emit_byte (mb, CEE_LOCALLOC);
2115 mono_mb_emit_byte (mb, CEE_STLOC_1);
2116 mono_mb_emit_byte (mb, CEE_LDLOC_1);
2117 mono_mb_emit_stloc (mb, tmp);
2119 /* emit valuetype conversion code */
2120 emit_struct_conv (mb, klass, FALSE);
2121 mono_mb_emit_ldloc (mb, tmp);
2122 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2123 mono_mb_emit_byte (mb, CEE_MONO_RETOBJ);
2124 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2128 g_warning ("return type 0x%02x unknown", sig->ret->type);
2129 g_assert_not_reached ();
2132 mono_mb_emit_byte (mb, CEE_RET);
2135 res = mono_mb_create_method (mb, csig, sig->param_count + 16);
2139 g_hash_table_insert (cache, method, res);
2145 * mono_marshal_get_ldfld_wrapper:
2146 * @type: the type of the field
2148 * This method generates a function which can be use to load a field with type
2149 * @type from an object. The generated function has the following signature:
2150 * <@type> ldfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset)
2153 mono_marshal_get_ldfld_wrapper (MonoType *type)
2155 MonoMethodSignature *sig, *csig;
2156 MonoMethodBuilder *mb;
2159 static GHashTable *ldfld_hash = NULL;
2164 ldfld_hash = g_hash_table_new (NULL, NULL);
2170 if (type->type == MONO_TYPE_SZARRAY) {
2171 klass = mono_defaults.array_class;
2172 } else if (type->type == MONO_TYPE_VALUETYPE) {
2173 klass = type->data.klass;
2174 if (klass->enumtype) {
2175 t = klass->enum_basetype->type;
2176 klass = mono_class_from_mono_type (klass->enum_basetype);
2178 } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
2179 t == MONO_TYPE_CLASS) {
2180 klass = mono_defaults.object_class;
2181 } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
2182 klass = mono_defaults.int_class;
2184 klass = mono_class_from_mono_type (type);
2187 klass = mono_defaults.int_class;
2190 if ((res = g_hash_table_lookup (ldfld_hash, klass)))
2193 name = g_strdup_printf ("__ldfld_wrapper_%s.%s", klass->name_space, klass->name);
2194 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_LDFLD);
2197 mb->method->save_lmf = 1;
2199 sig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
2200 sig->params [0] = &mono_defaults.object_class->byval_arg;
2201 sig->params [1] = &mono_defaults.int_class->byval_arg;
2202 sig->params [2] = &mono_defaults.int_class->byval_arg;
2203 sig->params [3] = &mono_defaults.int_class->byval_arg;
2204 sig->ret = &klass->byval_arg;
2206 mono_mb_emit_ldarg (mb, 0);
2207 pos0 = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
2209 mono_mb_emit_ldarg (mb, 0);
2210 mono_mb_emit_ldarg (mb, 1);
2211 mono_mb_emit_ldarg (mb, 2);
2213 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
2214 csig->params [0] = &mono_defaults.object_class->byval_arg;
2215 csig->params [1] = &mono_defaults.int_class->byval_arg;
2216 csig->params [2] = &mono_defaults.int_class->byval_arg;
2217 csig->ret = &klass->this_arg;
2220 mono_mb_emit_native_call (mb, csig, mono_load_remote_field_new);
2222 if (klass->valuetype) {
2223 mono_mb_emit_byte (mb, CEE_UNBOX);
2224 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2225 mono_mb_emit_byte (mb, CEE_BR);
2227 mono_mb_emit_i4 (mb, 0);
2229 mono_mb_emit_byte (mb, CEE_RET);
2233 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
2235 mono_mb_emit_ldarg (mb, 0);
2236 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2237 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2238 mono_mb_emit_ldarg (mb, 3);
2239 mono_mb_emit_byte (mb, CEE_ADD);
2241 if (klass->valuetype)
2242 mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
2247 case MONO_TYPE_BOOLEAN:
2248 mono_mb_emit_byte (mb, CEE_LDIND_I1);
2250 case MONO_TYPE_CHAR:
2253 mono_mb_emit_byte (mb, CEE_LDIND_I2);
2257 mono_mb_emit_byte (mb, CEE_LDIND_I4);
2261 mono_mb_emit_byte (mb, CEE_LDIND_I8);
2264 mono_mb_emit_byte (mb, CEE_LDIND_R4);
2267 mono_mb_emit_byte (mb, CEE_LDIND_R8);
2269 case MONO_TYPE_ARRAY:
2271 case MONO_TYPE_FNPTR:
2272 case MONO_TYPE_SZARRAY:
2273 case MONO_TYPE_OBJECT:
2274 case MONO_TYPE_CLASS:
2275 case MONO_TYPE_STRING:
2278 mono_mb_emit_byte (mb, CEE_LDIND_I);
2280 case MONO_TYPE_VALUETYPE:
2281 g_assert (!klass->enumtype);
2282 mono_mb_emit_byte (mb, CEE_LDOBJ);
2283 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2286 g_warning ("type %x not implemented", type->type);
2287 g_assert_not_reached ();
2290 mono_mb_emit_byte (mb, CEE_RET);
2292 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
2295 g_hash_table_insert (ldfld_hash, klass, res);
2301 * mono_marshal_get_stfld_wrapper:
2302 * @type: the type of the field
2304 * This method generates a function which can be use to store a field with type
2305 * @type. The generated function has the following signature:
2306 * void stfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset, <@type> val)
2309 mono_marshal_get_stfld_wrapper (MonoType *type)
2311 MonoMethodSignature *sig, *csig;
2312 MonoMethodBuilder *mb;
2315 static GHashTable *stfld_hash = NULL;
2320 stfld_hash = g_hash_table_new (NULL, NULL);
2325 if (type->type == MONO_TYPE_SZARRAY) {
2326 klass = mono_defaults.array_class;
2327 } else if (type->type == MONO_TYPE_VALUETYPE) {
2328 klass = type->data.klass;
2329 if (klass->enumtype) {
2330 t = klass->enum_basetype->type;
2331 klass = mono_class_from_mono_type (klass->enum_basetype);
2333 } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
2334 t == MONO_TYPE_CLASS) {
2335 klass = mono_defaults.object_class;
2336 } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
2337 klass = mono_defaults.int_class;
2339 klass = mono_class_from_mono_type (type);
2342 klass = mono_defaults.int_class;
2345 if ((res = g_hash_table_lookup (stfld_hash, klass)))
2348 name = g_strdup_printf ("__stfld_wrapper_%s.%s", klass->name_space, klass->name);
2349 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_STFLD);
2352 mb->method->save_lmf = 1;
2354 sig = mono_metadata_signature_alloc (mono_defaults.corlib, 5);
2355 sig->params [0] = &mono_defaults.object_class->byval_arg;
2356 sig->params [1] = &mono_defaults.int_class->byval_arg;
2357 sig->params [2] = &mono_defaults.int_class->byval_arg;
2358 sig->params [3] = &mono_defaults.int_class->byval_arg;
2359 sig->params [4] = &klass->byval_arg;
2360 sig->ret = &mono_defaults.void_class->byval_arg;
2362 mono_mb_emit_ldarg (mb, 0);
2363 pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
2365 mono_mb_emit_ldarg (mb, 0);
2366 mono_mb_emit_ldarg (mb, 1);
2367 mono_mb_emit_ldarg (mb, 2);
2368 mono_mb_emit_ldarg (mb, 4);
2370 if (klass->valuetype) {
2371 mono_mb_emit_byte (mb, CEE_BOX);
2372 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2375 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
2376 csig->params [0] = &mono_defaults.object_class->byval_arg;
2377 csig->params [1] = &mono_defaults.int_class->byval_arg;
2378 csig->params [2] = &mono_defaults.int_class->byval_arg;
2379 csig->params [3] = &klass->this_arg;
2380 csig->ret = &mono_defaults.void_class->byval_arg;
2383 mono_mb_emit_native_call (mb, csig, mono_store_remote_field_new);
2385 mono_mb_emit_byte (mb, CEE_RET);
2387 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2389 mono_mb_emit_ldarg (mb, 0);
2390 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2391 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2392 mono_mb_emit_ldarg (mb, 3);
2393 mono_mb_emit_byte (mb, CEE_ADD);
2394 mono_mb_emit_ldarg (mb, 4);
2399 case MONO_TYPE_BOOLEAN:
2400 mono_mb_emit_byte (mb, CEE_STIND_I1);
2402 case MONO_TYPE_CHAR:
2405 mono_mb_emit_byte (mb, CEE_STIND_I2);
2409 mono_mb_emit_byte (mb, CEE_STIND_I4);
2413 mono_mb_emit_byte (mb, CEE_STIND_I8);
2416 mono_mb_emit_byte (mb, CEE_STIND_R4);
2419 mono_mb_emit_byte (mb, CEE_STIND_R8);
2421 case MONO_TYPE_ARRAY:
2423 case MONO_TYPE_FNPTR:
2424 case MONO_TYPE_SZARRAY:
2425 case MONO_TYPE_OBJECT:
2426 case MONO_TYPE_CLASS:
2427 case MONO_TYPE_STRING:
2430 mono_mb_emit_byte (mb, CEE_STIND_I);
2432 case MONO_TYPE_VALUETYPE:
2433 g_assert (!klass->enumtype);
2434 mono_mb_emit_byte (mb, CEE_STOBJ);
2435 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2438 g_warning ("type %x not implemented", type->type);
2439 g_assert_not_reached ();
2442 mono_mb_emit_byte (mb, CEE_RET);
2444 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
2447 g_hash_table_insert (stfld_hash, klass, res);
2453 * generates IL code for the icall wrapper (the generated method
2454 * calls the unamnaged code in func)
2457 mono_marshal_get_icall_wrapper (MonoMethodSignature *sig, const char *name, gconstpointer func)
2459 MonoMethodSignature *csig;
2460 MonoMethodBuilder *mb;
2464 g_assert (sig->pinvoke);
2466 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_MANAGED_TO_NATIVE);
2468 mb->method->save_lmf = 1;
2470 /* we copy the signature, so that we can modify it */
2471 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
2474 mono_mb_emit_byte (mb, CEE_LDARG_0);
2476 for (i = 0; i < sig->param_count; i++)
2477 mono_mb_emit_ldarg (mb, i + sig->hasthis);
2479 mono_mb_emit_native_call (mb, sig, (gpointer) func);
2481 mono_mb_emit_byte (mb, CEE_RET);
2483 csig = g_memdup (sig, sigsize);
2486 res = mono_mb_create_method (mb, csig, csig->param_count + 16);
2493 * generates IL code for the pinvoke wrapper (the generated method
2494 * calls the unamnage code in method->addr)
2497 mono_marshal_get_native_wrapper (MonoMethod *method)
2499 MonoMethodSignature *sig, *csig;
2500 MonoMethodPInvoke *piinfo;
2501 MonoMethodBuilder *mb;
2502 MonoMarshalSpec **mspecs;
2506 gboolean pinvoke = FALSE;
2507 int i, pos, argnum, *tmp_locals;
2510 g_assert (method != NULL);
2511 g_assert (method->signature->pinvoke);
2513 cache = method->klass->image->native_wrapper_cache;
2514 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
2517 sig = method->signature;
2518 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
2520 if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
2521 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2524 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_MANAGED_TO_NATIVE);
2526 mb->method->save_lmf = 1;
2528 if (pinvoke && !method->addr)
2529 mono_lookup_pinvoke_call (method);
2531 piinfo = (MonoMethodPInvoke *)method;
2533 if (!method->addr) {
2534 mono_mb_emit_exception (mb);
2535 csig = g_memdup (sig, sigsize);
2537 res = mono_mb_create_method (mb, csig, csig->param_count + 16);
2539 g_hash_table_insert (cache, method, res);
2543 /* internal calls: we simply push all arguments and call the method (no conversions) */
2544 if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
2546 /* hack - string constructors returns a value */
2547 if (method->string_ctor) {
2548 csig = g_memdup (sig, sigsize);
2549 csig->ret = &mono_defaults.string_class->byval_arg;
2554 mono_mb_emit_byte (mb, CEE_LDARG_0);
2556 for (i = 0; i < sig->param_count; i++)
2557 mono_mb_emit_ldarg (mb, i + sig->hasthis);
2559 g_assert (method->addr);
2560 mono_mb_emit_native_call (mb, csig, method->addr);
2562 mono_mb_emit_byte (mb, CEE_RET);
2564 csig = g_memdup (csig, sigsize);
2566 res = mono_mb_create_method (mb, csig, csig->param_count + 16);
2568 g_hash_table_insert (cache, method, res);
2574 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
2575 mono_method_get_marshal_info (method, mspecs);
2577 /* pinvoke: we need to convert the arguments if necessary */
2579 /* we copy the signature, so that we can set pinvoke to 0 */
2580 csig = g_memdup (sig, sigsize);
2583 /* we allocate local for use with emit_struct_conv() */
2584 /* allocate local 0 (pointer) src_ptr */
2585 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2586 /* allocate local 1 (pointer) dst_ptr */
2587 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2588 /* allocate local 2 (boolean) delete_old */
2589 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2591 /* delete_old = FALSE */
2592 mono_mb_emit_icon (mb, 0);
2593 mono_mb_emit_byte (mb, CEE_STLOC_2);
2595 if (!MONO_TYPE_IS_VOID(sig->ret)) {
2596 /* allocate local 3 to store the return value */
2597 mono_mb_add_local (mb, sig->ret);
2600 /* we first do all conversions */
2601 tmp_locals = alloca (sizeof (int) * sig->param_count);
2603 for (i = 0; i < sig->param_count; i ++) {
2604 MonoType *t = sig->params [i];
2605 MonoMarshalSpec *spec = mspecs [i + 1];
2607 argnum = i + sig->hasthis;
2610 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
2613 MonoMethod *marshal_managed_to_native;
2614 MonoMethod *get_instance;
2616 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
2617 g_assert (mtype != NULL);
2618 mklass = mono_class_from_mono_type (mtype);
2619 g_assert (mklass != NULL);
2621 marshal_managed_to_native = mono_find_method_by_name (mklass, "MarshalManagedToNative", 1);
2622 g_assert (marshal_managed_to_native);
2623 get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
2624 g_assert (get_instance);
2627 case MONO_TYPE_CLASS:
2628 case MONO_TYPE_OBJECT:
2629 case MONO_TYPE_STRING:
2630 case MONO_TYPE_ARRAY:
2631 case MONO_TYPE_SZARRAY:
2635 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2637 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
2639 mono_mb_emit_byte (mb, CEE_CALL);
2640 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
2642 mono_mb_emit_ldarg (mb, argnum);
2644 mono_mb_emit_byte (mb, CEE_CALLVIRT);
2645 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_managed_to_native));
2647 mono_mb_emit_stloc (mb, tmp_locals [i]);
2650 g_warning ("custom marshalling of type %x is currently not supported", t->type);
2651 g_assert_not_reached ();
2659 case MONO_TYPE_VALUETYPE:
2660 klass = t->data.klass;
2662 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2663 klass->blittable || klass->enumtype)
2666 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2668 /* store the address of the source into local variable 0 */
2670 mono_mb_emit_ldarg (mb, argnum);
2672 mono_mb_emit_ldarg_addr (mb, argnum);
2674 mono_mb_emit_byte (mb, CEE_STLOC_0);
2676 /* allocate space for the native struct and
2677 * store the address into local variable 1 (dest) */
2678 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2679 mono_mb_emit_byte (mb, CEE_PREFIX1);
2680 mono_mb_emit_byte (mb, CEE_LOCALLOC);
2681 mono_mb_emit_stloc (mb, tmp_locals [i]);
2684 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2685 mono_mb_emit_byte (mb, CEE_BRFALSE);
2687 mono_mb_emit_i4 (mb, 0);
2691 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2692 mono_mb_emit_byte (mb, CEE_STLOC_1);
2694 /* emit valuetype conversion code */
2695 emit_struct_conv (mb, klass, FALSE);
2698 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2700 case MONO_TYPE_STRING:
2701 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2702 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2705 if (t->attrs & PARAM_ATTRIBUTE_OUT)
2708 mono_mb_emit_ldarg (mb, argnum);
2709 mono_mb_emit_byte (mb, CEE_LDIND_I);
2711 mono_mb_emit_ldarg (mb, argnum);
2714 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2715 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2718 switch (spec->native) {
2719 case MONO_NATIVE_LPWSTR:
2720 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPWSTR);
2722 case MONO_NATIVE_LPSTR:
2723 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
2726 g_warning ("marshalling conversion %d not implemented", spec->native);
2727 g_assert_not_reached ();
2730 switch (piinfo->piflags & PINVOKE_ATTRIBUTE_CHAR_SET_MASK) {
2731 case PINVOKE_ATTRIBUTE_CHAR_SET_ANSI:
2732 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
2734 case PINVOKE_ATTRIBUTE_CHAR_SET_UNICODE:
2735 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPWSTR);
2737 case PINVOKE_ATTRIBUTE_CHAR_SET_AUTO:
2738 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPTSTR);
2741 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
2746 mono_mb_emit_stloc (mb, tmp_locals [i]);
2748 case MONO_TYPE_CLASS:
2749 case MONO_TYPE_OBJECT:
2750 klass = t->data.klass;
2752 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2753 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2755 if (klass->delegate) {
2756 g_assert (!t->byref);
2757 mono_mb_emit_ldarg (mb, argnum);
2758 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2759 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2760 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_DEL_FTN);
2761 mono_mb_emit_stloc (mb, tmp_locals [i]);
2762 } else if (klass == mono_defaults.stringbuilder_class) {
2763 g_assert (!t->byref);
2764 mono_mb_emit_ldarg (mb, argnum);
2765 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2766 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2767 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_SB_LPSTR);
2768 mono_mb_emit_stloc (mb, tmp_locals [i]);
2770 mono_mb_emit_byte (mb, CEE_LDNULL);
2771 mono_mb_emit_stloc (mb, tmp_locals [i]);
2774 /* we dont need any conversions for out parameters */
2775 if (t->attrs & PARAM_ATTRIBUTE_OUT)
2778 mono_mb_emit_ldarg (mb, argnum);
2779 mono_mb_emit_byte (mb, CEE_LDIND_I);
2782 mono_mb_emit_ldarg (mb, argnum);
2783 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2784 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2787 /* store the address of the source into local variable 0 */
2788 mono_mb_emit_byte (mb, CEE_STLOC_0);
2789 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2790 mono_mb_emit_byte (mb, CEE_BRFALSE);
2792 mono_mb_emit_i4 (mb, 0);
2794 /* allocate space for the native struct and store the address */
2795 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2796 mono_mb_emit_byte (mb, CEE_PREFIX1);
2797 mono_mb_emit_byte (mb, CEE_LOCALLOC);
2798 mono_mb_emit_stloc (mb, tmp_locals [i]);
2800 /* set the src_ptr */
2801 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2802 mono_mb_emit_icon (mb, sizeof (MonoObject));
2803 mono_mb_emit_byte (mb, CEE_ADD);
2804 mono_mb_emit_byte (mb, CEE_STLOC_0);
2807 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2808 mono_mb_emit_byte (mb, CEE_STLOC_1);
2810 /* emit valuetype conversion code */
2811 emit_struct_conv (mb, klass, FALSE);
2813 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2817 case MONO_TYPE_ARRAY:
2818 case MONO_TYPE_SZARRAY:
2822 klass = mono_class_from_mono_type (t);
2824 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2825 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2827 mono_mb_emit_ldarg (mb, argnum);
2828 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2829 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2830 if (klass->element_class == mono_defaults.string_class)
2831 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STRARRAY_STRLPARRAY);
2833 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_ARRAY_LPARRAY);
2834 mono_mb_emit_stloc (mb, tmp_locals [i]);
2839 /* push all arguments */
2842 mono_mb_emit_byte (mb, CEE_LDARG_0);
2844 for (i = 0; i < sig->param_count; i++) {
2845 MonoType *t = sig->params [i];
2847 argnum = i + sig->hasthis;
2850 case MONO_TYPE_BOOLEAN:
2852 g_warning ("byref boolean marshalling not inplemented");
2853 mono_mb_emit_ldarg (mb, argnum);
2868 mono_mb_emit_ldarg (mb, argnum);
2870 case MONO_TYPE_VALUETYPE:
2871 klass = sig->params [i]->data.klass;
2872 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2873 klass->blittable || klass->enumtype) {
2874 mono_mb_emit_ldarg (mb, argnum);
2877 g_assert (tmp_locals [i]);
2878 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2880 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2881 mono_mb_emit_byte (mb, CEE_MONO_LDNATIVEOBJ);
2882 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2885 case MONO_TYPE_STRING:
2886 case MONO_TYPE_CLASS:
2887 case MONO_TYPE_OBJECT:
2888 g_assert (tmp_locals [i]);
2890 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2892 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2894 case MONO_TYPE_CHAR:
2895 /* fixme: dont know how to marshal that. We cant simply
2896 * convert it to a one byte UTF8 character, because an
2897 * unicode character may need more that one byte in UTF8 */
2898 mono_mb_emit_ldarg (mb, argnum);
2900 case MONO_TYPE_ARRAY:
2901 case MONO_TYPE_SZARRAY:
2903 mono_mb_emit_ldarg (mb, argnum);
2905 g_assert (tmp_locals [i]);
2906 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2909 case MONO_TYPE_TYPEDBYREF:
2910 case MONO_TYPE_FNPTR:
2912 g_warning ("type 0x%02x unknown", t->type);
2913 g_assert_not_reached ();
2917 /* call the native method */
2918 mono_mb_emit_native_call (mb, csig, method->addr);
2920 /* convert the result */
2921 if (!sig->ret->byref) {
2922 MonoMarshalSpec *spec = mspecs [0];
2923 type = sig->ret->type;
2925 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
2928 MonoMethod *marshal_native_to_managed;
2929 MonoMethod *get_instance;
2931 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
2932 g_assert (mtype != NULL);
2933 mklass = mono_class_from_mono_type (mtype);
2934 g_assert (mklass != NULL);
2936 marshal_native_to_managed = mono_find_method_by_name (mklass, "MarshalNativeToManaged", 1);
2937 g_assert (marshal_native_to_managed);
2938 get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
2939 g_assert (get_instance);
2942 case MONO_TYPE_CLASS:
2943 case MONO_TYPE_OBJECT:
2944 case MONO_TYPE_STRING:
2945 case MONO_TYPE_ARRAY:
2946 case MONO_TYPE_SZARRAY:
2947 mono_mb_emit_byte (mb, CEE_STLOC_3);
2949 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
2951 mono_mb_emit_byte (mb, CEE_CALL);
2952 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
2954 mono_mb_emit_byte (mb, CEE_LDLOC_3);
2956 mono_mb_emit_byte (mb, CEE_CALLVIRT);
2957 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_native_to_managed));
2959 mono_mb_emit_byte (mb, CEE_STLOC_3);
2962 g_warning ("custom marshalling of type %x is currently not supported", type);
2963 g_assert_not_reached ();
2970 case MONO_TYPE_VOID:
2985 /* no conversions necessary */
2986 mono_mb_emit_byte (mb, CEE_STLOC_3);
2988 case MONO_TYPE_BOOLEAN:
2989 /* maybe we need to make sure that it fits within 8 bits */
2990 mono_mb_emit_byte (mb, CEE_STLOC_3);
2992 case MONO_TYPE_VALUETYPE:
2993 klass = sig->ret->data.klass;
2994 if (klass->enumtype) {
2995 type = sig->ret->data.klass->enum_basetype->type;
2999 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3001 mono_mb_emit_byte (mb, CEE_STLOC_3);
3004 /* load pointer to returned value type */
3005 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3006 mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
3007 /* store the address of the source into local variable 0 */
3008 mono_mb_emit_byte (mb, CEE_STLOC_0);
3010 mono_mb_emit_ldloc_addr (mb, 3);
3011 mono_mb_emit_byte (mb, CEE_STLOC_1);
3013 /* emit valuetype conversion code */
3014 emit_struct_conv (mb, sig->ret->data.klass, TRUE);
3016 case MONO_TYPE_STRING:
3017 #ifdef GTK_SHARP_FIXED
3018 mono_mb_emit_byte (mb, CEE_STLOC_0);
3019 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3022 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3023 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3025 switch (spec->native) {
3026 case MONO_NATIVE_LPWSTR:
3027 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPWSTR_STR);
3030 g_warning ("marshalling conversion not implemented");
3031 g_assert_not_reached ();
3034 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
3036 mono_mb_emit_byte (mb, CEE_STLOC_3);
3038 #ifdef GTK_SHARP_FIXED
3039 /* free the string */
3040 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3041 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3042 mono_mb_emit_byte (mb, CEE_MONO_FREE);
3045 case MONO_TYPE_CLASS:
3046 case MONO_TYPE_OBJECT:
3047 klass = sig->ret->data.klass;
3050 mono_mb_emit_byte (mb, CEE_STLOC_0);
3052 mono_mb_emit_byte (mb, CEE_LDNULL);
3053 mono_mb_emit_byte (mb, CEE_STLOC_3);
3056 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3057 mono_mb_emit_byte (mb, CEE_BRFALSE);
3059 mono_mb_emit_i4 (mb, 0);
3061 /* allocate result object */
3063 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3064 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
3065 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3066 mono_mb_emit_byte (mb, CEE_STLOC_3);
3070 mono_mb_emit_byte (mb, CEE_LDLOC_3);
3071 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3072 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
3073 mono_mb_emit_icon (mb, sizeof (MonoObject));
3074 mono_mb_emit_byte (mb, CEE_ADD);
3075 mono_mb_emit_byte (mb, CEE_STLOC_1);
3077 /* emit conversion code */
3078 emit_struct_conv (mb, klass, TRUE);
3080 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3082 case MONO_TYPE_ARRAY:
3083 case MONO_TYPE_SZARRAY:
3084 /* fixme: we need conversions here */
3085 mono_mb_emit_byte (mb, CEE_STLOC_3);
3087 case MONO_TYPE_CHAR:
3088 /* fixme: we need conversions here */
3089 mono_mb_emit_byte (mb, CEE_STLOC_3);
3091 case MONO_TYPE_TYPEDBYREF:
3092 case MONO_TYPE_FNPTR:
3094 g_warning ("return type 0x%02x unknown", sig->ret->type);
3095 g_assert_not_reached ();
3099 mono_mb_emit_byte (mb, CEE_STLOC_3);
3102 /* we need to convert byref arguments back and free string arrays */
3103 for (i = 0; i < sig->param_count; i++) {
3104 MonoType *t = sig->params [i];
3106 argnum = i + sig->hasthis;
3109 case MONO_TYPE_STRING:
3110 if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT)) {
3111 mono_mb_emit_ldarg (mb, argnum);
3112 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3113 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3114 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3115 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
3116 mono_mb_emit_byte (mb, CEE_STIND_I);
3118 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3119 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3120 mono_mb_emit_byte (mb, CEE_MONO_FREE);
3123 case MONO_TYPE_CLASS:
3124 case MONO_TYPE_OBJECT:
3125 if (t->data.klass == mono_defaults.stringbuilder_class) {
3126 g_assert (!t->byref);
3127 mono_mb_emit_ldarg (mb, argnum);
3128 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3129 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3130 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
3131 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_SB);
3132 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3133 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3134 mono_mb_emit_byte (mb, CEE_MONO_FREE);
3138 if (!(t->byref || (t->attrs & PARAM_ATTRIBUTE_OUT)))
3141 if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT)) {
3142 /* allocate a new object new object */
3143 mono_mb_emit_ldarg (mb, argnum);
3144 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3145 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
3146 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3147 mono_mb_emit_byte (mb, CEE_STIND_I);
3150 /* dst = *argument */
3151 mono_mb_emit_ldarg (mb, argnum);
3154 mono_mb_emit_byte (mb, CEE_LDIND_I);
3156 mono_mb_emit_byte (mb, CEE_STLOC_1);
3158 mono_mb_emit_byte (mb, CEE_LDLOC_1);
3159 mono_mb_emit_byte (mb, CEE_BRFALSE);
3161 mono_mb_emit_i4 (mb, 0);
3163 mono_mb_emit_byte (mb, CEE_LDLOC_1);
3164 mono_mb_emit_icon (mb, sizeof (MonoObject));
3165 mono_mb_emit_byte (mb, CEE_ADD);
3166 mono_mb_emit_byte (mb, CEE_STLOC_1);
3168 /* src = tmp_locals [i] */
3169 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3170 mono_mb_emit_byte (mb, CEE_STLOC_0);
3172 /* emit valuetype conversion code */
3173 emit_struct_conv (mb, klass, TRUE);
3175 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3177 case MONO_TYPE_VALUETYPE:
3181 klass = t->data.klass;
3182 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3183 klass->blittable || klass->enumtype)
3186 /* dst = argument */
3187 mono_mb_emit_ldarg (mb, argnum);
3188 mono_mb_emit_byte (mb, CEE_STLOC_1);
3190 mono_mb_emit_byte (mb, CEE_LDLOC_1);
3191 mono_mb_emit_byte (mb, CEE_BRFALSE);
3193 mono_mb_emit_i4 (mb, 0);
3195 /* src = tmp_locals [i] */
3196 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3197 mono_mb_emit_byte (mb, CEE_STLOC_0);
3199 /* emit valuetype conversion code */
3200 emit_struct_conv (mb, klass, TRUE);
3202 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3204 case MONO_TYPE_SZARRAY:
3208 klass = mono_class_from_mono_type (t);
3210 if (klass->element_class == mono_defaults.string_class) {
3211 g_assert (tmp_locals [i]);
3213 mono_mb_emit_ldarg (mb, argnum);
3214 mono_mb_emit_byte (mb, CEE_BRFALSE);
3216 mono_mb_emit_i4 (mb, 0);
3218 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3219 mono_mb_emit_ldarg (mb, argnum);
3220 mono_mb_emit_byte (mb, CEE_LDLEN);
3221 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3222 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
3223 mono_mb_emit_byte (mb, MONO_MARSHAL_FREE_ARRAY);
3225 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3233 if (!MONO_TYPE_IS_VOID(sig->ret))
3234 mono_mb_emit_byte (mb, CEE_LDLOC_3);
3236 mono_mb_emit_byte (mb, CEE_RET);
3238 csig = g_memdup (sig, sigsize);
3240 res = mono_mb_create_method (mb, csig, csig->param_count + 16);
3243 g_hash_table_insert (cache, method, res);
3245 for (i = sig->param_count; i >= 0; i--)
3246 g_free (mspecs [i]);
3253 * generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld)
3256 mono_marshal_get_struct_to_ptr (MonoClass *klass)
3258 MonoMethodBuilder *mb;
3259 static MonoMethod *stoptr = NULL;
3262 g_assert (klass != NULL);
3264 if (klass->str_to_ptr)
3265 return klass->str_to_ptr;
3268 stoptr = mono_find_method_by_name (mono_defaults.marshal_class, "StructureToPtr", 3);
3271 mb = mono_mb_new (klass, stoptr->name, MONO_WRAPPER_UNKNOWN);
3273 if (klass->blittable) {
3274 mono_mb_emit_byte (mb, CEE_LDARG_1);
3275 mono_mb_emit_byte (mb, CEE_LDARG_0);
3276 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3277 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
3278 mono_mb_emit_byte (mb, CEE_PREFIX1);
3279 mono_mb_emit_byte (mb, CEE_CPBLK);
3282 /* allocate local 0 (pointer) src_ptr */
3283 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3284 /* allocate local 1 (pointer) dst_ptr */
3285 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3286 /* allocate local 2 (boolean) delete_old */
3287 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
3288 mono_mb_emit_byte (mb, CEE_LDARG_2);
3289 mono_mb_emit_byte (mb, CEE_STLOC_2);
3291 /* initialize src_ptr to point to the start of object data */
3292 mono_mb_emit_byte (mb, CEE_LDARG_0);
3293 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3294 mono_mb_emit_byte (mb, CEE_STLOC_0);
3296 /* initialize dst_ptr */
3297 mono_mb_emit_byte (mb, CEE_LDARG_1);
3298 mono_mb_emit_byte (mb, CEE_STLOC_1);
3300 emit_struct_conv (mb, klass, FALSE);
3303 mono_mb_emit_byte (mb, CEE_RET);
3305 res = mono_mb_create_method (mb, stoptr->signature, 0);
3308 klass->str_to_ptr = res;
3313 * generates IL code for PtrToStructure (IntPtr src, object structure)
3316 mono_marshal_get_ptr_to_struct (MonoClass *klass)
3318 MonoMethodBuilder *mb;
3319 static MonoMethod *ptostr = NULL;
3322 g_assert (klass != NULL);
3324 if (klass->ptr_to_str)
3325 return klass->ptr_to_str;
3328 ptostr = mono_find_method_by_name (mono_defaults.marshal_class, "PtrToStructure", 2);
3331 mb = mono_mb_new (klass, ptostr->name, MONO_WRAPPER_UNKNOWN);
3333 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable) {
3334 mono_mb_emit_byte (mb, CEE_LDARG_1);
3335 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3336 mono_mb_emit_byte (mb, CEE_LDARG_0);
3337 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
3338 mono_mb_emit_byte (mb, CEE_PREFIX1);
3339 mono_mb_emit_byte (mb, CEE_CPBLK);
3342 /* allocate local 0 (pointer) src_ptr */
3343 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3344 /* allocate local 1 (pointer) dst_ptr */
3345 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3347 /* initialize src_ptr to point to the start of object data */
3348 mono_mb_emit_byte (mb, CEE_LDARG_0);
3349 mono_mb_emit_byte (mb, CEE_STLOC_0);
3351 /* initialize dst_ptr */
3352 mono_mb_emit_byte (mb, CEE_LDARG_1);
3353 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3354 mono_mb_emit_byte (mb, CEE_STLOC_1);
3356 emit_struct_conv (mb, klass, TRUE);
3359 mono_mb_emit_byte (mb, CEE_RET);
3361 res = mono_mb_create_method (mb, ptostr->signature, 0);
3364 klass->ptr_to_str = res;
3368 static MonoReflectionType *
3369 type_from_handle (MonoType *handle)
3371 MonoDomain *domain = mono_domain_get ();
3372 MonoClass *klass = mono_class_from_mono_type (handle);
3374 MONO_ARCH_SAVE_REGS;
3376 mono_class_init (klass);
3377 return mono_type_get_object (domain, handle);
3381 * generates IL code for the synchronized wrapper: the generated method
3382 * calls METHOD while locking 'this' or the parent type.
3385 mono_marshal_get_synchronized_wrapper (MonoMethod *method)
3387 static MonoMethodSignature *from_handle_sig = NULL;
3388 static MonoMethod *enter_method, *exit_method;
3389 MonoMethodSignature *sig;
3390 MonoExceptionClause *clause;
3391 MonoMethodHeader *header;
3392 MonoMethodBuilder *mb;
3395 int i, pos, this_local, ret_local;
3399 if (method->wrapper_type == MONO_WRAPPER_SYNCHRONIZED)
3402 cache = method->klass->image->synchronized_cache;
3403 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
3406 sig = method->signature;
3408 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_SYNCHRONIZED);
3411 if (!MONO_TYPE_IS_VOID (sig->ret))
3412 ret_local = mono_mb_add_local (mb, sig->ret);
3415 this_local = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
3417 clause = g_new0 (MonoExceptionClause, 1);
3418 clause->flags = MONO_EXCEPTION_CLAUSE_FINALLY;
3420 if (!enter_method) {
3421 MonoMethodDesc *desc;
3423 desc = mono_method_desc_new ("Monitor:Enter", FALSE);
3424 enter_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
3425 g_assert (enter_method);
3426 mono_method_desc_free (desc);
3427 desc = mono_method_desc_new ("Monitor:Exit", FALSE);
3428 exit_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
3429 g_assert (exit_method);
3430 mono_method_desc_free (desc);
3433 * GetTypeFromHandle isn't called as a managed method because it has
3434 * a funky calling sequence, e.g. ldtoken+GetTypeFromHandle gets
3435 * transformed into something else by the JIT.
3437 from_handle_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
3438 from_handle_sig->params [0] = &mono_defaults.object_class->byval_arg;
3439 from_handle_sig->ret = &mono_defaults.object_class->byval_arg;
3442 /* Push this or the type object */
3443 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3444 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3445 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
3446 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, &method->klass->byval_arg));
3447 mono_mb_emit_native_call (mb, from_handle_sig, type_from_handle);
3450 mono_mb_emit_ldarg (mb, 0);
3451 mono_mb_emit_stloc (mb, this_local);
3453 /* Call Monitor::Enter() */
3454 mono_mb_emit_ldloc (mb, this_local);
3455 mono_mb_emit_managed_call (mb, enter_method, NULL);
3457 clause->try_offset = mb->pos;
3459 /* Call the method */
3461 mono_mb_emit_ldarg (mb, 0);
3462 for (i = 0; i < sig->param_count; i++)
3463 mono_mb_emit_ldarg (mb, i + (sig->hasthis == TRUE));
3464 mono_mb_emit_managed_call (mb, method, method->signature);
3465 if (!MONO_TYPE_IS_VOID (sig->ret))
3466 mono_mb_emit_stloc (mb, ret_local);
3468 mono_mb_emit_byte (mb, CEE_LEAVE);
3470 mono_mb_emit_i4 (mb, 0);
3472 clause->try_len = mb->pos - clause->try_offset;
3473 clause->handler_offset = mb->pos;
3475 /* Call Monitor::Exit() */
3476 mono_mb_emit_ldloc (mb, this_local);
3477 // mono_mb_emit_native_call (mb, exit_sig, mono_monitor_exit);
3478 mono_mb_emit_managed_call (mb, exit_method, NULL);
3479 mono_mb_emit_byte (mb, CEE_ENDFINALLY);
3481 clause->handler_len = mb->pos - clause->handler_offset;
3483 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3484 if (!MONO_TYPE_IS_VOID (sig->ret))
3485 mono_mb_emit_ldloc (mb, ret_local);
3486 mono_mb_emit_byte (mb, CEE_RET);
3488 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
3491 header = ((MonoMethodNormal *)res)->header;
3492 header->num_clauses = 1;
3493 header->clauses = clause;
3495 g_hash_table_insert (cache, method, res);
3500 /* FIXME: on win32 we should probably use GlobalAlloc(). */
3502 mono_marshal_alloc (gpointer size)
3504 MONO_ARCH_SAVE_REGS;
3506 return g_try_malloc ((gulong)size);
3510 mono_marshal_free (gpointer ptr)
3512 MONO_ARCH_SAVE_REGS;
3518 mono_marshal_free_array (gpointer *ptr, int size)
3525 for (i = 0; i < size; i++)
3531 mono_marshal_realloc (gpointer ptr, gpointer size)
3533 MONO_ARCH_SAVE_REGS;
3535 return g_try_realloc (ptr, (gulong)size);
3539 mono_marshal_string_array (MonoArray *array)
3547 len = mono_array_length (array);
3549 result = g_malloc (sizeof (char *) * (len + 1));
3550 for (i = 0; i < len; ++i) {
3551 MonoString *s = (MonoString *)mono_array_get (array, gpointer, i);
3552 result [i] = s ? mono_string_to_utf8 (s): NULL;
3554 /* null terminate the array */
3561 ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArray *src, gint32 start_index,
3562 gpointer dest, gint32 length)
3567 MONO_ARCH_SAVE_REGS;
3569 MONO_CHECK_ARG_NULL (src);
3570 MONO_CHECK_ARG_NULL (dest);
3572 g_assert (src->obj.vtable->klass->rank == 1);
3573 g_assert (start_index >= 0);
3574 g_assert (length >= 0);
3575 g_assert (start_index + length <= mono_array_length (src));
3577 element_size = mono_array_element_size (src->obj.vtable->klass);
3579 source_addr = mono_array_addr_with_size (src, element_size, start_index);
3581 memcpy (dest, source_addr, length * element_size);
3585 ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer src, gint32 start_index,
3586 MonoArray *dest, gint32 length)
3591 MONO_ARCH_SAVE_REGS;
3593 MONO_CHECK_ARG_NULL (src);
3594 MONO_CHECK_ARG_NULL (dest);
3596 g_assert (dest->obj.vtable->klass->rank == 1);
3597 g_assert (start_index >= 0);
3598 g_assert (length >= 0);
3599 g_assert (start_index + length <= mono_array_length (dest));
3601 element_size = mono_array_element_size (dest->obj.vtable->klass);
3603 dest_addr = mono_array_addr_with_size (dest, element_size, start_index);
3605 memcpy (dest_addr, src, length * element_size);
3609 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr, gint32 offset)
3613 MONO_ARCH_SAVE_REGS;
3615 return *(gpointer*)(p + offset);
3619 ves_icall_System_Runtime_InteropServices_Marshal_ReadByte (gpointer ptr, gint32 offset)
3623 MONO_ARCH_SAVE_REGS;
3625 return *(unsigned char*)(p + offset);
3629 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt16 (gpointer ptr, gint32 offset)
3633 MONO_ARCH_SAVE_REGS;
3635 return *(gint16*)(p + offset);
3639 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt32 (gpointer ptr, gint32 offset)
3643 MONO_ARCH_SAVE_REGS;
3645 return *(gint32*)(p + offset);
3649 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt64 (gpointer ptr, gint32 offset)
3653 MONO_ARCH_SAVE_REGS;
3655 return *(gint64*)(p + offset);
3659 ves_icall_System_Runtime_InteropServices_Marshal_WriteByte (gpointer ptr, gint32 offset, unsigned char val)
3663 MONO_ARCH_SAVE_REGS;
3665 *(unsigned char*)(p + offset) = val;
3669 ves_icall_System_Runtime_InteropServices_Marshal_WriteIntPtr (gpointer ptr, gint32 offset, gpointer val)
3673 MONO_ARCH_SAVE_REGS;
3675 *(gpointer*)(p + offset) = val;
3679 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt16 (gpointer ptr, gint32 offset, gint16 val)
3683 MONO_ARCH_SAVE_REGS;
3685 *(gint16*)(p + offset) = val;
3689 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt32 (gpointer ptr, gint32 offset, gint32 val)
3693 MONO_ARCH_SAVE_REGS;
3695 *(gint32*)(p + offset) = val;
3699 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt64 (gpointer ptr, gint32 offset, gint64 val)
3703 MONO_ARCH_SAVE_REGS;
3705 *(gint64*)(p + offset) = val;
3709 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (char *ptr)
3711 MONO_ARCH_SAVE_REGS;
3713 return mono_string_new (mono_domain_get (), ptr);
3717 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len (char *ptr, gint32 len)
3719 MONO_ARCH_SAVE_REGS;
3721 return mono_string_new_len (mono_domain_get (), ptr, len);
3725 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni (guint16 *ptr)
3727 MonoDomain *domain = mono_domain_get ();
3731 MONO_ARCH_SAVE_REGS;
3736 return mono_string_new_utf16 (domain, ptr, len);
3740 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len (guint16 *ptr, gint32 len)
3742 MonoDomain *domain = mono_domain_get ();
3744 MONO_ARCH_SAVE_REGS;
3746 return mono_string_new_utf16 (domain, ptr, len);
3750 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR (gpointer ptr)
3752 MONO_ARCH_SAVE_REGS;
3754 g_warning ("PtrToStringBSTR not implemented");
3755 g_assert_not_reached ();
3761 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
3763 MONO_ARCH_SAVE_REGS;
3765 return (GetLastError ());
3769 ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype)
3773 MONO_ARCH_SAVE_REGS;
3775 MONO_CHECK_ARG_NULL (rtype);
3777 klass = mono_class_from_mono_type (rtype->type);
3779 return mono_class_native_size (klass, NULL);
3783 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old)
3788 MONO_ARCH_SAVE_REGS;
3790 MONO_CHECK_ARG_NULL (obj);
3791 MONO_CHECK_ARG_NULL (dst);
3793 method = mono_marshal_get_struct_to_ptr (obj->vtable->klass);
3797 pa [2] = &delete_old;
3799 mono_runtime_invoke (method, NULL, pa, NULL);
3803 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, MonoObject *dst)
3808 MONO_ARCH_SAVE_REGS;
3810 MONO_CHECK_ARG_NULL (src);
3811 MONO_CHECK_ARG_NULL (dst);
3813 method = mono_marshal_get_ptr_to_struct (dst->vtable->klass);
3818 mono_runtime_invoke (method, NULL, pa, NULL);
3822 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer src, MonoReflectionType *type)
3824 MonoDomain *domain = mono_domain_get ();
3827 MONO_ARCH_SAVE_REGS;
3829 MONO_CHECK_ARG_NULL (src);
3830 MONO_CHECK_ARG_NULL (type);
3832 res = mono_object_new (domain, mono_class_from_mono_type (type->type));
3834 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (src, res);
3840 ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *type, MonoString *field_name)
3842 MonoMarshalType *info;
3845 int i, match_index = -1;
3847 MONO_ARCH_SAVE_REGS;
3849 MONO_CHECK_ARG_NULL (type);
3850 MONO_CHECK_ARG_NULL (field_name);
3852 fname = mono_string_to_utf8 (field_name);
3853 klass = mono_class_from_mono_type (type->type);
3855 while(klass && match_index == -1) {
3856 for (i = 0; i < klass->field.count; ++i) {
3857 if (*fname == *klass->fields [i].name && strcmp (fname, klass->fields [i].name) == 0) {
3863 if(match_index == -1)
3864 klass = klass->parent;
3869 if(match_index == -1) {
3873 /* Get back original class instance */
3874 klass = mono_class_from_mono_type (type->type);
3876 tmp = g_strdup_printf ("Field passed in is not a marshaled member of the type %s", klass->name);
3877 exc = mono_get_exception_argument ("fieldName", tmp);
3880 mono_raise_exception ((MonoException*)exc);
3883 info = mono_marshal_load_type_info (klass);
3884 return info->fields [match_index].offset;
3888 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString *string)
3890 MONO_ARCH_SAVE_REGS;
3892 return mono_string_to_utf8 (string);
3896 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni (MonoString *string)
3898 MONO_ARCH_SAVE_REGS;
3900 return g_memdup (mono_string_chars (string), mono_string_length (string)*2);
3904 mono_struct_delete_old (MonoClass *klass, char *ptr)
3906 MonoMarshalType *info;
3909 info = mono_marshal_load_type_info (klass);
3911 for (i = 0; i < info->num_fields; i++) {
3912 MonoMarshalNative ntype;
3913 MonoMarshalConv conv;
3914 MonoType *ftype = info->fields [i].field->type;
3917 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
3920 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE,
3921 klass->unicode, &conv);
3923 cpos = ptr + info->fields [i].offset;
3926 case MONO_MARSHAL_CONV_NONE:
3927 if (MONO_TYPE_ISSTRUCT (ftype)) {
3928 mono_struct_delete_old (ftype->data.klass, cpos);
3932 case MONO_MARSHAL_CONV_STR_LPWSTR:
3933 case MONO_MARSHAL_CONV_STR_LPSTR:
3934 case MONO_MARSHAL_CONV_STR_LPTSTR:
3935 case MONO_MARSHAL_CONV_STR_BSTR:
3936 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
3937 case MONO_MARSHAL_CONV_STR_TBSTR:
3938 g_free (*(gpointer *)cpos);
3947 ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure (gpointer src, MonoReflectionType *type)
3951 MONO_ARCH_SAVE_REGS;
3953 MONO_CHECK_ARG_NULL (src);
3954 MONO_CHECK_ARG_NULL (type);
3956 klass = mono_class_from_mono_type (type->type);
3958 mono_struct_delete_old (klass, (char *)src);
3962 mono_marshal_load_type_info (MonoClass* klass)
3964 int i, j, count = 0, native_size = 0;
3965 MonoMarshalType *info;
3968 g_assert (klass != NULL);
3970 if (klass->marshal_info)
3971 return klass->marshal_info;
3974 mono_class_init (klass);
3976 for (i = 0; i < klass->field.count; ++i) {
3977 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
3982 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
3984 klass->marshal_info = info = g_malloc0 (sizeof (MonoMarshalType) + sizeof (MonoMarshalField) * count);
3985 info->num_fields = count;
3987 /* Try to find a size for this type in metadata */
3988 mono_metadata_packing_from_typedef (klass->image, klass->type_token, NULL, &native_size);
3990 if (klass->parent) {
3991 int parent_size = mono_class_native_size (klass->parent, NULL);
3993 /* Add parent size to real size */
3994 native_size += parent_size;
3995 info->native_size = parent_size;
3998 for (j = i = 0; i < klass->field.count; ++i) {
4001 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
4004 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL)
4005 mono_metadata_field_info (klass->image, klass->field.first + i,
4006 NULL, NULL, &info->fields [j].mspec);
4008 info->fields [j].field = &klass->fields [i];
4011 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
4012 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
4013 size = mono_marshal_type_size (klass->fields [i].type, info->fields [j].mspec,
4014 &align, TRUE, klass->unicode);
4015 align = klass->packing_size ? MIN (klass->packing_size, align): align;
4016 info->fields [j].offset = info->native_size;
4017 info->fields [j].offset += align - 1;
4018 info->fields [j].offset &= ~(align - 1);
4019 info->native_size = info->fields [j].offset + size;
4021 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
4023 info->fields [j].offset = klass->fields [i].offset - sizeof (MonoObject);
4024 info->native_size = klass->instance_size - sizeof (MonoObject);
4030 if(layout != TYPE_ATTRIBUTE_AUTO_LAYOUT) {
4031 info->native_size = MAX (native_size, info->native_size);
4034 if (info->native_size & (klass->min_align - 1)) {
4035 info->native_size += klass->min_align - 1;
4036 info->native_size &= ~(klass->min_align - 1);
4039 return klass->marshal_info;
4043 * mono_class_native_size:
4046 * Returns: the native size of an object instance (when marshaled
4047 * to unmanaged code)
4050 mono_class_native_size (MonoClass *klass, guint32 *align)
4053 if (!klass->marshal_info)
4054 mono_marshal_load_type_info (klass);
4057 *align = klass->min_align;
4059 return klass->marshal_info->native_size;
4063 * mono_type_native_stack_size:
4064 * @t: the type to return the size it uses on the stack
4066 * Returns: the number of bytes required to hold an instance of this
4067 * type on the native stack
4070 mono_type_native_stack_size (MonoType *t, gint *align)
4074 g_assert (t != NULL);
4085 case MONO_TYPE_BOOLEAN:
4086 case MONO_TYPE_CHAR:
4095 case MONO_TYPE_STRING:
4096 case MONO_TYPE_OBJECT:
4097 case MONO_TYPE_CLASS:
4098 case MONO_TYPE_SZARRAY:
4100 case MONO_TYPE_FNPTR:
4101 case MONO_TYPE_ARRAY:
4102 case MONO_TYPE_TYPEDBYREF:
4113 case MONO_TYPE_VALUETYPE: {
4116 if (t->data.klass->enumtype)
4117 return mono_type_native_stack_size (t->data.klass->enum_basetype, align);
4119 size = mono_class_native_size (t->data.klass, align);
4120 *align = *align + 3;
4130 g_error ("type 0x%02x unknown", t->type);
4136 mono_marshal_type_size (MonoType *type, MonoMarshalSpec *mspec, gint32 *align,
4137 gboolean as_field, gboolean unicode)
4139 MonoMarshalNative native_type = mono_type_to_unmanaged (type, mspec, as_field, unicode, NULL);
4142 switch (native_type) {
4143 case MONO_NATIVE_BOOLEAN:
4146 case MONO_NATIVE_I1:
4147 case MONO_NATIVE_U1:
4150 case MONO_NATIVE_I2:
4151 case MONO_NATIVE_U2:
4154 case MONO_NATIVE_I4:
4155 case MONO_NATIVE_U4:
4156 case MONO_NATIVE_ERROR:
4159 case MONO_NATIVE_I8:
4160 case MONO_NATIVE_U8:
4163 case MONO_NATIVE_R4:
4166 case MONO_NATIVE_R8:
4169 case MONO_NATIVE_INT:
4170 case MONO_NATIVE_UINT:
4171 case MONO_NATIVE_LPSTR:
4172 case MONO_NATIVE_LPWSTR:
4173 case MONO_NATIVE_LPTSTR:
4174 case MONO_NATIVE_BSTR:
4175 case MONO_NATIVE_ANSIBSTR:
4176 case MONO_NATIVE_TBSTR:
4177 case MONO_NATIVE_LPARRAY:
4178 case MONO_NATIVE_SAFEARRAY:
4179 case MONO_NATIVE_IUNKNOWN:
4180 case MONO_NATIVE_IDISPATCH:
4181 case MONO_NATIVE_INTERFACE:
4182 case MONO_NATIVE_ASANY:
4183 case MONO_NATIVE_VARIANTBOOL:
4184 case MONO_NATIVE_FUNC:
4185 case MONO_NATIVE_LPSTRUCT:
4187 return sizeof (gpointer);
4188 case MONO_NATIVE_STRUCT:
4189 klass = mono_class_from_mono_type (type);
4190 return mono_class_native_size (klass, align);
4191 case MONO_NATIVE_BYVALTSTR: {
4192 int esize = unicode ? 2: 1;
4195 return mspec->data.array_data.num_elem * esize;
4197 case MONO_NATIVE_BYVALARRAY: {
4199 klass = mono_class_from_mono_type (type);
4200 esize = mono_class_native_size (klass->element_class, align);
4202 return mspec->data.array_data.num_elem * esize;
4204 case MONO_NATIVE_CUSTOM:
4205 g_assert_not_reached ();
4207 case MONO_NATIVE_CURRENCY:
4208 case MONO_NATIVE_VBBYREFSTR:
4210 g_error ("native type %02x not implemented", native_type);
4213 g_assert_not_reached ();