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 if (delegate->target && mono_object_class (delegate->target) == mono_defaults.transparent_proxy_class) {
977 MonoTransparentProxy* tp = (MonoTransparentProxy *)delegate->target;
978 if (!tp->klass->contextbound || tp->rp->context != (MonoObject *) mono_context_get ()) {
980 // If the target is a proxy, make a direct call. Is proxy's work
981 // to make the call asynchronous.
983 MonoAsyncResult *ares;
986 method = delegate->method_info->method;
988 msg = mono_method_call_message_new (method, params, NULL, &async_callback, &state);
989 HANDLE handle = CreateEvent (NULL, TRUE, FALSE, NULL);
990 ares = mono_async_result_new (mono_domain_get (), handle, state, handle);
991 ares->async_delegate = (MonoObject *)async_callback;
992 msg->async_result = ares;
994 mono_remoting_invoke ((MonoObject *)tp->rp, msg, &exc, &out_args);
999 klass = delegate->object.vtable->klass;
1001 method = mono_get_delegate_invoke (klass);
1002 for (i = 0; i < klass->method.count; ++i) {
1003 if (klass->methods [i]->name[0] == 'B' &&
1004 !strcmp ("BeginInvoke", klass->methods [i]->name)) {
1005 method = klass->methods [i];
1010 g_assert (method != NULL);
1012 im = mono_get_delegate_invoke (method->klass);
1013 msg = mono_method_call_message_new (method, params, im, &async_callback, &state);
1015 return mono_thread_pool_add ((MonoObject *)delegate, msg, async_callback, state);
1019 mono_mb_emit_save_args (MonoMethodBuilder *mb, MonoMethodSignature *sig, gboolean save_this)
1021 int i, params_var, tmp_var;
1023 /* allocate local (pointer) *params[] */
1024 params_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1025 /* allocate local (pointer) tmp */
1026 tmp_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1028 /* alloate space on stack to store an array of pointers to the arguments */
1029 mono_mb_emit_icon (mb, sizeof (gpointer) * (sig->param_count + 1));
1030 mono_mb_emit_byte (mb, CEE_PREFIX1);
1031 mono_mb_emit_byte (mb, CEE_LOCALLOC);
1032 mono_mb_emit_stloc (mb, params_var);
1035 mono_mb_emit_ldloc (mb, params_var);
1036 mono_mb_emit_stloc (mb, tmp_var);
1038 if (save_this && sig->hasthis) {
1039 mono_mb_emit_ldloc (mb, tmp_var);
1040 mono_mb_emit_ldarg_addr (mb, 0);
1041 mono_mb_emit_byte (mb, CEE_STIND_I);
1042 /* tmp = tmp + sizeof (gpointer) */
1043 if (sig->param_count)
1044 mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
1048 for (i = 0; i < sig->param_count; i++) {
1049 mono_mb_emit_ldloc (mb, tmp_var);
1050 mono_mb_emit_ldarg_addr (mb, i + sig->hasthis);
1051 mono_mb_emit_byte (mb, CEE_STIND_I);
1052 /* tmp = tmp + sizeof (gpointer) */
1053 if (i < (sig->param_count - 1))
1054 mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
1061 mono_signature_to_name (MonoMethodSignature *sig, const char *prefix)
1065 GString *res = g_string_new ("");
1068 g_string_append (res, prefix);
1069 g_string_append_c (res, '_');
1072 mono_type_get_desc (res, sig->ret, FALSE);
1074 for (i = 0; i < sig->param_count; ++i) {
1075 g_string_append_c (res, '_');
1076 mono_type_get_desc (res, sig->params [i], FALSE);
1079 g_string_free (res, FALSE);
1084 mono_marshal_get_delegate_begin_invoke (MonoMethod *method)
1086 MonoMethodSignature *sig;
1087 static MonoMethodSignature *csig = NULL;
1088 MonoMethodBuilder *mb;
1094 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1095 !strcmp (method->name, "BeginInvoke"));
1097 sig = method->signature;
1099 cache = method->klass->image->delegate_begin_invoke_cache;
1100 if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1103 g_assert (sig->hasthis);
1106 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1107 csig = g_malloc0 (sigsize);
1109 /* MonoAsyncResult * begin_invoke (MonoDelegate *delegate, gpointer params[]) */
1110 csig->param_count = 2;
1111 csig->ret = &mono_defaults.object_class->byval_arg;
1112 csig->params [0] = &mono_defaults.object_class->byval_arg;
1113 csig->params [1] = &mono_defaults.int_class->byval_arg;
1116 name = mono_signature_to_name (sig, "begin_invoke");
1117 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_BEGIN_INVOKE);
1120 mb->method->save_lmf = 1;
1122 params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1124 mono_mb_emit_ldarg (mb, 0);
1125 mono_mb_emit_ldloc (mb, params_var);
1126 mono_mb_emit_native_call (mb, csig, mono_delegate_begin_invoke);
1127 mono_mb_emit_byte (mb, CEE_RET);
1129 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1131 g_hash_table_insert (cache, sig, res);
1136 mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params)
1138 MonoDomain *domain = mono_domain_get ();
1139 MonoAsyncResult *ares;
1140 MonoMethod *method = NULL;
1141 MonoMethodSignature *sig;
1142 MonoMethodMessage *msg;
1143 MonoObject *res, *exc;
1144 MonoArray *out_args;
1148 g_assert (delegate);
1150 if (!delegate->method_info || !delegate->method_info->method)
1151 g_assert_not_reached ();
1153 klass = delegate->object.vtable->klass;
1155 for (i = 0; i < klass->method.count; ++i) {
1156 if (klass->methods [i]->name[0] == 'E' &&
1157 !strcmp ("EndInvoke", klass->methods [i]->name)) {
1158 method = klass->methods [i];
1163 g_assert (method != NULL);
1165 sig = method->signature;
1167 msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1169 ares = mono_array_get (msg->args, gpointer, sig->param_count - 1);
1172 if (delegate->target && mono_object_class (delegate->target) == mono_defaults.transparent_proxy_class) {
1173 /* wait until we are really finished */
1174 WaitForSingleObject ((HANDLE)ares->data, INFINITE);
1175 out_args = ares->remoting_args;
1176 res = ares->remoting_rval;
1177 exc = ares->remoting_exc;
1180 res = mono_thread_pool_finish (ares, &out_args, &exc);
1183 char *strace = mono_string_to_utf8 (((MonoException*)exc)->stack_trace);
1185 tmp = g_strdup_printf ("%s\nException Rethrown at:\n", strace);
1187 ((MonoException*)exc)->stack_trace = mono_string_new (domain, tmp);
1189 mono_raise_exception ((MonoException*)exc);
1192 mono_method_return_message_restore (method, params, out_args);
1197 mono_mb_emit_restore_result (MonoMethodBuilder *mb, MonoType *return_type)
1199 if (return_type->byref)
1200 return_type = &mono_defaults.int_class->byval_arg;
1201 else if (return_type->type == MONO_TYPE_VALUETYPE && return_type->data.klass->enumtype)
1202 return_type = return_type->data.klass->enum_basetype;
1204 switch (return_type->type) {
1205 case MONO_TYPE_VOID:
1206 g_assert_not_reached ();
1209 case MONO_TYPE_STRING:
1210 case MONO_TYPE_CLASS:
1211 case MONO_TYPE_OBJECT:
1212 case MONO_TYPE_ARRAY:
1213 case MONO_TYPE_SZARRAY:
1217 case MONO_TYPE_BOOLEAN:
1218 mono_mb_emit_byte (mb, CEE_UNBOX);
1219 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1220 mono_mb_emit_byte (mb, CEE_LDIND_U1);
1223 mono_mb_emit_byte (mb, CEE_UNBOX);
1224 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1225 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1228 case MONO_TYPE_CHAR:
1229 mono_mb_emit_byte (mb, CEE_UNBOX);
1230 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1231 mono_mb_emit_byte (mb, CEE_LDIND_U2);
1234 mono_mb_emit_byte (mb, CEE_UNBOX);
1235 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1236 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1240 mono_mb_emit_byte (mb, CEE_UNBOX);
1241 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1242 mono_mb_emit_byte (mb, CEE_LDIND_I);
1245 mono_mb_emit_byte (mb, CEE_UNBOX);
1246 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1247 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1250 mono_mb_emit_byte (mb, CEE_UNBOX);
1251 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1252 mono_mb_emit_byte (mb, CEE_LDIND_U4);
1256 mono_mb_emit_byte (mb, CEE_UNBOX);
1257 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1258 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1261 mono_mb_emit_byte (mb, CEE_UNBOX);
1262 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1263 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1266 mono_mb_emit_byte (mb, CEE_UNBOX);
1267 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1268 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1270 case MONO_TYPE_VALUETYPE: {
1272 mono_mb_emit_byte (mb, CEE_UNBOX);
1273 class = mono_mb_add_data (mb, mono_class_from_mono_type (return_type));
1274 mono_mb_emit_i4 (mb, class);
1275 mono_mb_emit_byte (mb, CEE_LDOBJ);
1276 mono_mb_emit_i4 (mb, class);
1280 g_warning ("type 0x%x not handled", return_type->type);
1281 g_assert_not_reached ();
1284 mono_mb_emit_byte (mb, CEE_RET);
1288 mono_marshal_get_delegate_end_invoke (MonoMethod *method)
1290 MonoMethodSignature *sig;
1291 static MonoMethodSignature *csig = NULL;
1292 MonoMethodBuilder *mb;
1298 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1299 !strcmp (method->name, "EndInvoke"));
1301 sig = method->signature;
1303 cache = method->klass->image->delegate_end_invoke_cache;
1304 if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1307 g_assert (sig->hasthis);
1310 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1311 csig = g_malloc0 (sigsize);
1313 /* MonoObject *end_invoke (MonoDelegate *delegate, gpointer params[]) */
1314 csig->param_count = 2;
1315 csig->ret = &mono_defaults.object_class->byval_arg;
1316 csig->params [0] = &mono_defaults.object_class->byval_arg;
1317 csig->params [1] = &mono_defaults.int_class->byval_arg;
1320 name = mono_signature_to_name (sig, "end_invoke");
1321 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_END_INVOKE);
1324 mb->method->save_lmf = 1;
1326 params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1328 mono_mb_emit_ldarg (mb, 0);
1329 mono_mb_emit_ldloc (mb, params_var);
1330 mono_mb_emit_native_call (mb, csig, mono_delegate_end_invoke);
1332 if (sig->ret->type == MONO_TYPE_VOID) {
1333 mono_mb_emit_byte (mb, CEE_POP);
1334 mono_mb_emit_byte (mb, CEE_RET);
1336 mono_mb_emit_restore_result (mb, sig->ret);
1338 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1340 g_hash_table_insert (cache, sig, res);
1346 mono_remoting_wrapper (MonoMethod *method, gpointer *params)
1348 MonoMethodMessage *msg;
1349 MonoTransparentProxy *this;
1350 MonoObject *res, *exc;
1351 MonoArray *out_args;
1353 this = *((MonoTransparentProxy **)params [0]);
1356 g_assert (((MonoObject *)this)->vtable->klass == mono_defaults.transparent_proxy_class);
1358 /* skip the this pointer */
1361 if (this->klass->contextbound && this->rp->context == (MonoObject *) mono_context_get ())
1364 MonoMethodSignature *sig = method->signature;
1365 int count = sig->param_count;
1366 gpointer* mparams = (gpointer*) alloca(count*sizeof(gpointer));
1368 for (i=0; i<count; i++) {
1369 MonoClass *class = mono_class_from_mono_type (sig->params [i]);
1370 if (class->valuetype) {
1371 if (sig->params [i]->byref)
1372 mparams[i] = *((gpointer *)params [i]);
1374 mparams[i] = params [i];
1376 mparams[i] = *((gpointer**)params [i]);
1380 return mono_runtime_invoke (method, this->rp->unwrapped_server, mparams, NULL);
1383 msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1385 res = mono_remoting_invoke ((MonoObject *)this->rp, msg, &exc, &out_args);
1388 mono_raise_exception ((MonoException *)exc);
1390 mono_method_return_message_restore (method, params, out_args);
1396 mono_marshal_get_remoting_invoke (MonoMethod *method)
1398 MonoMethodSignature *sig;
1399 static MonoMethodSignature *csig = NULL;
1400 MonoMethodBuilder *mb;
1407 if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE)
1410 sig = method->signature;
1412 /* we cant remote methods without this pointer */
1416 cache = method->klass->image->remoting_invoke_cache;
1417 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1421 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
1422 csig->params [0] = &mono_defaults.int_class->byval_arg;
1423 csig->params [1] = &mono_defaults.int_class->byval_arg;
1424 csig->ret = &mono_defaults.object_class->byval_arg;
1428 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE);
1429 mb->method->save_lmf = 1;
1431 params_var = mono_mb_emit_save_args (mb, sig, TRUE);
1433 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1434 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1435 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
1436 mono_mb_emit_ldloc (mb, params_var);
1437 mono_mb_emit_native_call (mb, csig, mono_remoting_wrapper);
1439 if (sig->ret->type == MONO_TYPE_VOID) {
1440 mono_mb_emit_byte (mb, CEE_POP);
1441 mono_mb_emit_byte (mb, CEE_RET);
1443 mono_mb_emit_restore_result (mb, sig->ret);
1446 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1448 g_hash_table_insert (cache, method, res);
1453 mono_marshal_get_remoting_invoke_with_check (MonoMethod *method)
1455 MonoMethodSignature *sig;
1456 MonoMethodBuilder *mb;
1457 MonoMethod *res, *native;
1463 if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)
1466 sig = method->signature;
1468 /* we cant remote methods without this pointer */
1469 g_assert (sig->hasthis);
1471 cache = method->klass->image->remoting_invoke_cache;
1472 if ((res = (MonoMethod *)g_hash_table_lookup (cache, (char *)method + 1)))
1475 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK);
1477 mono_mb_emit_ldarg (mb, 0);
1478 pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
1480 native = mono_marshal_get_remoting_invoke (method);
1482 for (i = 0; i <= sig->param_count; i++)
1483 mono_mb_emit_ldarg (mb, i);
1485 mono_mb_emit_managed_call (mb, native, native->signature);
1486 mono_mb_emit_byte (mb, CEE_RET);
1488 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1490 for (i = 0; i <= sig->param_count; i++)
1491 mono_mb_emit_ldarg (mb, i);
1493 mono_mb_emit_managed_call (mb, method, method->signature);
1494 mono_mb_emit_byte (mb, CEE_RET);
1496 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1498 g_hash_table_insert (cache, (char *)method + 1, res);
1503 * the returned method invokes all methods in a multicast delegate
1506 mono_marshal_get_delegate_invoke (MonoMethod *method)
1508 MonoMethodSignature *sig, *static_sig;
1510 MonoMethodBuilder *mb;
1516 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1517 !strcmp (method->name, "Invoke"));
1519 sig = method->signature;
1521 cache = method->klass->image->delegate_invoke_cache;
1522 if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1525 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1526 static_sig = g_memdup (sig, sigsize);
1527 static_sig->hasthis = 0;
1529 name = mono_signature_to_name (sig, "invoke");
1530 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_INVOKE);
1533 /* allocate local 0 (object) */
1534 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1536 g_assert (sig->hasthis);
1540 * prev.Invoke( args .. );
1541 * return this.<target>( args .. );
1544 /* get this->prev */
1545 mono_mb_emit_ldarg (mb, 0);
1546 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoMulticastDelegate, prev));
1547 mono_mb_emit_byte (mb, CEE_LDIND_I );
1548 mono_mb_emit_stloc (mb, 0);
1550 /* if prev != null */
1551 mono_mb_emit_ldloc (mb, 0);
1552 mono_mb_emit_byte (mb, CEE_BRFALSE);
1555 mono_mb_emit_i4 (mb, 0);
1558 mono_mb_emit_ldloc (mb, 0);
1559 for (i = 0; i < sig->param_count; i++)
1560 mono_mb_emit_ldarg (mb, i + 1);
1561 mono_mb_emit_managed_call (mb, method, method->signature);
1562 if (sig->ret->type != MONO_TYPE_VOID)
1563 mono_mb_emit_byte (mb, CEE_POP);
1565 /* continued or prev == null */
1566 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1568 /* get this->target */
1569 mono_mb_emit_ldarg (mb, 0);
1570 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, target));
1571 mono_mb_emit_byte (mb, CEE_LDIND_I );
1572 mono_mb_emit_stloc (mb, 0);
1574 /* if target != null */
1575 mono_mb_emit_ldloc (mb, 0);
1576 mono_mb_emit_byte (mb, CEE_BRFALSE);
1578 mono_mb_emit_i4 (mb, 0);
1580 /* then call this->method_ptr nonstatic */
1581 mono_mb_emit_ldloc (mb, 0);
1582 for (i = 0; i < sig->param_count; ++i)
1583 mono_mb_emit_ldarg (mb, i + 1);
1584 mono_mb_emit_ldarg (mb, 0);
1585 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1586 mono_mb_emit_byte (mb, CEE_LDIND_I );
1587 mono_mb_emit_byte (mb, CEE_CALLI);
1588 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
1590 mono_mb_emit_byte (mb, CEE_BR);
1592 mono_mb_emit_i4 (mb, 0);
1594 /* else [target == null] call this->method_ptr static */
1595 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1597 for (i = 0; i < sig->param_count; ++i)
1598 mono_mb_emit_ldarg (mb, i + 1);
1599 mono_mb_emit_ldarg (mb, 0);
1600 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1601 mono_mb_emit_byte (mb, CEE_LDIND_I );
1602 mono_mb_emit_byte (mb, CEE_CALLI);
1603 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, static_sig));
1606 mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
1607 mono_mb_emit_byte (mb, CEE_RET);
1609 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1612 g_hash_table_insert (cache, sig, res);
1618 * generates IL code for the runtime invoke function
1619 * MonoObject *runtime_invoke (MonoObject *this, void **params, MonoObject **exc)
1621 * we also catch exceptions if exc != null
1624 mono_marshal_get_runtime_invoke (MonoMethod *method)
1626 MonoMethodSignature *sig, *csig;
1627 MonoExceptionClause *clause;
1628 MonoMethodHeader *header;
1629 MonoMethodBuilder *mb;
1632 static MonoString *string_dummy = NULL;
1633 int i, pos, sigsize;
1637 cache = method->klass->image->runtime_invoke_cache;
1638 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1641 /* to make it work with our special string constructors */
1643 string_dummy = mono_string_new_wrapper ("dummy");
1645 sig = method->signature;
1647 sigsize = sizeof (MonoMethodSignature) + 3 * sizeof (MonoType *);
1648 csig = g_malloc0 (sigsize);
1650 csig->param_count = 3;
1651 csig->ret = &mono_defaults.object_class->byval_arg;
1652 csig->params [0] = &mono_defaults.object_class->byval_arg;
1653 csig->params [1] = &mono_defaults.int_class->byval_arg;
1654 csig->params [2] = &mono_defaults.int_class->byval_arg;
1656 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_RUNTIME_INVOKE);
1658 /* allocate local 0 (object) tmp */
1659 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1660 /* allocate local 1 (object) exc */
1661 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1663 /* cond set *exc to null */
1664 mono_mb_emit_byte (mb, CEE_LDARG_2);
1665 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
1666 mono_mb_emit_byte (mb, 3);
1667 mono_mb_emit_byte (mb, CEE_LDARG_2);
1668 mono_mb_emit_byte (mb, CEE_LDNULL);
1669 mono_mb_emit_byte (mb, CEE_STIND_I);
1672 if (method->string_ctor) {
1673 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1674 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1675 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, string_dummy));
1677 mono_mb_emit_ldarg (mb, 0);
1678 if (method->klass->valuetype) {
1679 mono_mb_emit_byte (mb, CEE_UNBOX);
1680 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method->klass));
1685 for (i = 0; i < sig->param_count; i++) {
1686 MonoType *t = sig->params [i];
1689 mono_mb_emit_ldarg (mb, 1);
1691 mono_mb_emit_icon (mb, sizeof (gpointer) * i);
1692 mono_mb_emit_byte (mb, CEE_ADD);
1694 mono_mb_emit_byte (mb, CEE_LDIND_I);
1699 type = sig->params [i]->type;
1703 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1705 case MONO_TYPE_BOOLEAN:
1707 mono_mb_emit_byte (mb, CEE_LDIND_U1);
1710 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1713 case MONO_TYPE_CHAR:
1714 mono_mb_emit_byte (mb, CEE_LDIND_U2);
1718 mono_mb_emit_byte (mb, CEE_LDIND_I);
1721 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1724 mono_mb_emit_byte (mb, CEE_LDIND_U4);
1727 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1730 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1734 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1736 case MONO_TYPE_STRING:
1737 case MONO_TYPE_CLASS:
1738 case MONO_TYPE_ARRAY:
1740 case MONO_TYPE_SZARRAY:
1741 case MONO_TYPE_OBJECT:
1744 case MONO_TYPE_VALUETYPE:
1745 if (t->data.klass->enumtype) {
1746 type = t->data.klass->enum_basetype->type;
1749 mono_mb_emit_byte (mb, CEE_LDOBJ);
1750 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, t->data.klass));
1753 g_assert_not_reached ();
1757 if (method->string_ctor) {
1758 MonoMethodSignature *strsig;
1760 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1761 strsig = g_memdup (sig, sigsize);
1762 strsig->ret = &mono_defaults.string_class->byval_arg;
1764 mono_mb_emit_managed_call (mb, method, strsig);
1766 mono_mb_emit_managed_call (mb, method, NULL);
1768 if (sig->ret->byref) {
1770 g_assert_not_reached ();
1774 switch (sig->ret->type) {
1775 case MONO_TYPE_VOID:
1776 if (!method->string_ctor)
1777 mono_mb_emit_byte (mb, CEE_LDNULL);
1779 case MONO_TYPE_BOOLEAN:
1780 case MONO_TYPE_CHAR:
1793 case MONO_TYPE_VALUETYPE:
1794 /* box value types */
1795 mono_mb_emit_byte (mb, CEE_BOX);
1796 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (sig->ret)));
1798 case MONO_TYPE_STRING:
1799 case MONO_TYPE_CLASS:
1800 case MONO_TYPE_ARRAY:
1801 case MONO_TYPE_SZARRAY:
1802 case MONO_TYPE_OBJECT:
1807 g_assert_not_reached ();
1810 mono_mb_emit_stloc (mb, 0);
1812 mono_mb_emit_byte (mb, CEE_LEAVE);
1814 mono_mb_emit_i4 (mb, 0);
1816 clause = g_new0 (MonoExceptionClause, 1);
1817 clause->flags = MONO_EXCEPTION_CLAUSE_FILTER;
1818 clause->try_len = mb->pos;
1821 clause->token_or_filter = mb->pos;
1823 mono_mb_emit_byte (mb, CEE_POP);
1824 mono_mb_emit_byte (mb, CEE_LDARG_2);
1825 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
1826 mono_mb_emit_byte (mb, CEE_PREFIX1);
1827 mono_mb_emit_byte (mb, CEE_CGT_UN);
1828 mono_mb_emit_byte (mb, CEE_PREFIX1);
1829 mono_mb_emit_byte (mb, CEE_ENDFILTER);
1831 clause->handler_offset = mb->pos;
1834 /* store exception */
1835 mono_mb_emit_stloc (mb, 1);
1837 mono_mb_emit_byte (mb, CEE_LDARG_2);
1838 mono_mb_emit_ldloc (mb, 1);
1839 mono_mb_emit_byte (mb, CEE_STIND_I);
1841 mono_mb_emit_byte (mb, CEE_LEAVE);
1842 mono_mb_emit_i4 (mb, 0);
1844 clause->handler_len = mb->pos - clause->handler_offset;
1847 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1848 mono_mb_emit_ldloc (mb, 0);
1849 mono_mb_emit_byte (mb, CEE_RET);
1851 res = mono_mb_create_method (mb, csig, sig->param_count + 16);
1854 header = ((MonoMethodNormal *)res)->header;
1855 header->num_clauses = 1;
1856 header->clauses = clause;
1858 g_hash_table_insert (cache, method, res);
1864 * generates IL code to call managed methods from unmanaged code
1867 mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this, MonoMarshalSpec **mspecs)
1869 MonoMethodSignature *sig, *csig;
1870 MonoMethodBuilder *mb;
1874 int i, pos, sigsize, *tmp_locals;
1876 g_assert (method != NULL);
1877 g_assert (!method->signature->pinvoke);
1879 cache = method->klass->image->managed_wrapper_cache;
1880 if (!this && (res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1884 /* fime: howto free that memory ? */
1887 sig = method->signature;
1889 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_NATIVE_TO_MANAGED);
1891 /* allocate local 0 (pointer) src_ptr */
1892 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1893 /* allocate local 1 (pointer) dst_ptr */
1894 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1895 /* allocate local 2 (boolean) delete_old */
1896 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
1898 mono_mb_emit_byte (mb, CEE_LDNULL);
1899 mono_mb_emit_byte (mb, CEE_STLOC_2);
1901 /* we copy the signature, so that we can modify it */
1902 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1903 csig = g_memdup (sig, sigsize);
1907 /* fixme: howto handle this ? */
1911 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1912 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1913 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, this));
1918 g_assert_not_reached ();
1923 /* we first do all conversions */
1924 tmp_locals = alloca (sizeof (int) * sig->param_count);
1925 for (i = 0; i < sig->param_count; i ++) {
1926 MonoType *t = sig->params [i];
1927 MonoMarshalSpec *spec = mspecs [i + 1];
1931 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
1934 MonoMethod *marshal_native_to_managed;
1935 MonoMethod *get_instance;
1937 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
1938 g_assert (mtype != NULL);
1939 mklass = mono_class_from_mono_type (mtype);
1940 g_assert (mklass != NULL);
1942 marshal_native_to_managed = mono_find_method_by_name (mklass, "MarshalNativeToManaged", 1);
1943 g_assert (marshal_native_to_managed);
1944 get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
1945 g_assert (get_instance);
1948 case MONO_TYPE_CLASS:
1949 case MONO_TYPE_OBJECT:
1950 case MONO_TYPE_STRING:
1951 case MONO_TYPE_ARRAY:
1952 case MONO_TYPE_SZARRAY:
1956 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1958 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
1960 mono_mb_emit_byte (mb, CEE_CALL);
1961 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
1963 mono_mb_emit_ldarg (mb, i);
1965 mono_mb_emit_byte (mb, CEE_CALLVIRT);
1966 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_native_to_managed));
1968 mono_mb_emit_stloc (mb, tmp_locals [i]);
1971 g_warning ("custom marshalling of type %x is currently not supported", t->type);
1972 g_assert_not_reached ();
1979 case MONO_TYPE_VALUETYPE:
1981 klass = sig->params [i]->data.klass;
1982 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
1983 klass->blittable || klass->enumtype)
1986 tmp_locals [i] = mono_mb_add_local (mb, &klass->byval_arg);
1989 mono_mb_emit_ldarg (mb, i);
1991 mono_mb_emit_ldarg_addr (mb, i);
1992 mono_mb_emit_byte (mb, CEE_STLOC_0);
1995 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1996 mono_mb_emit_byte (mb, CEE_BRFALSE);
1998 mono_mb_emit_i4 (mb, 0);
2001 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2002 mono_mb_emit_byte (mb, CEE_STLOC_1);
2004 /* emit valuetype convnversion code code */
2005 emit_struct_conv (mb, klass, TRUE);
2008 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2010 case MONO_TYPE_STRING:
2014 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2015 csig->params [i] = &mono_defaults.int_class->byval_arg;
2017 mono_mb_emit_ldarg (mb, i);
2018 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2019 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2020 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
2021 mono_mb_emit_stloc (mb, tmp_locals [i]);
2023 case MONO_TYPE_ARRAY:
2024 case MONO_TYPE_SZARRAY:
2028 klass = mono_class_from_mono_type (t);
2030 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2031 csig->params [i] = &mono_defaults.int_class->byval_arg;
2033 g_warning ("array marshaling not implemented");
2034 g_assert_not_reached ();
2039 for (i = 0; i < sig->param_count; i++) {
2040 MonoType *t = sig->params [i];
2043 case MONO_TYPE_BOOLEAN:
2057 mono_mb_emit_ldarg (mb, i);
2059 case MONO_TYPE_STRING:
2061 mono_mb_emit_ldarg (mb, i);
2063 g_assert (tmp_locals [i]);
2064 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2067 case MONO_TYPE_CLASS:
2068 case MONO_TYPE_ARRAY:
2069 case MONO_TYPE_SZARRAY:
2070 case MONO_TYPE_OBJECT:
2072 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2074 mono_mb_emit_ldarg (mb, i);
2076 case MONO_TYPE_VALUETYPE:
2077 klass = sig->params [i]->data.klass;
2078 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2079 klass->blittable || klass->enumtype) {
2080 mono_mb_emit_ldarg (mb, i);
2084 g_assert (tmp_locals [i]);
2086 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2088 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2091 g_warning ("type 0x%02x unknown", t->type);
2092 g_assert_not_reached ();
2096 mono_mb_emit_managed_call (mb, method, NULL);
2098 if (!sig->ret->byref) {
2099 switch (sig->ret->type) {
2100 case MONO_TYPE_VOID:
2101 case MONO_TYPE_BOOLEAN:
2115 case MONO_TYPE_OBJECT:
2116 mono_mb_emit_byte (mb, CEE_RET);
2118 case MONO_TYPE_STRING:
2119 csig->ret = &mono_defaults.int_class->byval_arg;
2121 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2122 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2123 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
2124 mono_mb_emit_byte (mb, CEE_RET);
2126 case MONO_TYPE_VALUETYPE: {
2128 klass = sig->ret->data.klass;
2129 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2130 klass->blittable || klass->enumtype)
2133 /* load pointer to returned value type */
2134 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2135 mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
2137 /* store the address of the source into local variable 0 */
2138 mono_mb_emit_byte (mb, CEE_STLOC_0);
2139 /* allocate space for the native struct and
2140 * store the address into dst_ptr */
2141 tmp = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2143 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2144 mono_mb_emit_byte (mb, CEE_PREFIX1);
2145 mono_mb_emit_byte (mb, CEE_LOCALLOC);
2146 mono_mb_emit_byte (mb, CEE_STLOC_1);
2147 mono_mb_emit_byte (mb, CEE_LDLOC_1);
2148 mono_mb_emit_stloc (mb, tmp);
2150 /* emit valuetype conversion code */
2151 emit_struct_conv (mb, klass, FALSE);
2152 mono_mb_emit_ldloc (mb, tmp);
2153 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2154 mono_mb_emit_byte (mb, CEE_MONO_RETOBJ);
2155 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2159 g_warning ("return type 0x%02x unknown", sig->ret->type);
2160 g_assert_not_reached ();
2163 mono_mb_emit_byte (mb, CEE_RET);
2166 res = mono_mb_create_method (mb, csig, sig->param_count + 16);
2170 g_hash_table_insert (cache, method, res);
2176 * mono_marshal_get_ldfld_wrapper:
2177 * @type: the type of the field
2179 * This method generates a function which can be use to load a field with type
2180 * @type from an object. The generated function has the following signature:
2181 * <@type> ldfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset)
2184 mono_marshal_get_ldfld_wrapper (MonoType *type)
2186 MonoMethodSignature *sig, *csig;
2187 MonoMethodBuilder *mb;
2190 static GHashTable *ldfld_hash = NULL;
2195 ldfld_hash = g_hash_table_new (NULL, NULL);
2201 if (type->type == MONO_TYPE_SZARRAY) {
2202 klass = mono_defaults.array_class;
2203 } else if (type->type == MONO_TYPE_VALUETYPE) {
2204 klass = type->data.klass;
2205 if (klass->enumtype) {
2206 t = klass->enum_basetype->type;
2207 klass = mono_class_from_mono_type (klass->enum_basetype);
2209 } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
2210 t == MONO_TYPE_CLASS) {
2211 klass = mono_defaults.object_class;
2212 } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
2213 klass = mono_defaults.int_class;
2215 klass = mono_class_from_mono_type (type);
2218 klass = mono_defaults.int_class;
2221 if ((res = g_hash_table_lookup (ldfld_hash, klass)))
2224 name = g_strdup_printf ("__ldfld_wrapper_%s.%s", klass->name_space, klass->name);
2225 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_LDFLD);
2228 mb->method->save_lmf = 1;
2230 sig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
2231 sig->params [0] = &mono_defaults.object_class->byval_arg;
2232 sig->params [1] = &mono_defaults.int_class->byval_arg;
2233 sig->params [2] = &mono_defaults.int_class->byval_arg;
2234 sig->params [3] = &mono_defaults.int_class->byval_arg;
2235 sig->ret = &klass->byval_arg;
2237 mono_mb_emit_ldarg (mb, 0);
2238 pos0 = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
2240 mono_mb_emit_ldarg (mb, 0);
2241 mono_mb_emit_ldarg (mb, 1);
2242 mono_mb_emit_ldarg (mb, 2);
2244 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
2245 csig->params [0] = &mono_defaults.object_class->byval_arg;
2246 csig->params [1] = &mono_defaults.int_class->byval_arg;
2247 csig->params [2] = &mono_defaults.int_class->byval_arg;
2248 csig->ret = &klass->this_arg;
2251 mono_mb_emit_native_call (mb, csig, mono_load_remote_field_new);
2253 if (klass->valuetype) {
2254 mono_mb_emit_byte (mb, CEE_UNBOX);
2255 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2256 mono_mb_emit_byte (mb, CEE_BR);
2258 mono_mb_emit_i4 (mb, 0);
2260 mono_mb_emit_byte (mb, CEE_RET);
2264 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
2266 mono_mb_emit_ldarg (mb, 0);
2267 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2268 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2269 mono_mb_emit_ldarg (mb, 3);
2270 mono_mb_emit_byte (mb, CEE_ADD);
2272 if (klass->valuetype)
2273 mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
2278 case MONO_TYPE_BOOLEAN:
2279 mono_mb_emit_byte (mb, CEE_LDIND_I1);
2281 case MONO_TYPE_CHAR:
2284 mono_mb_emit_byte (mb, CEE_LDIND_I2);
2288 mono_mb_emit_byte (mb, CEE_LDIND_I4);
2292 mono_mb_emit_byte (mb, CEE_LDIND_I8);
2295 mono_mb_emit_byte (mb, CEE_LDIND_R4);
2298 mono_mb_emit_byte (mb, CEE_LDIND_R8);
2300 case MONO_TYPE_ARRAY:
2302 case MONO_TYPE_FNPTR:
2303 case MONO_TYPE_SZARRAY:
2304 case MONO_TYPE_OBJECT:
2305 case MONO_TYPE_CLASS:
2306 case MONO_TYPE_STRING:
2309 mono_mb_emit_byte (mb, CEE_LDIND_I);
2311 case MONO_TYPE_VALUETYPE:
2312 g_assert (!klass->enumtype);
2313 mono_mb_emit_byte (mb, CEE_LDOBJ);
2314 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2317 g_warning ("type %x not implemented", type->type);
2318 g_assert_not_reached ();
2321 mono_mb_emit_byte (mb, CEE_RET);
2323 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
2326 g_hash_table_insert (ldfld_hash, klass, res);
2332 * mono_marshal_get_stfld_wrapper:
2333 * @type: the type of the field
2335 * This method generates a function which can be use to store a field with type
2336 * @type. The generated function has the following signature:
2337 * void stfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset, <@type> val)
2340 mono_marshal_get_stfld_wrapper (MonoType *type)
2342 MonoMethodSignature *sig, *csig;
2343 MonoMethodBuilder *mb;
2346 static GHashTable *stfld_hash = NULL;
2351 stfld_hash = g_hash_table_new (NULL, NULL);
2356 if (type->type == MONO_TYPE_SZARRAY) {
2357 klass = mono_defaults.array_class;
2358 } else if (type->type == MONO_TYPE_VALUETYPE) {
2359 klass = type->data.klass;
2360 if (klass->enumtype) {
2361 t = klass->enum_basetype->type;
2362 klass = mono_class_from_mono_type (klass->enum_basetype);
2364 } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
2365 t == MONO_TYPE_CLASS) {
2366 klass = mono_defaults.object_class;
2367 } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
2368 klass = mono_defaults.int_class;
2370 klass = mono_class_from_mono_type (type);
2373 klass = mono_defaults.int_class;
2376 if ((res = g_hash_table_lookup (stfld_hash, klass)))
2379 name = g_strdup_printf ("__stfld_wrapper_%s.%s", klass->name_space, klass->name);
2380 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_STFLD);
2383 mb->method->save_lmf = 1;
2385 sig = mono_metadata_signature_alloc (mono_defaults.corlib, 5);
2386 sig->params [0] = &mono_defaults.object_class->byval_arg;
2387 sig->params [1] = &mono_defaults.int_class->byval_arg;
2388 sig->params [2] = &mono_defaults.int_class->byval_arg;
2389 sig->params [3] = &mono_defaults.int_class->byval_arg;
2390 sig->params [4] = &klass->byval_arg;
2391 sig->ret = &mono_defaults.void_class->byval_arg;
2393 mono_mb_emit_ldarg (mb, 0);
2394 pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
2396 mono_mb_emit_ldarg (mb, 0);
2397 mono_mb_emit_ldarg (mb, 1);
2398 mono_mb_emit_ldarg (mb, 2);
2399 mono_mb_emit_ldarg (mb, 4);
2401 if (klass->valuetype) {
2402 mono_mb_emit_byte (mb, CEE_BOX);
2403 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2406 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
2407 csig->params [0] = &mono_defaults.object_class->byval_arg;
2408 csig->params [1] = &mono_defaults.int_class->byval_arg;
2409 csig->params [2] = &mono_defaults.int_class->byval_arg;
2410 csig->params [3] = &klass->this_arg;
2411 csig->ret = &mono_defaults.void_class->byval_arg;
2414 mono_mb_emit_native_call (mb, csig, mono_store_remote_field_new);
2416 mono_mb_emit_byte (mb, CEE_RET);
2418 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2420 mono_mb_emit_ldarg (mb, 0);
2421 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2422 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2423 mono_mb_emit_ldarg (mb, 3);
2424 mono_mb_emit_byte (mb, CEE_ADD);
2425 mono_mb_emit_ldarg (mb, 4);
2430 case MONO_TYPE_BOOLEAN:
2431 mono_mb_emit_byte (mb, CEE_STIND_I1);
2433 case MONO_TYPE_CHAR:
2436 mono_mb_emit_byte (mb, CEE_STIND_I2);
2440 mono_mb_emit_byte (mb, CEE_STIND_I4);
2444 mono_mb_emit_byte (mb, CEE_STIND_I8);
2447 mono_mb_emit_byte (mb, CEE_STIND_R4);
2450 mono_mb_emit_byte (mb, CEE_STIND_R8);
2452 case MONO_TYPE_ARRAY:
2454 case MONO_TYPE_FNPTR:
2455 case MONO_TYPE_SZARRAY:
2456 case MONO_TYPE_OBJECT:
2457 case MONO_TYPE_CLASS:
2458 case MONO_TYPE_STRING:
2461 mono_mb_emit_byte (mb, CEE_STIND_I);
2463 case MONO_TYPE_VALUETYPE:
2464 g_assert (!klass->enumtype);
2465 mono_mb_emit_byte (mb, CEE_STOBJ);
2466 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2469 g_warning ("type %x not implemented", type->type);
2470 g_assert_not_reached ();
2473 mono_mb_emit_byte (mb, CEE_RET);
2475 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
2478 g_hash_table_insert (stfld_hash, klass, res);
2484 * generates IL code for the icall wrapper (the generated method
2485 * calls the unamnaged code in func)
2488 mono_marshal_get_icall_wrapper (MonoMethodSignature *sig, const char *name, gconstpointer func)
2490 MonoMethodSignature *csig;
2491 MonoMethodBuilder *mb;
2495 g_assert (sig->pinvoke);
2497 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_MANAGED_TO_NATIVE);
2499 mb->method->save_lmf = 1;
2501 /* we copy the signature, so that we can modify it */
2502 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
2505 mono_mb_emit_byte (mb, CEE_LDARG_0);
2507 for (i = 0; i < sig->param_count; i++)
2508 mono_mb_emit_ldarg (mb, i + sig->hasthis);
2510 mono_mb_emit_native_call (mb, sig, (gpointer) func);
2512 mono_mb_emit_byte (mb, CEE_RET);
2514 csig = g_memdup (sig, sigsize);
2517 res = mono_mb_create_method (mb, csig, csig->param_count + 16);
2524 * generates IL code for the pinvoke wrapper (the generated method
2525 * calls the unamnage code in method->addr)
2528 mono_marshal_get_native_wrapper (MonoMethod *method)
2530 MonoMethodSignature *sig, *csig;
2531 MonoMethodPInvoke *piinfo;
2532 MonoMethodBuilder *mb;
2533 MonoMarshalSpec **mspecs;
2537 gboolean pinvoke = FALSE;
2538 int i, pos, argnum, *tmp_locals;
2541 g_assert (method != NULL);
2542 g_assert (method->signature->pinvoke);
2544 cache = method->klass->image->native_wrapper_cache;
2545 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
2548 sig = method->signature;
2549 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
2551 if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
2552 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2555 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_MANAGED_TO_NATIVE);
2557 mb->method->save_lmf = 1;
2559 if (pinvoke && !method->addr)
2560 mono_lookup_pinvoke_call (method);
2562 piinfo = (MonoMethodPInvoke *)method;
2564 if (!method->addr) {
2565 mono_mb_emit_exception (mb);
2566 csig = g_memdup (sig, sigsize);
2568 res = mono_mb_create_method (mb, csig, csig->param_count + 16);
2570 g_hash_table_insert (cache, method, res);
2574 /* internal calls: we simply push all arguments and call the method (no conversions) */
2575 if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
2577 /* hack - string constructors returns a value */
2578 if (method->string_ctor) {
2579 csig = g_memdup (sig, sigsize);
2580 csig->ret = &mono_defaults.string_class->byval_arg;
2585 mono_mb_emit_byte (mb, CEE_LDARG_0);
2587 for (i = 0; i < sig->param_count; i++)
2588 mono_mb_emit_ldarg (mb, i + sig->hasthis);
2590 g_assert (method->addr);
2591 mono_mb_emit_native_call (mb, csig, method->addr);
2593 mono_mb_emit_byte (mb, CEE_RET);
2595 csig = g_memdup (csig, sigsize);
2597 res = mono_mb_create_method (mb, csig, csig->param_count + 16);
2599 g_hash_table_insert (cache, method, res);
2605 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
2606 mono_method_get_marshal_info (method, mspecs);
2608 /* pinvoke: we need to convert the arguments if necessary */
2610 /* we copy the signature, so that we can set pinvoke to 0 */
2611 csig = g_memdup (sig, sigsize);
2614 /* we allocate local for use with emit_struct_conv() */
2615 /* allocate local 0 (pointer) src_ptr */
2616 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2617 /* allocate local 1 (pointer) dst_ptr */
2618 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2619 /* allocate local 2 (boolean) delete_old */
2620 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2622 /* delete_old = FALSE */
2623 mono_mb_emit_icon (mb, 0);
2624 mono_mb_emit_byte (mb, CEE_STLOC_2);
2626 if (!MONO_TYPE_IS_VOID(sig->ret)) {
2627 /* allocate local 3 to store the return value */
2628 mono_mb_add_local (mb, sig->ret);
2631 /* we first do all conversions */
2632 tmp_locals = alloca (sizeof (int) * sig->param_count);
2634 for (i = 0; i < sig->param_count; i ++) {
2635 MonoType *t = sig->params [i];
2636 MonoMarshalSpec *spec = mspecs [i + 1];
2638 argnum = i + sig->hasthis;
2641 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
2644 MonoMethod *marshal_managed_to_native;
2645 MonoMethod *get_instance;
2647 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
2648 g_assert (mtype != NULL);
2649 mklass = mono_class_from_mono_type (mtype);
2650 g_assert (mklass != NULL);
2652 marshal_managed_to_native = mono_find_method_by_name (mklass, "MarshalManagedToNative", 1);
2653 g_assert (marshal_managed_to_native);
2654 get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
2655 g_assert (get_instance);
2658 case MONO_TYPE_CLASS:
2659 case MONO_TYPE_OBJECT:
2660 case MONO_TYPE_STRING:
2661 case MONO_TYPE_ARRAY:
2662 case MONO_TYPE_SZARRAY:
2666 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2668 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
2670 mono_mb_emit_byte (mb, CEE_CALL);
2671 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
2673 mono_mb_emit_ldarg (mb, argnum);
2675 mono_mb_emit_byte (mb, CEE_CALLVIRT);
2676 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_managed_to_native));
2678 mono_mb_emit_stloc (mb, tmp_locals [i]);
2681 g_warning ("custom marshalling of type %x is currently not supported", t->type);
2682 g_assert_not_reached ();
2690 case MONO_TYPE_VALUETYPE:
2691 klass = t->data.klass;
2693 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2694 klass->blittable || klass->enumtype)
2697 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2699 /* store the address of the source into local variable 0 */
2701 mono_mb_emit_ldarg (mb, argnum);
2703 mono_mb_emit_ldarg_addr (mb, argnum);
2705 mono_mb_emit_byte (mb, CEE_STLOC_0);
2707 /* allocate space for the native struct and
2708 * store the address into local variable 1 (dest) */
2709 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2710 mono_mb_emit_byte (mb, CEE_PREFIX1);
2711 mono_mb_emit_byte (mb, CEE_LOCALLOC);
2712 mono_mb_emit_stloc (mb, tmp_locals [i]);
2715 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2716 mono_mb_emit_byte (mb, CEE_BRFALSE);
2718 mono_mb_emit_i4 (mb, 0);
2722 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2723 mono_mb_emit_byte (mb, CEE_STLOC_1);
2725 /* emit valuetype conversion code */
2726 emit_struct_conv (mb, klass, FALSE);
2729 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2731 case MONO_TYPE_STRING:
2732 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2733 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2736 if (t->attrs & PARAM_ATTRIBUTE_OUT)
2739 mono_mb_emit_ldarg (mb, argnum);
2740 mono_mb_emit_byte (mb, CEE_LDIND_I);
2742 mono_mb_emit_ldarg (mb, argnum);
2745 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2746 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2749 switch (spec->native) {
2750 case MONO_NATIVE_LPWSTR:
2751 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPWSTR);
2753 case MONO_NATIVE_LPSTR:
2754 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
2757 g_warning ("marshalling conversion %d not implemented", spec->native);
2758 g_assert_not_reached ();
2761 switch (piinfo->piflags & PINVOKE_ATTRIBUTE_CHAR_SET_MASK) {
2762 case PINVOKE_ATTRIBUTE_CHAR_SET_ANSI:
2763 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
2765 case PINVOKE_ATTRIBUTE_CHAR_SET_UNICODE:
2766 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPWSTR);
2768 case PINVOKE_ATTRIBUTE_CHAR_SET_AUTO:
2769 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPTSTR);
2772 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
2777 mono_mb_emit_stloc (mb, tmp_locals [i]);
2779 case MONO_TYPE_CLASS:
2780 case MONO_TYPE_OBJECT:
2781 klass = t->data.klass;
2783 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2784 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2786 if (klass->delegate) {
2787 g_assert (!t->byref);
2788 mono_mb_emit_ldarg (mb, argnum);
2789 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2790 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2791 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_DEL_FTN);
2792 mono_mb_emit_stloc (mb, tmp_locals [i]);
2793 } else if (klass == mono_defaults.stringbuilder_class) {
2794 g_assert (!t->byref);
2795 mono_mb_emit_ldarg (mb, argnum);
2796 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2797 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2798 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_SB_LPSTR);
2799 mono_mb_emit_stloc (mb, tmp_locals [i]);
2801 mono_mb_emit_byte (mb, CEE_LDNULL);
2802 mono_mb_emit_stloc (mb, tmp_locals [i]);
2805 /* we dont need any conversions for out parameters */
2806 if (t->attrs & PARAM_ATTRIBUTE_OUT)
2809 mono_mb_emit_ldarg (mb, argnum);
2810 mono_mb_emit_byte (mb, CEE_LDIND_I);
2813 mono_mb_emit_ldarg (mb, argnum);
2814 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2815 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2818 /* store the address of the source into local variable 0 */
2819 mono_mb_emit_byte (mb, CEE_STLOC_0);
2820 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2821 mono_mb_emit_byte (mb, CEE_BRFALSE);
2823 mono_mb_emit_i4 (mb, 0);
2825 /* allocate space for the native struct and store the address */
2826 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2827 mono_mb_emit_byte (mb, CEE_PREFIX1);
2828 mono_mb_emit_byte (mb, CEE_LOCALLOC);
2829 mono_mb_emit_stloc (mb, tmp_locals [i]);
2831 /* set the src_ptr */
2832 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2833 mono_mb_emit_icon (mb, sizeof (MonoObject));
2834 mono_mb_emit_byte (mb, CEE_ADD);
2835 mono_mb_emit_byte (mb, CEE_STLOC_0);
2838 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2839 mono_mb_emit_byte (mb, CEE_STLOC_1);
2841 /* emit valuetype conversion code */
2842 emit_struct_conv (mb, klass, FALSE);
2844 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2848 case MONO_TYPE_ARRAY:
2849 case MONO_TYPE_SZARRAY:
2853 klass = mono_class_from_mono_type (t);
2855 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2856 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2858 mono_mb_emit_ldarg (mb, argnum);
2859 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2860 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2861 if (klass->element_class == mono_defaults.string_class)
2862 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STRARRAY_STRLPARRAY);
2864 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_ARRAY_LPARRAY);
2865 mono_mb_emit_stloc (mb, tmp_locals [i]);
2870 /* push all arguments */
2873 mono_mb_emit_byte (mb, CEE_LDARG_0);
2875 for (i = 0; i < sig->param_count; i++) {
2876 MonoType *t = sig->params [i];
2878 argnum = i + sig->hasthis;
2881 case MONO_TYPE_BOOLEAN:
2883 g_warning ("byref boolean marshalling not inplemented");
2884 mono_mb_emit_ldarg (mb, argnum);
2899 mono_mb_emit_ldarg (mb, argnum);
2901 case MONO_TYPE_VALUETYPE:
2902 klass = sig->params [i]->data.klass;
2903 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2904 klass->blittable || klass->enumtype) {
2905 mono_mb_emit_ldarg (mb, argnum);
2908 g_assert (tmp_locals [i]);
2909 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2911 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2912 mono_mb_emit_byte (mb, CEE_MONO_LDNATIVEOBJ);
2913 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2916 case MONO_TYPE_STRING:
2917 case MONO_TYPE_CLASS:
2918 case MONO_TYPE_OBJECT:
2919 g_assert (tmp_locals [i]);
2921 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2923 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2925 case MONO_TYPE_CHAR:
2926 /* fixme: dont know how to marshal that. We cant simply
2927 * convert it to a one byte UTF8 character, because an
2928 * unicode character may need more that one byte in UTF8 */
2929 mono_mb_emit_ldarg (mb, argnum);
2931 case MONO_TYPE_ARRAY:
2932 case MONO_TYPE_SZARRAY:
2934 mono_mb_emit_ldarg (mb, argnum);
2936 g_assert (tmp_locals [i]);
2937 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2940 case MONO_TYPE_TYPEDBYREF:
2941 case MONO_TYPE_FNPTR:
2943 g_warning ("type 0x%02x unknown", t->type);
2944 g_assert_not_reached ();
2948 /* call the native method */
2949 mono_mb_emit_native_call (mb, csig, method->addr);
2951 /* convert the result */
2952 if (!sig->ret->byref) {
2953 MonoMarshalSpec *spec = mspecs [0];
2954 type = sig->ret->type;
2956 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
2959 MonoMethod *marshal_native_to_managed;
2960 MonoMethod *get_instance;
2962 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
2963 g_assert (mtype != NULL);
2964 mklass = mono_class_from_mono_type (mtype);
2965 g_assert (mklass != NULL);
2967 marshal_native_to_managed = mono_find_method_by_name (mklass, "MarshalNativeToManaged", 1);
2968 g_assert (marshal_native_to_managed);
2969 get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
2970 g_assert (get_instance);
2973 case MONO_TYPE_CLASS:
2974 case MONO_TYPE_OBJECT:
2975 case MONO_TYPE_STRING:
2976 case MONO_TYPE_ARRAY:
2977 case MONO_TYPE_SZARRAY:
2978 mono_mb_emit_byte (mb, CEE_STLOC_3);
2980 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
2982 mono_mb_emit_byte (mb, CEE_CALL);
2983 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
2985 mono_mb_emit_byte (mb, CEE_LDLOC_3);
2987 mono_mb_emit_byte (mb, CEE_CALLVIRT);
2988 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_native_to_managed));
2990 mono_mb_emit_byte (mb, CEE_STLOC_3);
2993 g_warning ("custom marshalling of type %x is currently not supported", type);
2994 g_assert_not_reached ();
3001 case MONO_TYPE_VOID:
3016 /* no conversions necessary */
3017 mono_mb_emit_byte (mb, CEE_STLOC_3);
3019 case MONO_TYPE_BOOLEAN:
3020 /* maybe we need to make sure that it fits within 8 bits */
3021 mono_mb_emit_byte (mb, CEE_STLOC_3);
3023 case MONO_TYPE_VALUETYPE:
3024 klass = sig->ret->data.klass;
3025 if (klass->enumtype) {
3026 type = sig->ret->data.klass->enum_basetype->type;
3030 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3032 mono_mb_emit_byte (mb, CEE_STLOC_3);
3035 /* load pointer to returned value type */
3036 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3037 mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
3038 /* store the address of the source into local variable 0 */
3039 mono_mb_emit_byte (mb, CEE_STLOC_0);
3041 mono_mb_emit_ldloc_addr (mb, 3);
3042 mono_mb_emit_byte (mb, CEE_STLOC_1);
3044 /* emit valuetype conversion code */
3045 emit_struct_conv (mb, sig->ret->data.klass, TRUE);
3047 case MONO_TYPE_STRING:
3048 #ifdef GTK_SHARP_FIXED
3049 mono_mb_emit_byte (mb, CEE_STLOC_0);
3050 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3053 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3054 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3056 switch (spec->native) {
3057 case MONO_NATIVE_LPWSTR:
3058 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPWSTR_STR);
3061 g_warning ("marshalling conversion not implemented");
3062 g_assert_not_reached ();
3065 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
3067 mono_mb_emit_byte (mb, CEE_STLOC_3);
3069 #ifdef GTK_SHARP_FIXED
3070 /* free the string */
3071 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3072 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3073 mono_mb_emit_byte (mb, CEE_MONO_FREE);
3076 case MONO_TYPE_CLASS:
3077 case MONO_TYPE_OBJECT:
3078 klass = sig->ret->data.klass;
3081 mono_mb_emit_byte (mb, CEE_STLOC_0);
3083 mono_mb_emit_byte (mb, CEE_LDNULL);
3084 mono_mb_emit_byte (mb, CEE_STLOC_3);
3087 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3088 mono_mb_emit_byte (mb, CEE_BRFALSE);
3090 mono_mb_emit_i4 (mb, 0);
3092 /* allocate result object */
3094 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3095 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
3096 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3097 mono_mb_emit_byte (mb, CEE_STLOC_3);
3101 mono_mb_emit_byte (mb, CEE_LDLOC_3);
3102 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3103 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
3104 mono_mb_emit_icon (mb, sizeof (MonoObject));
3105 mono_mb_emit_byte (mb, CEE_ADD);
3106 mono_mb_emit_byte (mb, CEE_STLOC_1);
3108 /* emit conversion code */
3109 emit_struct_conv (mb, klass, TRUE);
3111 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3113 case MONO_TYPE_ARRAY:
3114 case MONO_TYPE_SZARRAY:
3115 /* fixme: we need conversions here */
3116 mono_mb_emit_byte (mb, CEE_STLOC_3);
3118 case MONO_TYPE_CHAR:
3119 /* fixme: we need conversions here */
3120 mono_mb_emit_byte (mb, CEE_STLOC_3);
3122 case MONO_TYPE_TYPEDBYREF:
3123 case MONO_TYPE_FNPTR:
3125 g_warning ("return type 0x%02x unknown", sig->ret->type);
3126 g_assert_not_reached ();
3130 mono_mb_emit_byte (mb, CEE_STLOC_3);
3133 /* we need to convert byref arguments back and free string arrays */
3134 for (i = 0; i < sig->param_count; i++) {
3135 MonoType *t = sig->params [i];
3137 argnum = i + sig->hasthis;
3140 case MONO_TYPE_STRING:
3141 if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT)) {
3142 mono_mb_emit_ldarg (mb, argnum);
3143 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3144 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3145 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3146 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
3147 mono_mb_emit_byte (mb, CEE_STIND_I);
3149 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3150 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3151 mono_mb_emit_byte (mb, CEE_MONO_FREE);
3154 case MONO_TYPE_CLASS:
3155 case MONO_TYPE_OBJECT:
3156 if (t->data.klass == mono_defaults.stringbuilder_class) {
3157 g_assert (!t->byref);
3158 mono_mb_emit_ldarg (mb, argnum);
3159 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3160 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3161 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
3162 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_SB);
3163 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3164 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3165 mono_mb_emit_byte (mb, CEE_MONO_FREE);
3169 if (!(t->byref || (t->attrs & PARAM_ATTRIBUTE_OUT)))
3172 if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT)) {
3173 /* allocate a new object new object */
3174 mono_mb_emit_ldarg (mb, argnum);
3175 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3176 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
3177 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3178 mono_mb_emit_byte (mb, CEE_STIND_I);
3181 /* dst = *argument */
3182 mono_mb_emit_ldarg (mb, argnum);
3185 mono_mb_emit_byte (mb, CEE_LDIND_I);
3187 mono_mb_emit_byte (mb, CEE_STLOC_1);
3189 mono_mb_emit_byte (mb, CEE_LDLOC_1);
3190 mono_mb_emit_byte (mb, CEE_BRFALSE);
3192 mono_mb_emit_i4 (mb, 0);
3194 mono_mb_emit_byte (mb, CEE_LDLOC_1);
3195 mono_mb_emit_icon (mb, sizeof (MonoObject));
3196 mono_mb_emit_byte (mb, CEE_ADD);
3197 mono_mb_emit_byte (mb, CEE_STLOC_1);
3199 /* src = tmp_locals [i] */
3200 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3201 mono_mb_emit_byte (mb, CEE_STLOC_0);
3203 /* emit valuetype conversion code */
3204 emit_struct_conv (mb, klass, TRUE);
3206 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3208 case MONO_TYPE_VALUETYPE:
3212 klass = t->data.klass;
3213 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3214 klass->blittable || klass->enumtype)
3217 /* dst = argument */
3218 mono_mb_emit_ldarg (mb, argnum);
3219 mono_mb_emit_byte (mb, CEE_STLOC_1);
3221 mono_mb_emit_byte (mb, CEE_LDLOC_1);
3222 mono_mb_emit_byte (mb, CEE_BRFALSE);
3224 mono_mb_emit_i4 (mb, 0);
3226 /* src = tmp_locals [i] */
3227 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3228 mono_mb_emit_byte (mb, CEE_STLOC_0);
3230 /* emit valuetype conversion code */
3231 emit_struct_conv (mb, klass, TRUE);
3233 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3235 case MONO_TYPE_SZARRAY:
3239 klass = mono_class_from_mono_type (t);
3241 if (klass->element_class == mono_defaults.string_class) {
3242 g_assert (tmp_locals [i]);
3244 mono_mb_emit_ldarg (mb, argnum);
3245 mono_mb_emit_byte (mb, CEE_BRFALSE);
3247 mono_mb_emit_i4 (mb, 0);
3249 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3250 mono_mb_emit_ldarg (mb, argnum);
3251 mono_mb_emit_byte (mb, CEE_LDLEN);
3252 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3253 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
3254 mono_mb_emit_byte (mb, MONO_MARSHAL_FREE_ARRAY);
3256 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3264 if (!MONO_TYPE_IS_VOID(sig->ret))
3265 mono_mb_emit_byte (mb, CEE_LDLOC_3);
3267 mono_mb_emit_byte (mb, CEE_RET);
3269 csig = g_memdup (sig, sigsize);
3271 res = mono_mb_create_method (mb, csig, csig->param_count + 16);
3274 g_hash_table_insert (cache, method, res);
3276 for (i = sig->param_count; i >= 0; i--)
3277 g_free (mspecs [i]);
3284 * generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld)
3287 mono_marshal_get_struct_to_ptr (MonoClass *klass)
3289 MonoMethodBuilder *mb;
3290 static MonoMethod *stoptr = NULL;
3293 g_assert (klass != NULL);
3295 if (klass->str_to_ptr)
3296 return klass->str_to_ptr;
3299 stoptr = mono_find_method_by_name (mono_defaults.marshal_class, "StructureToPtr", 3);
3302 mb = mono_mb_new (klass, stoptr->name, MONO_WRAPPER_UNKNOWN);
3304 if (klass->blittable) {
3305 mono_mb_emit_byte (mb, CEE_LDARG_1);
3306 mono_mb_emit_byte (mb, CEE_LDARG_0);
3307 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3308 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
3309 mono_mb_emit_byte (mb, CEE_PREFIX1);
3310 mono_mb_emit_byte (mb, CEE_CPBLK);
3313 /* allocate local 0 (pointer) src_ptr */
3314 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3315 /* allocate local 1 (pointer) dst_ptr */
3316 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3317 /* allocate local 2 (boolean) delete_old */
3318 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
3319 mono_mb_emit_byte (mb, CEE_LDARG_2);
3320 mono_mb_emit_byte (mb, CEE_STLOC_2);
3322 /* initialize src_ptr to point to the start of object data */
3323 mono_mb_emit_byte (mb, CEE_LDARG_0);
3324 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3325 mono_mb_emit_byte (mb, CEE_STLOC_0);
3327 /* initialize dst_ptr */
3328 mono_mb_emit_byte (mb, CEE_LDARG_1);
3329 mono_mb_emit_byte (mb, CEE_STLOC_1);
3331 emit_struct_conv (mb, klass, FALSE);
3334 mono_mb_emit_byte (mb, CEE_RET);
3336 res = mono_mb_create_method (mb, stoptr->signature, 0);
3339 klass->str_to_ptr = res;
3344 * generates IL code for PtrToStructure (IntPtr src, object structure)
3347 mono_marshal_get_ptr_to_struct (MonoClass *klass)
3349 MonoMethodBuilder *mb;
3350 static MonoMethod *ptostr = NULL;
3353 g_assert (klass != NULL);
3355 if (klass->ptr_to_str)
3356 return klass->ptr_to_str;
3359 ptostr = mono_find_method_by_name (mono_defaults.marshal_class, "PtrToStructure", 2);
3362 mb = mono_mb_new (klass, ptostr->name, MONO_WRAPPER_UNKNOWN);
3364 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable) {
3365 mono_mb_emit_byte (mb, CEE_LDARG_1);
3366 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3367 mono_mb_emit_byte (mb, CEE_LDARG_0);
3368 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
3369 mono_mb_emit_byte (mb, CEE_PREFIX1);
3370 mono_mb_emit_byte (mb, CEE_CPBLK);
3373 /* allocate local 0 (pointer) src_ptr */
3374 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3375 /* allocate local 1 (pointer) dst_ptr */
3376 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3378 /* initialize src_ptr to point to the start of object data */
3379 mono_mb_emit_byte (mb, CEE_LDARG_0);
3380 mono_mb_emit_byte (mb, CEE_STLOC_0);
3382 /* initialize dst_ptr */
3383 mono_mb_emit_byte (mb, CEE_LDARG_1);
3384 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3385 mono_mb_emit_byte (mb, CEE_STLOC_1);
3387 emit_struct_conv (mb, klass, TRUE);
3390 mono_mb_emit_byte (mb, CEE_RET);
3392 res = mono_mb_create_method (mb, ptostr->signature, 0);
3395 klass->ptr_to_str = res;
3399 static MonoReflectionType *
3400 type_from_handle (MonoType *handle)
3402 MonoDomain *domain = mono_domain_get ();
3403 MonoClass *klass = mono_class_from_mono_type (handle);
3405 MONO_ARCH_SAVE_REGS;
3407 mono_class_init (klass);
3408 return mono_type_get_object (domain, handle);
3412 * generates IL code for the synchronized wrapper: the generated method
3413 * calls METHOD while locking 'this' or the parent type.
3416 mono_marshal_get_synchronized_wrapper (MonoMethod *method)
3418 static MonoMethodSignature *from_handle_sig = NULL;
3419 static MonoMethod *enter_method, *exit_method;
3420 MonoMethodSignature *sig;
3421 MonoExceptionClause *clause;
3422 MonoMethodHeader *header;
3423 MonoMethodBuilder *mb;
3426 int i, pos, this_local, ret_local;
3430 if (method->wrapper_type == MONO_WRAPPER_SYNCHRONIZED)
3433 cache = method->klass->image->synchronized_cache;
3434 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
3437 sig = method->signature;
3439 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_SYNCHRONIZED);
3442 if (!MONO_TYPE_IS_VOID (sig->ret))
3443 ret_local = mono_mb_add_local (mb, sig->ret);
3446 this_local = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
3448 clause = g_new0 (MonoExceptionClause, 1);
3449 clause->flags = MONO_EXCEPTION_CLAUSE_FINALLY;
3451 if (!enter_method) {
3452 MonoMethodDesc *desc;
3454 desc = mono_method_desc_new ("Monitor:Enter", FALSE);
3455 enter_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
3456 g_assert (enter_method);
3457 mono_method_desc_free (desc);
3458 desc = mono_method_desc_new ("Monitor:Exit", FALSE);
3459 exit_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
3460 g_assert (exit_method);
3461 mono_method_desc_free (desc);
3464 * GetTypeFromHandle isn't called as a managed method because it has
3465 * a funky calling sequence, e.g. ldtoken+GetTypeFromHandle gets
3466 * transformed into something else by the JIT.
3468 from_handle_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
3469 from_handle_sig->params [0] = &mono_defaults.object_class->byval_arg;
3470 from_handle_sig->ret = &mono_defaults.object_class->byval_arg;
3473 /* Push this or the type object */
3474 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3475 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3476 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
3477 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, &method->klass->byval_arg));
3478 mono_mb_emit_native_call (mb, from_handle_sig, type_from_handle);
3481 mono_mb_emit_ldarg (mb, 0);
3482 mono_mb_emit_stloc (mb, this_local);
3484 /* Call Monitor::Enter() */
3485 mono_mb_emit_ldloc (mb, this_local);
3486 mono_mb_emit_managed_call (mb, enter_method, NULL);
3488 clause->try_offset = mb->pos;
3490 /* Call the method */
3492 mono_mb_emit_ldarg (mb, 0);
3493 for (i = 0; i < sig->param_count; i++)
3494 mono_mb_emit_ldarg (mb, i + (sig->hasthis == TRUE));
3495 mono_mb_emit_managed_call (mb, method, method->signature);
3496 if (!MONO_TYPE_IS_VOID (sig->ret))
3497 mono_mb_emit_stloc (mb, ret_local);
3499 mono_mb_emit_byte (mb, CEE_LEAVE);
3501 mono_mb_emit_i4 (mb, 0);
3503 clause->try_len = mb->pos - clause->try_offset;
3504 clause->handler_offset = mb->pos;
3506 /* Call Monitor::Exit() */
3507 mono_mb_emit_ldloc (mb, this_local);
3508 // mono_mb_emit_native_call (mb, exit_sig, mono_monitor_exit);
3509 mono_mb_emit_managed_call (mb, exit_method, NULL);
3510 mono_mb_emit_byte (mb, CEE_ENDFINALLY);
3512 clause->handler_len = mb->pos - clause->handler_offset;
3514 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3515 if (!MONO_TYPE_IS_VOID (sig->ret))
3516 mono_mb_emit_ldloc (mb, ret_local);
3517 mono_mb_emit_byte (mb, CEE_RET);
3519 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
3522 header = ((MonoMethodNormal *)res)->header;
3523 header->num_clauses = 1;
3524 header->clauses = clause;
3526 g_hash_table_insert (cache, method, res);
3531 /* FIXME: on win32 we should probably use GlobalAlloc(). */
3533 mono_marshal_alloc (gpointer size)
3535 MONO_ARCH_SAVE_REGS;
3537 return g_try_malloc ((gulong)size);
3541 mono_marshal_free (gpointer ptr)
3543 MONO_ARCH_SAVE_REGS;
3549 mono_marshal_free_array (gpointer *ptr, int size)
3556 for (i = 0; i < size; i++)
3562 mono_marshal_realloc (gpointer ptr, gpointer size)
3564 MONO_ARCH_SAVE_REGS;
3566 return g_try_realloc (ptr, (gulong)size);
3570 mono_marshal_string_array (MonoArray *array)
3578 len = mono_array_length (array);
3580 result = g_malloc (sizeof (char *) * (len + 1));
3581 for (i = 0; i < len; ++i) {
3582 MonoString *s = (MonoString *)mono_array_get (array, gpointer, i);
3583 result [i] = s ? mono_string_to_utf8 (s): NULL;
3585 /* null terminate the array */
3592 ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArray *src, gint32 start_index,
3593 gpointer dest, gint32 length)
3598 MONO_ARCH_SAVE_REGS;
3600 MONO_CHECK_ARG_NULL (src);
3601 MONO_CHECK_ARG_NULL (dest);
3603 g_assert (src->obj.vtable->klass->rank == 1);
3604 g_assert (start_index >= 0);
3605 g_assert (length >= 0);
3606 g_assert (start_index + length <= mono_array_length (src));
3608 element_size = mono_array_element_size (src->obj.vtable->klass);
3610 source_addr = mono_array_addr_with_size (src, element_size, start_index);
3612 memcpy (dest, source_addr, length * element_size);
3616 ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer src, gint32 start_index,
3617 MonoArray *dest, gint32 length)
3622 MONO_ARCH_SAVE_REGS;
3624 MONO_CHECK_ARG_NULL (src);
3625 MONO_CHECK_ARG_NULL (dest);
3627 g_assert (dest->obj.vtable->klass->rank == 1);
3628 g_assert (start_index >= 0);
3629 g_assert (length >= 0);
3630 g_assert (start_index + length <= mono_array_length (dest));
3632 element_size = mono_array_element_size (dest->obj.vtable->klass);
3634 dest_addr = mono_array_addr_with_size (dest, element_size, start_index);
3636 memcpy (dest_addr, src, length * element_size);
3640 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr, gint32 offset)
3644 MONO_ARCH_SAVE_REGS;
3646 return *(gpointer*)(p + offset);
3650 ves_icall_System_Runtime_InteropServices_Marshal_ReadByte (gpointer ptr, gint32 offset)
3654 MONO_ARCH_SAVE_REGS;
3656 return *(unsigned char*)(p + offset);
3660 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt16 (gpointer ptr, gint32 offset)
3664 MONO_ARCH_SAVE_REGS;
3666 return *(gint16*)(p + offset);
3670 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt32 (gpointer ptr, gint32 offset)
3674 MONO_ARCH_SAVE_REGS;
3676 return *(gint32*)(p + offset);
3680 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt64 (gpointer ptr, gint32 offset)
3684 MONO_ARCH_SAVE_REGS;
3686 return *(gint64*)(p + offset);
3690 ves_icall_System_Runtime_InteropServices_Marshal_WriteByte (gpointer ptr, gint32 offset, unsigned char val)
3694 MONO_ARCH_SAVE_REGS;
3696 *(unsigned char*)(p + offset) = val;
3700 ves_icall_System_Runtime_InteropServices_Marshal_WriteIntPtr (gpointer ptr, gint32 offset, gpointer val)
3704 MONO_ARCH_SAVE_REGS;
3706 *(gpointer*)(p + offset) = val;
3710 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt16 (gpointer ptr, gint32 offset, gint16 val)
3714 MONO_ARCH_SAVE_REGS;
3716 *(gint16*)(p + offset) = val;
3720 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt32 (gpointer ptr, gint32 offset, gint32 val)
3724 MONO_ARCH_SAVE_REGS;
3726 *(gint32*)(p + offset) = val;
3730 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt64 (gpointer ptr, gint32 offset, gint64 val)
3734 MONO_ARCH_SAVE_REGS;
3736 *(gint64*)(p + offset) = val;
3740 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (char *ptr)
3742 MONO_ARCH_SAVE_REGS;
3744 return mono_string_new (mono_domain_get (), ptr);
3748 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len (char *ptr, gint32 len)
3750 MONO_ARCH_SAVE_REGS;
3752 return mono_string_new_len (mono_domain_get (), ptr, len);
3756 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni (guint16 *ptr)
3758 MonoDomain *domain = mono_domain_get ();
3762 MONO_ARCH_SAVE_REGS;
3767 return mono_string_new_utf16 (domain, ptr, len);
3771 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len (guint16 *ptr, gint32 len)
3773 MonoDomain *domain = mono_domain_get ();
3775 MONO_ARCH_SAVE_REGS;
3777 return mono_string_new_utf16 (domain, ptr, len);
3781 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR (gpointer ptr)
3783 MONO_ARCH_SAVE_REGS;
3785 g_warning ("PtrToStringBSTR not implemented");
3786 g_assert_not_reached ();
3792 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
3794 MONO_ARCH_SAVE_REGS;
3796 return (GetLastError ());
3800 ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype)
3804 MONO_ARCH_SAVE_REGS;
3806 MONO_CHECK_ARG_NULL (rtype);
3808 klass = mono_class_from_mono_type (rtype->type);
3810 return mono_class_native_size (klass, NULL);
3814 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old)
3819 MONO_ARCH_SAVE_REGS;
3821 MONO_CHECK_ARG_NULL (obj);
3822 MONO_CHECK_ARG_NULL (dst);
3824 method = mono_marshal_get_struct_to_ptr (obj->vtable->klass);
3828 pa [2] = &delete_old;
3830 mono_runtime_invoke (method, NULL, pa, NULL);
3834 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, MonoObject *dst)
3839 MONO_ARCH_SAVE_REGS;
3841 MONO_CHECK_ARG_NULL (src);
3842 MONO_CHECK_ARG_NULL (dst);
3844 method = mono_marshal_get_ptr_to_struct (dst->vtable->klass);
3849 mono_runtime_invoke (method, NULL, pa, NULL);
3853 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer src, MonoReflectionType *type)
3855 MonoDomain *domain = mono_domain_get ();
3858 MONO_ARCH_SAVE_REGS;
3860 MONO_CHECK_ARG_NULL (src);
3861 MONO_CHECK_ARG_NULL (type);
3863 res = mono_object_new (domain, mono_class_from_mono_type (type->type));
3865 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (src, res);
3871 ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *type, MonoString *field_name)
3873 MonoMarshalType *info;
3876 int i, match_index = -1;
3878 MONO_ARCH_SAVE_REGS;
3880 MONO_CHECK_ARG_NULL (type);
3881 MONO_CHECK_ARG_NULL (field_name);
3883 fname = mono_string_to_utf8 (field_name);
3884 klass = mono_class_from_mono_type (type->type);
3886 while(klass && match_index == -1) {
3887 for (i = 0; i < klass->field.count; ++i) {
3888 if (*fname == *klass->fields [i].name && strcmp (fname, klass->fields [i].name) == 0) {
3894 if(match_index == -1)
3895 klass = klass->parent;
3900 if(match_index == -1) {
3904 /* Get back original class instance */
3905 klass = mono_class_from_mono_type (type->type);
3907 tmp = g_strdup_printf ("Field passed in is not a marshaled member of the type %s", klass->name);
3908 exc = mono_get_exception_argument ("fieldName", tmp);
3911 mono_raise_exception ((MonoException*)exc);
3914 info = mono_marshal_load_type_info (klass);
3915 return info->fields [match_index].offset;
3919 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString *string)
3921 MONO_ARCH_SAVE_REGS;
3923 return mono_string_to_utf8 (string);
3927 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni (MonoString *string)
3929 MONO_ARCH_SAVE_REGS;
3931 return g_memdup (mono_string_chars (string), mono_string_length (string)*2);
3935 mono_struct_delete_old (MonoClass *klass, char *ptr)
3937 MonoMarshalType *info;
3940 info = mono_marshal_load_type_info (klass);
3942 for (i = 0; i < info->num_fields; i++) {
3943 MonoMarshalNative ntype;
3944 MonoMarshalConv conv;
3945 MonoType *ftype = info->fields [i].field->type;
3948 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
3951 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE,
3952 klass->unicode, &conv);
3954 cpos = ptr + info->fields [i].offset;
3957 case MONO_MARSHAL_CONV_NONE:
3958 if (MONO_TYPE_ISSTRUCT (ftype)) {
3959 mono_struct_delete_old (ftype->data.klass, cpos);
3963 case MONO_MARSHAL_CONV_STR_LPWSTR:
3964 case MONO_MARSHAL_CONV_STR_LPSTR:
3965 case MONO_MARSHAL_CONV_STR_LPTSTR:
3966 case MONO_MARSHAL_CONV_STR_BSTR:
3967 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
3968 case MONO_MARSHAL_CONV_STR_TBSTR:
3969 g_free (*(gpointer *)cpos);
3978 ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure (gpointer src, MonoReflectionType *type)
3982 MONO_ARCH_SAVE_REGS;
3984 MONO_CHECK_ARG_NULL (src);
3985 MONO_CHECK_ARG_NULL (type);
3987 klass = mono_class_from_mono_type (type->type);
3989 mono_struct_delete_old (klass, (char *)src);
3993 mono_marshal_load_type_info (MonoClass* klass)
3995 int i, j, count = 0, native_size = 0;
3996 MonoMarshalType *info;
3999 g_assert (klass != NULL);
4001 if (klass->marshal_info)
4002 return klass->marshal_info;
4005 mono_class_init (klass);
4007 for (i = 0; i < klass->field.count; ++i) {
4008 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
4013 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
4015 klass->marshal_info = info = g_malloc0 (sizeof (MonoMarshalType) + sizeof (MonoMarshalField) * count);
4016 info->num_fields = count;
4018 /* Try to find a size for this type in metadata */
4019 mono_metadata_packing_from_typedef (klass->image, klass->type_token, NULL, &native_size);
4021 if (klass->parent) {
4022 int parent_size = mono_class_native_size (klass->parent, NULL);
4024 /* Add parent size to real size */
4025 native_size += parent_size;
4026 info->native_size = parent_size;
4029 for (j = i = 0; i < klass->field.count; ++i) {
4032 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
4035 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL)
4036 mono_metadata_field_info (klass->image, klass->field.first + i,
4037 NULL, NULL, &info->fields [j].mspec);
4039 info->fields [j].field = &klass->fields [i];
4042 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
4043 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
4044 size = mono_marshal_type_size (klass->fields [i].type, info->fields [j].mspec,
4045 &align, TRUE, klass->unicode);
4046 align = klass->packing_size ? MIN (klass->packing_size, align): align;
4047 info->fields [j].offset = info->native_size;
4048 info->fields [j].offset += align - 1;
4049 info->fields [j].offset &= ~(align - 1);
4050 info->native_size = info->fields [j].offset + size;
4052 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
4054 info->fields [j].offset = klass->fields [i].offset - sizeof (MonoObject);
4055 info->native_size = klass->instance_size - sizeof (MonoObject);
4061 if(layout != TYPE_ATTRIBUTE_AUTO_LAYOUT) {
4062 info->native_size = MAX (native_size, info->native_size);
4065 if (info->native_size & (klass->min_align - 1)) {
4066 info->native_size += klass->min_align - 1;
4067 info->native_size &= ~(klass->min_align - 1);
4070 return klass->marshal_info;
4074 * mono_class_native_size:
4077 * Returns: the native size of an object instance (when marshaled
4078 * to unmanaged code)
4081 mono_class_native_size (MonoClass *klass, guint32 *align)
4084 if (!klass->marshal_info)
4085 mono_marshal_load_type_info (klass);
4088 *align = klass->min_align;
4090 return klass->marshal_info->native_size;
4094 * mono_type_native_stack_size:
4095 * @t: the type to return the size it uses on the stack
4097 * Returns: the number of bytes required to hold an instance of this
4098 * type on the native stack
4101 mono_type_native_stack_size (MonoType *t, gint *align)
4105 g_assert (t != NULL);
4116 case MONO_TYPE_BOOLEAN:
4117 case MONO_TYPE_CHAR:
4126 case MONO_TYPE_STRING:
4127 case MONO_TYPE_OBJECT:
4128 case MONO_TYPE_CLASS:
4129 case MONO_TYPE_SZARRAY:
4131 case MONO_TYPE_FNPTR:
4132 case MONO_TYPE_ARRAY:
4133 case MONO_TYPE_TYPEDBYREF:
4144 case MONO_TYPE_VALUETYPE: {
4147 if (t->data.klass->enumtype)
4148 return mono_type_native_stack_size (t->data.klass->enum_basetype, align);
4150 size = mono_class_native_size (t->data.klass, align);
4151 *align = *align + 3;
4161 g_error ("type 0x%02x unknown", t->type);
4167 mono_marshal_type_size (MonoType *type, MonoMarshalSpec *mspec, gint32 *align,
4168 gboolean as_field, gboolean unicode)
4170 MonoMarshalNative native_type = mono_type_to_unmanaged (type, mspec, as_field, unicode, NULL);
4173 switch (native_type) {
4174 case MONO_NATIVE_BOOLEAN:
4177 case MONO_NATIVE_I1:
4178 case MONO_NATIVE_U1:
4181 case MONO_NATIVE_I2:
4182 case MONO_NATIVE_U2:
4185 case MONO_NATIVE_I4:
4186 case MONO_NATIVE_U4:
4187 case MONO_NATIVE_ERROR:
4190 case MONO_NATIVE_I8:
4191 case MONO_NATIVE_U8:
4194 case MONO_NATIVE_R4:
4197 case MONO_NATIVE_R8:
4200 case MONO_NATIVE_INT:
4201 case MONO_NATIVE_UINT:
4202 case MONO_NATIVE_LPSTR:
4203 case MONO_NATIVE_LPWSTR:
4204 case MONO_NATIVE_LPTSTR:
4205 case MONO_NATIVE_BSTR:
4206 case MONO_NATIVE_ANSIBSTR:
4207 case MONO_NATIVE_TBSTR:
4208 case MONO_NATIVE_LPARRAY:
4209 case MONO_NATIVE_SAFEARRAY:
4210 case MONO_NATIVE_IUNKNOWN:
4211 case MONO_NATIVE_IDISPATCH:
4212 case MONO_NATIVE_INTERFACE:
4213 case MONO_NATIVE_ASANY:
4214 case MONO_NATIVE_VARIANTBOOL:
4215 case MONO_NATIVE_FUNC:
4216 case MONO_NATIVE_LPSTRUCT:
4218 return sizeof (gpointer);
4219 case MONO_NATIVE_STRUCT:
4220 klass = mono_class_from_mono_type (type);
4221 return mono_class_native_size (klass, align);
4222 case MONO_NATIVE_BYVALTSTR: {
4223 int esize = unicode ? 2: 1;
4226 return mspec->data.array_data.num_elem * esize;
4228 case MONO_NATIVE_BYVALARRAY: {
4230 klass = mono_class_from_mono_type (type);
4231 esize = mono_class_native_size (klass->element_class, align);
4233 return mspec->data.array_data.num_elem * esize;
4235 case MONO_NATIVE_CUSTOM:
4236 g_assert_not_reached ();
4238 case MONO_NATIVE_CURRENCY:
4239 case MONO_NATIVE_VBBYREFSTR:
4241 g_error ("native type %02x not implemented", native_type);
4244 g_assert_not_reached ();