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);
45 #ifdef DEBUG_RUNTIME_CODE
47 indenter (MonoDisHelper *dh, MonoMethod *method, guint32 ip_offset)
49 return g_strdup (" ");
52 static MonoDisHelper marshal_dh = {
63 mono_delegate_to_ftnptr (MonoDelegate *delegate)
65 MonoMethod *method, *wrapper;
71 if (delegate->delegate_trampoline)
72 return delegate->delegate_trampoline;
74 klass = ((MonoObject *)delegate)->vtable->klass;
75 g_assert (klass->delegate);
77 method = delegate->method_info->method;
78 wrapper = mono_marshal_get_managed_wrapper (method, delegate->target);
80 delegate->delegate_trampoline = mono_compile_method (wrapper);
82 return delegate->delegate_trampoline;
86 mono_array_to_savearray (MonoArray *array)
91 g_assert_not_reached ();
96 mono_array_to_lparray (MonoArray *array)
101 /* fixme: maybe we need to make a copy */
102 return array->vector;
106 mono_string_utf8_to_builder (MonoStringBuilder *sb, char *text)
108 GError *error = NULL;
118 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
120 if (items_written > sb->capacity)
121 items_written = sb->capacity;
124 memcpy (sb->chars->vector, ut, items_written * 2);
125 sb->length = items_written;
127 g_error_free (error);
133 mono_string_builder_to_utf8 (MonoStringBuilder *sb)
140 res = g_malloc (sb->capacity + 1);
142 /* fixme: copy the content of the string builder? */
149 mono_string_to_ansibstr (MonoString *string_obj)
151 g_error ("implement me");
156 mono_string_to_bstr (MonoString *string_obj)
158 g_error ("implement me");
163 mono_string_to_byvalstr (gpointer dst, MonoString *src, int size)
168 g_assert (dst != NULL);
171 memset (dst, 0, size);
176 s = mono_string_to_utf8 (src);
177 len = MIN (size, strlen (s));
178 memcpy (dst, s, len);
181 *((char *)dst + size - 1) = 0;
185 mono_string_to_byvalwstr (gpointer dst, MonoString *src, int size)
189 g_assert (dst != NULL);
193 memset (dst, 0, size);
197 len = MIN (size, (mono_string_length (src) * 2));
198 memcpy (dst, mono_string_chars (src), len);
200 *((char *)dst + size - 1) = 0;
201 *((char *)dst + size - 2) = 0;
206 mono_find_method_by_name (MonoClass *klass, const char *name, int param_count)
208 MonoMethod *res = NULL;
211 for (i = 0; i < klass->method.count; ++i) {
212 if ((klass->methods [i]->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
213 klass->methods [i]->name[0] == name [0] &&
214 !strcmp (name, klass->methods [i]->name) &&
215 klass->methods [i]->signature->param_count == param_count) {
216 res = klass->methods [i];
224 mono_mb_free (MonoMethodBuilder *mb)
226 g_list_free (mb->locals_list);
231 mono_mb_new (MonoClass *klass, const char *name, MonoWrapperType type)
233 MonoMethodBuilder *mb;
236 g_assert (klass != NULL);
237 g_assert (name != NULL);
239 mb = g_new0 (MonoMethodBuilder, 1);
241 mb->method = m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
244 m->name = g_strdup (name);
246 m->inline_count = -1;
247 m->wrapper_type = type;
250 mb->code = g_malloc (mb->code_size);
256 mono_mb_add_local (MonoMethodBuilder *mb, MonoType *type)
258 int res = mb->locals;
260 g_assert (mb != NULL);
261 g_assert (type != NULL);
263 mb->locals_list = g_list_append (mb->locals_list, type);
270 mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack)
272 MonoMethodHeader *header;
276 g_assert (mb != NULL);
278 ((MonoMethodNormal *)mb->method)->header = header = (MonoMethodHeader *)
279 g_malloc0 (sizeof (MonoMethodHeader) + mb->locals * sizeof (MonoType *));
284 header->max_stack = max_stack;
286 for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
287 header->locals [i] = (MonoType *)l->data;
290 mb->method->signature = signature;
291 header->code = mb->code;
292 header->code_size = mb->pos;
293 header->num_locals = mb->locals;
295 #ifdef DEBUG_RUNTIME_CODE
296 printf ("RUNTIME CODE FOR %s\n", mono_method_full_name (mb->method, TRUE));
297 printf ("%s\n", mono_disasm_code (&marshal_dh, mb->method, mb->code, mb->code + mb->pos));
304 mono_mb_add_data (MonoMethodBuilder *mb, gpointer data)
306 MonoMethodWrapper *mw;
308 g_assert (mb != NULL);
310 mw = (MonoMethodWrapper *)mb->method;
312 mw->data = g_list_append (mw->data, data);
314 return g_list_length (mw->data);
318 mono_mb_patch_addr (MonoMethodBuilder *mb, int pos, int value)
320 mb->code [pos] = value & 0xff;
321 mb->code [pos + 1] = (value >> 8) & 0xff;
322 mb->code [pos + 2] = (value >> 16) & 0xff;
323 mb->code [pos + 3] = (value >> 24) & 0xff;
327 mono_mb_patch_addr_s (MonoMethodBuilder *mb, int pos, gint8 value)
329 *((gint8 *)(&mb->code [pos])) = value;
333 mono_mb_emit_byte (MonoMethodBuilder *mb, guint8 op)
335 if (mb->pos >= mb->code_size) {
337 mb->code = g_realloc (mb->code, mb->code_size);
340 mb->code [mb->pos++] = op;
344 mono_mb_emit_ldflda (MonoMethodBuilder *mb, gint32 offset)
346 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
347 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
350 mono_mb_emit_icon (mb, offset);
351 mono_mb_emit_byte (mb, CEE_ADD);
356 mono_mb_emit_proxy_check (MonoMethodBuilder *mb, int branch_code)
359 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoObject, vtable));
360 mono_mb_emit_byte (mb, CEE_LDIND_I);
361 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoVTable, klass));
362 mono_mb_emit_byte (mb, CEE_ADD);
363 mono_mb_emit_byte (mb, CEE_LDIND_I);
364 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
365 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
366 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_defaults.transparent_proxy_class));
367 mono_mb_emit_byte (mb, branch_code);
369 mono_mb_emit_i4 (mb, 0);
374 mono_mb_emit_i4 (MonoMethodBuilder *mb, gint32 data)
376 if ((mb->pos + 4) >= mb->code_size) {
378 mb->code = g_realloc (mb->code, mb->code_size);
381 mono_mb_patch_addr (mb, mb->pos, data);
386 mono_mb_emit_i2 (MonoMethodBuilder *mb, gint16 data)
388 if ((mb->pos + 2) >= mb->code_size) {
390 mb->code = g_realloc (mb->code, mb->code_size);
393 mb->code [mb->pos] = data & 0xff;
394 mb->code [mb->pos + 1] = (data >> 8) & 0xff;
399 mono_mb_emit_ldarg (MonoMethodBuilder *mb, guint argnum)
402 mono_mb_emit_byte (mb, CEE_LDARG_0 + argnum);
403 } else if (argnum < 256) {
404 mono_mb_emit_byte (mb, CEE_LDARG_S);
405 mono_mb_emit_byte (mb, argnum);
407 mono_mb_emit_byte (mb, CEE_PREFIX1);
408 mono_mb_emit_byte (mb, CEE_LDARG);
409 mono_mb_emit_i2 (mb, argnum);
414 mono_mb_emit_ldarg_addr (MonoMethodBuilder *mb, guint argnum)
417 mono_mb_emit_byte (mb, CEE_LDARGA_S);
418 mono_mb_emit_byte (mb, argnum);
420 mono_mb_emit_byte (mb, CEE_PREFIX1);
421 mono_mb_emit_byte (mb, CEE_LDARGA);
422 mono_mb_emit_i2 (mb, argnum);
427 mono_mb_emit_ldloc_addr (MonoMethodBuilder *mb, guint locnum)
430 mono_mb_emit_byte (mb, CEE_LDLOCA_S);
431 mono_mb_emit_byte (mb, locnum);
433 mono_mb_emit_byte (mb, CEE_PREFIX1);
434 mono_mb_emit_byte (mb, CEE_LDLOCA);
435 mono_mb_emit_i2 (mb, locnum);
440 mono_mb_emit_ldloc (MonoMethodBuilder *mb, guint num)
443 mono_mb_emit_byte (mb, CEE_LDLOC_0 + num);
444 } else if (num < 256) {
445 mono_mb_emit_byte (mb, CEE_LDLOC_S);
446 mono_mb_emit_byte (mb, num);
448 mono_mb_emit_byte (mb, CEE_PREFIX1);
449 mono_mb_emit_byte (mb, CEE_LDLOC);
450 mono_mb_emit_i2 (mb, num);
455 mono_mb_emit_stloc (MonoMethodBuilder *mb, guint num)
458 mono_mb_emit_byte (mb, CEE_STLOC_0 + num);
459 } else if (num < 256) {
460 mono_mb_emit_byte (mb, CEE_STLOC_S);
461 mono_mb_emit_byte (mb, num);
463 mono_mb_emit_byte (mb, CEE_PREFIX1);
464 mono_mb_emit_byte (mb, CEE_STLOC);
465 mono_mb_emit_i2 (mb, num);
470 mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value)
472 if (value >= -1 && value < 8) {
473 mono_mb_emit_byte (mb, CEE_LDC_I4_0 + value);
474 } else if (value >= -128 && value <= 127) {
475 mono_mb_emit_byte (mb, CEE_LDC_I4_S);
476 mono_mb_emit_byte (mb, value);
478 mono_mb_emit_byte (mb, CEE_LDC_I4);
479 mono_mb_emit_i4 (mb, value);
484 mono_mb_emit_managed_call (MonoMethodBuilder *mb, MonoMethod *method, MonoMethodSignature *opt_sig)
487 opt_sig = method->signature;
488 mono_mb_emit_byte (mb, CEE_PREFIX1);
489 mono_mb_emit_byte (mb, CEE_LDFTN);
490 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
491 mono_mb_emit_byte (mb, CEE_CALLI);
492 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, opt_sig));
496 mono_mb_emit_native_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, gpointer func)
498 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
499 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
500 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, func));
501 mono_mb_emit_byte (mb, CEE_CALLI);
502 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
506 mono_mb_emit_exception (MonoMethodBuilder *mb)
508 /* fixme: we need a better way to throw exception,
509 * supporting several exception types and messages */
510 static MonoMethod *missing_method_ctor = NULL;
512 if (!missing_method_ctor) {
513 MonoClass *mme = mono_class_from_name (mono_defaults.corlib, "System", "MissingMethodException");
515 mono_class_init (mme);
516 for (i = 0; i < mme->method.count; ++i) {
517 if (strcmp (mme->methods [i]->name, ".ctor") == 0 && mme->methods [i]->signature->param_count == 0) {
518 missing_method_ctor = mme->methods [i];
523 mono_mb_emit_byte (mb, CEE_NEWOBJ);
524 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, missing_method_ctor));
525 mono_mb_emit_byte (mb, CEE_THROW);
530 mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint16 local, gint32 incr)
532 mono_mb_emit_ldloc (mb, local);
533 mono_mb_emit_icon (mb, incr);
534 mono_mb_emit_byte (mb, CEE_ADD);
535 mono_mb_emit_stloc (mb, local);
539 emit_ptr_to_str_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv,
540 int usize, int msize, MonoMarshalSpec *mspec)
543 case MONO_MARSHAL_CONV_BOOL_I4:
544 mono_mb_emit_byte (mb, CEE_LDLOC_0);
545 mono_mb_emit_byte (mb, CEE_LDIND_I);
546 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
547 mono_mb_emit_byte (mb, 5);
548 mono_mb_emit_byte (mb, CEE_LDLOC_1);
549 mono_mb_emit_byte (mb, CEE_LDC_I4_1);
550 mono_mb_emit_byte (mb, CEE_STIND_I1);
551 mono_mb_emit_byte (mb, CEE_BR_S);
552 mono_mb_emit_byte (mb, 3);
553 mono_mb_emit_byte (mb, CEE_LDLOC_1);
554 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
555 mono_mb_emit_byte (mb, CEE_STIND_I1);
557 case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
561 if (type->type == MONO_TYPE_SZARRAY) {
562 eclass = mono_class_from_mono_type (type->data.type);
564 g_assert_not_reached ();
567 if (eclass->valuetype)
568 esize = mono_class_instance_size (eclass) - sizeof (MonoObject);
570 esize = sizeof (gpointer);
572 /* create a new array */
573 mono_mb_emit_byte (mb, CEE_LDLOC_1);
574 mono_mb_emit_icon (mb, mspec->num_elem);
575 mono_mb_emit_byte (mb, CEE_NEWARR);
576 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eclass));
577 mono_mb_emit_byte (mb, CEE_STIND_I);
579 /* copy the elements */
580 mono_mb_emit_byte (mb, CEE_LDLOC_1);
581 mono_mb_emit_byte (mb, CEE_LDIND_I);
582 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
583 mono_mb_emit_byte (mb, CEE_ADD);
584 mono_mb_emit_byte (mb, CEE_LDLOC_0);
585 mono_mb_emit_icon (mb, mspec->num_elem * esize);
586 mono_mb_emit_byte (mb, CEE_PREFIX1);
587 mono_mb_emit_byte (mb, CEE_CPBLK);
591 case MONO_MARSHAL_CONV_STR_BYVALSTR:
592 mono_mb_emit_byte (mb, CEE_LDLOC_1);
593 mono_mb_emit_byte (mb, CEE_LDLOC_0);
594 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
595 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
596 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
597 mono_mb_emit_byte (mb, CEE_STIND_I);
599 case MONO_MARSHAL_CONV_STR_LPTSTR:
600 case MONO_MARSHAL_CONV_STR_LPSTR:
601 mono_mb_emit_byte (mb, CEE_LDLOC_1);
602 mono_mb_emit_byte (mb, CEE_LDLOC_0);
603 mono_mb_emit_byte (mb, CEE_LDIND_I);
604 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
605 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
606 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
607 mono_mb_emit_byte (mb, CEE_STIND_I);
609 case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
610 MonoClass *klass = mono_class_from_mono_type (type);
611 int src_var, dst_var;
613 src_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
614 dst_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
616 /* *dst = new object */
617 mono_mb_emit_byte (mb, CEE_LDLOC_1);
618 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
619 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
620 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
621 mono_mb_emit_byte (mb, CEE_STIND_I);
623 /* save the old src pointer */
624 mono_mb_emit_byte (mb, CEE_LDLOC_0);
625 mono_mb_emit_stloc (mb, src_var);
626 /* save the old dst pointer */
627 mono_mb_emit_byte (mb, CEE_LDLOC_1);
628 mono_mb_emit_stloc (mb, dst_var);
630 /* dst = pointer to newly created object data */
631 mono_mb_emit_byte (mb, CEE_LDLOC_1);
632 mono_mb_emit_byte (mb, CEE_LDIND_I);
633 mono_mb_emit_icon (mb, sizeof (MonoObject));
634 mono_mb_emit_byte (mb, CEE_ADD);
635 mono_mb_emit_byte (mb, CEE_STLOC_1);
637 emit_struct_conv (mb, klass, TRUE);
639 /* restore the old src pointer */
640 mono_mb_emit_ldloc (mb, src_var);
641 mono_mb_emit_byte (mb, CEE_STLOC_0);
642 /* restore the old dst pointer */
643 mono_mb_emit_ldloc (mb, dst_var);
644 mono_mb_emit_byte (mb, CEE_STLOC_1);
647 case MONO_MARSHAL_CONV_DEL_FTN: {
648 // fixme: we never convert functions back to delegates, dont
649 // know if thats the correct behaviour
652 case MONO_MARSHAL_CONV_STR_LPWSTR:
653 case MONO_MARSHAL_CONV_STR_BSTR:
654 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
655 case MONO_MARSHAL_CONV_STR_TBSTR:
656 case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
657 case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
658 case MONO_MARSHAL_CONV_STR_BYVALWSTR:
659 case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
661 g_warning ("marshaling conversion %d not implemented", conv);
662 g_assert_not_reached ();
667 emit_str_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, int usize, int msize,
668 MonoMarshalSpec *mspec)
673 case MONO_MARSHAL_CONV_BOOL_I4:
674 mono_mb_emit_byte (mb, CEE_LDLOC_1);
675 mono_mb_emit_byte (mb, CEE_LDLOC_0);
676 mono_mb_emit_byte (mb, CEE_LDIND_U1);
677 mono_mb_emit_byte (mb, CEE_STIND_I4);
679 case MONO_MARSHAL_CONV_STR_LPWSTR:
680 case MONO_MARSHAL_CONV_STR_LPSTR:
681 case MONO_MARSHAL_CONV_STR_LPTSTR:
682 case MONO_MARSHAL_CONV_STR_BSTR:
683 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
684 case MONO_MARSHAL_CONV_STR_TBSTR:
685 /* free space if free == true */
686 mono_mb_emit_byte (mb, CEE_LDLOC_2);
687 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
688 mono_mb_emit_byte (mb, 4);
689 mono_mb_emit_byte (mb, CEE_LDLOC_1);
690 mono_mb_emit_byte (mb, CEE_LDIND_I);
691 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
692 mono_mb_emit_byte (mb, CEE_MONO_FREE);
694 mono_mb_emit_byte (mb, CEE_LDLOC_1);
695 mono_mb_emit_byte (mb, CEE_LDLOC_0);
696 mono_mb_emit_byte (mb, CEE_LDIND_I);
697 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
698 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
699 mono_mb_emit_byte (mb, conv);
700 mono_mb_emit_byte (mb, CEE_STIND_I);
702 case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
703 case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
704 case MONO_MARSHAL_CONV_DEL_FTN:
705 mono_mb_emit_byte (mb, CEE_LDLOC_1);
706 mono_mb_emit_byte (mb, CEE_LDLOC_0);
707 mono_mb_emit_byte (mb, CEE_LDIND_I);
708 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
709 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
710 mono_mb_emit_byte (mb, conv);
711 mono_mb_emit_byte (mb, CEE_STIND_I);
713 case MONO_MARSHAL_CONV_STR_BYVALSTR:
714 case MONO_MARSHAL_CONV_STR_BYVALWSTR: {
718 mono_mb_emit_byte (mb, CEE_LDLOC_1); /* dst */
719 mono_mb_emit_byte (mb, CEE_LDLOC_0);
720 mono_mb_emit_byte (mb, CEE_LDIND_I); /* src String */
721 mono_mb_emit_icon (mb, usize);
722 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
723 mono_mb_emit_byte (mb, CEE_MONO_PROC3);
724 mono_mb_emit_byte (mb, conv);
727 case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
731 if (type->type == MONO_TYPE_SZARRAY) {
732 eclass = mono_class_from_mono_type (type->data.type);
734 g_assert_not_reached ();
737 if (eclass->valuetype)
738 esize = mono_class_native_size (eclass, NULL);
740 esize = sizeof (gpointer);
745 mono_mb_emit_byte (mb, CEE_LDLOC_0);
746 mono_mb_emit_byte (mb, CEE_LDIND_I);
747 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
749 mono_mb_emit_byte (mb, 0);
751 mono_mb_emit_byte (mb, CEE_LDLOC_1);
752 mono_mb_emit_byte (mb, CEE_LDLOC_0);
753 mono_mb_emit_byte (mb, CEE_LDIND_I);
754 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
755 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
756 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
757 mono_mb_emit_byte (mb, CEE_ADD);
758 mono_mb_emit_icon (mb, mspec->num_elem * esize);
759 mono_mb_emit_byte (mb, CEE_PREFIX1);
760 mono_mb_emit_byte (mb, CEE_CPBLK);
761 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
764 case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
765 int src_var, dst_var;
767 src_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
768 dst_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
770 mono_mb_emit_byte (mb, CEE_LDLOC_0);
771 mono_mb_emit_byte (mb, CEE_LDIND_I);
772 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
774 mono_mb_emit_byte (mb, 0);
776 /* save the old src pointer */
777 mono_mb_emit_byte (mb, CEE_LDLOC_0);
778 mono_mb_emit_stloc (mb, src_var);
779 /* save the old dst pointer */
780 mono_mb_emit_byte (mb, CEE_LDLOC_1);
781 mono_mb_emit_stloc (mb, dst_var);
783 /* src = pointer to object data */
784 mono_mb_emit_byte (mb, CEE_LDLOC_0);
785 mono_mb_emit_byte (mb, CEE_LDIND_I);
786 mono_mb_emit_icon (mb, sizeof (MonoObject));
787 mono_mb_emit_byte (mb, CEE_ADD);
788 mono_mb_emit_byte (mb, CEE_STLOC_0);
790 emit_struct_conv (mb, mono_class_from_mono_type (type), FALSE);
792 /* restore the old src pointer */
793 mono_mb_emit_ldloc (mb, src_var);
794 mono_mb_emit_byte (mb, CEE_STLOC_0);
795 /* restore the old dst pointer */
796 mono_mb_emit_ldloc (mb, dst_var);
797 mono_mb_emit_byte (mb, CEE_STLOC_1);
799 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
802 case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
804 g_warning ("marshalling conversion %d not implemented", conv);
805 g_assert_not_reached ();
810 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
812 MonoMarshalType *info;
816 emit_struct_conv(mb, klass->parent, to_object);
818 info = mono_marshal_load_type_info (klass);
820 if (klass->blittable) {
821 mono_mb_emit_byte (mb, CEE_LDLOC_1);
822 mono_mb_emit_byte (mb, CEE_LDLOC_0);
823 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
824 mono_mb_emit_byte (mb, CEE_PREFIX1);
825 mono_mb_emit_byte (mb, CEE_CPBLK);
829 for (i = 0; i < info->num_fields; i++) {
830 MonoMarshalNative ntype;
831 MonoMarshalConv conv;
832 MonoType *ftype = info->fields [i].field->type;
835 gboolean last_field = i < (info->num_fields -1) ? 0 : 1;
837 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
840 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, klass->unicode, &conv);
843 msize = klass->instance_size - info->fields [i].field->offset;
844 usize = info->native_size - info->fields [i].offset;
846 msize = klass->fields [i + 1].offset - info->fields [i].field->offset;
847 usize = info->fields [i + 1].offset - info->fields [i].offset;
849 g_assert ((msize >= 0) && (usize >= 0));
852 case MONO_MARSHAL_CONV_NONE: {
855 if (ftype->byref || ftype->type == MONO_TYPE_I ||
856 ftype->type == MONO_TYPE_U) {
857 mono_mb_emit_byte (mb, CEE_LDLOC_1);
858 mono_mb_emit_byte (mb, CEE_LDLOC_0);
859 mono_mb_emit_byte (mb, CEE_LDIND_I);
860 mono_mb_emit_byte (mb, CEE_STIND_I);
869 #if SIZEOF_VOID_P == 4
872 mono_mb_emit_byte (mb, CEE_LDLOC_1);
873 mono_mb_emit_byte (mb, CEE_LDLOC_0);
874 mono_mb_emit_byte (mb, CEE_LDIND_I4);
875 mono_mb_emit_byte (mb, CEE_STIND_I4);
879 case MONO_TYPE_BOOLEAN:
880 mono_mb_emit_byte (mb, CEE_LDLOC_1);
881 mono_mb_emit_byte (mb, CEE_LDLOC_0);
882 mono_mb_emit_byte (mb, CEE_LDIND_I1);
883 mono_mb_emit_byte (mb, CEE_STIND_I1);
887 mono_mb_emit_byte (mb, CEE_LDLOC_1);
888 mono_mb_emit_byte (mb, CEE_LDLOC_0);
889 mono_mb_emit_byte (mb, CEE_LDIND_I2);
890 mono_mb_emit_byte (mb, CEE_STIND_I2);
894 #if SIZEOF_VOID_P == 8
897 mono_mb_emit_byte (mb, CEE_LDLOC_1);
898 mono_mb_emit_byte (mb, CEE_LDLOC_0);
899 mono_mb_emit_byte (mb, CEE_LDIND_I8);
900 mono_mb_emit_byte (mb, CEE_STIND_I8);
903 mono_mb_emit_byte (mb, CEE_LDLOC_1);
904 mono_mb_emit_byte (mb, CEE_LDLOC_0);
905 mono_mb_emit_byte (mb, CEE_LDIND_R4);
906 mono_mb_emit_byte (mb, CEE_STIND_R4);
909 mono_mb_emit_byte (mb, CEE_LDLOC_1);
910 mono_mb_emit_byte (mb, CEE_LDLOC_0);
911 mono_mb_emit_byte (mb, CEE_LDIND_R8);
912 mono_mb_emit_byte (mb, CEE_STIND_R8);
914 case MONO_TYPE_VALUETYPE:
915 if (ftype->data.klass->enumtype) {
916 t = ftype->data.klass->enum_basetype->type;
919 emit_struct_conv (mb, ftype->data.klass, to_object);
922 g_warning ("marshaling type %02x not implemented", ftype->type);
923 g_assert_not_reached ();
929 emit_ptr_to_str_conv (mb, ftype, conv, usize, msize, info->fields [i].mspec);
931 emit_str_to_ptr_conv (mb, ftype, conv, usize, msize, info->fields [i].mspec);
935 mono_mb_emit_add_to_local (mb, 0, usize);
936 mono_mb_emit_add_to_local (mb, 1, msize);
938 mono_mb_emit_add_to_local (mb, 0, msize);
939 mono_mb_emit_add_to_local (mb, 1, usize);
944 static MonoAsyncResult *
945 mono_delegate_begin_invoke (MonoDelegate *delegate, gpointer *params)
947 MonoMethodMessage *msg;
948 MonoDelegate *async_callback;
952 MonoMethod *method = NULL;
957 klass = delegate->object.vtable->klass;
959 method = mono_get_delegate_invoke (klass);
960 for (i = 0; i < klass->method.count; ++i) {
961 if (klass->methods [i]->name[0] == 'B' &&
962 !strcmp ("BeginInvoke", klass->methods [i]->name)) {
963 method = klass->methods [i];
968 g_assert (method != NULL);
970 im = mono_get_delegate_invoke (method->klass);
972 msg = mono_method_call_message_new (method, params, im, &async_callback, &state);
974 return mono_thread_pool_add ((MonoObject *)delegate, msg, async_callback, state);
978 mono_mb_emit_save_args (MonoMethodBuilder *mb, MonoMethodSignature *sig, gboolean save_this)
980 int i, params_var, tmp_var;
982 /* allocate local (pointer) *params[] */
983 params_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
984 /* allocate local (pointer) tmp */
985 tmp_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
987 /* alloate space on stack to store an array of pointers to the arguments */
988 mono_mb_emit_icon (mb, sizeof (gpointer) * (sig->param_count + 1));
989 mono_mb_emit_byte (mb, CEE_PREFIX1);
990 mono_mb_emit_byte (mb, CEE_LOCALLOC);
991 mono_mb_emit_stloc (mb, params_var);
994 mono_mb_emit_ldloc (mb, params_var);
995 mono_mb_emit_stloc (mb, tmp_var);
997 if (save_this && sig->hasthis) {
998 mono_mb_emit_ldloc (mb, tmp_var);
999 mono_mb_emit_ldarg_addr (mb, 0);
1000 mono_mb_emit_byte (mb, CEE_STIND_I);
1001 /* tmp = tmp + sizeof (gpointer) */
1002 if (sig->param_count)
1003 mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
1007 for (i = 0; i < sig->param_count; i++) {
1008 mono_mb_emit_ldloc (mb, tmp_var);
1009 mono_mb_emit_ldarg_addr (mb, i + sig->hasthis);
1010 mono_mb_emit_byte (mb, CEE_STIND_I);
1011 /* tmp = tmp + sizeof (gpointer) */
1012 if (i < (sig->param_count - 1))
1013 mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
1020 mono_signature_to_name (MonoMethodSignature *sig, const char *prefix)
1024 GString *res = g_string_new ("");
1027 g_string_append (res, prefix);
1028 g_string_append_c (res, '_');
1031 mono_type_get_desc (res, sig->ret, FALSE);
1033 for (i = 0; i < sig->param_count; ++i) {
1034 g_string_append_c (res, '_');
1035 mono_type_get_desc (res, sig->params [i], FALSE);
1038 g_string_free (res, FALSE);
1043 mono_marshal_get_delegate_begin_invoke (MonoMethod *method)
1045 MonoMethodSignature *sig;
1046 static MonoMethodSignature *csig = NULL;
1047 MonoMethodBuilder *mb;
1053 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1054 !strcmp (method->name, "BeginInvoke"));
1056 sig = method->signature;
1058 cache = method->klass->image->delegate_begin_invoke_cache;
1059 if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1062 g_assert (sig->hasthis);
1065 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1066 csig = g_malloc0 (sigsize);
1068 /* MonoAsyncResult * begin_invoke (MonoDelegate *delegate, gpointer params[]) */
1069 csig->param_count = 2;
1070 csig->ret = &mono_defaults.object_class->byval_arg;
1071 csig->params [0] = &mono_defaults.object_class->byval_arg;
1072 csig->params [1] = &mono_defaults.int_class->byval_arg;
1075 name = mono_signature_to_name (sig, "begin_invoke");
1076 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_BEGIN_INVOKE);
1079 mb->method->save_lmf = 1;
1081 params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1083 mono_mb_emit_ldarg (mb, 0);
1084 mono_mb_emit_ldloc (mb, params_var);
1085 mono_mb_emit_native_call (mb, csig, mono_delegate_begin_invoke);
1086 mono_mb_emit_byte (mb, CEE_RET);
1088 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1090 g_hash_table_insert (cache, sig, res);
1095 mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params)
1097 MonoDomain *domain = mono_domain_get ();
1098 MonoAsyncResult *ares;
1099 MonoMethod *method = NULL;
1100 MonoMethodSignature *sig;
1101 MonoMethodMessage *msg;
1102 MonoObject *res, *exc;
1103 MonoArray *out_args;
1107 g_assert (delegate);
1109 if (!delegate->method_info || !delegate->method_info->method)
1110 g_assert_not_reached ();
1112 klass = delegate->object.vtable->klass;
1114 for (i = 0; i < klass->method.count; ++i) {
1115 if (klass->methods [i]->name[0] == 'E' &&
1116 !strcmp ("EndInvoke", klass->methods [i]->name)) {
1117 method = klass->methods [i];
1122 g_assert (method != NULL);
1124 sig = method->signature;
1126 msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1128 ares = mono_array_get (msg->args, gpointer, sig->param_count - 1);
1131 res = mono_thread_pool_finish (ares, &out_args, &exc);
1134 char *strace = mono_string_to_utf8 (((MonoException*)exc)->stack_trace);
1136 tmp = g_strdup_printf ("%s\nException Rethrown at:\n", strace);
1138 ((MonoException*)exc)->stack_trace = mono_string_new (domain, tmp);
1140 mono_raise_exception ((MonoException*)exc);
1143 mono_method_return_message_restore (method, params, out_args);
1148 mono_mb_emit_restore_result (MonoMethodBuilder *mb, MonoType *return_type)
1150 if (return_type->byref)
1151 return_type = &mono_defaults.int_class->byval_arg;
1152 else if (return_type->type == MONO_TYPE_VALUETYPE && return_type->data.klass->enumtype)
1153 return_type = return_type->data.klass->enum_basetype;
1155 switch (return_type->type) {
1156 case MONO_TYPE_VOID:
1157 g_assert_not_reached ();
1160 case MONO_TYPE_STRING:
1161 case MONO_TYPE_CLASS:
1162 case MONO_TYPE_OBJECT:
1163 case MONO_TYPE_ARRAY:
1164 case MONO_TYPE_SZARRAY:
1168 case MONO_TYPE_BOOLEAN:
1169 mono_mb_emit_byte (mb, CEE_UNBOX);
1170 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1171 mono_mb_emit_byte (mb, CEE_LDIND_U1);
1174 mono_mb_emit_byte (mb, CEE_UNBOX);
1175 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1176 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1179 case MONO_TYPE_CHAR:
1180 mono_mb_emit_byte (mb, CEE_UNBOX);
1181 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1182 mono_mb_emit_byte (mb, CEE_LDIND_U2);
1185 mono_mb_emit_byte (mb, CEE_UNBOX);
1186 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1187 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1191 mono_mb_emit_byte (mb, CEE_UNBOX);
1192 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1193 mono_mb_emit_byte (mb, CEE_LDIND_I);
1196 mono_mb_emit_byte (mb, CEE_UNBOX);
1197 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1198 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1201 mono_mb_emit_byte (mb, CEE_UNBOX);
1202 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1203 mono_mb_emit_byte (mb, CEE_LDIND_U4);
1207 mono_mb_emit_byte (mb, CEE_UNBOX);
1208 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1209 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1212 mono_mb_emit_byte (mb, CEE_UNBOX);
1213 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1214 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1217 mono_mb_emit_byte (mb, CEE_UNBOX);
1218 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1219 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1221 case MONO_TYPE_VALUETYPE: {
1223 mono_mb_emit_byte (mb, CEE_UNBOX);
1224 class = mono_mb_add_data (mb, mono_class_from_mono_type (return_type));
1225 mono_mb_emit_i4 (mb, class);
1226 mono_mb_emit_byte (mb, CEE_LDOBJ);
1227 mono_mb_emit_i4 (mb, class);
1231 g_warning ("type 0x%x not handled", return_type->type);
1232 g_assert_not_reached ();
1235 mono_mb_emit_byte (mb, CEE_RET);
1239 mono_marshal_get_delegate_end_invoke (MonoMethod *method)
1241 MonoMethodSignature *sig;
1242 static MonoMethodSignature *csig = NULL;
1243 MonoMethodBuilder *mb;
1249 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1250 !strcmp (method->name, "EndInvoke"));
1252 sig = method->signature;
1254 cache = method->klass->image->delegate_end_invoke_cache;
1255 if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1258 g_assert (sig->hasthis);
1261 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1262 csig = g_malloc0 (sigsize);
1264 /* MonoObject *end_invoke (MonoDelegate *delegate, gpointer params[]) */
1265 csig->param_count = 2;
1266 csig->ret = &mono_defaults.object_class->byval_arg;
1267 csig->params [0] = &mono_defaults.object_class->byval_arg;
1268 csig->params [1] = &mono_defaults.int_class->byval_arg;
1271 name = mono_signature_to_name (sig, "end_invoke");
1272 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_END_INVOKE);
1275 mb->method->save_lmf = 1;
1277 params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1279 mono_mb_emit_ldarg (mb, 0);
1280 mono_mb_emit_ldloc (mb, params_var);
1281 mono_mb_emit_native_call (mb, csig, mono_delegate_end_invoke);
1283 if (sig->ret->type == MONO_TYPE_VOID) {
1284 mono_mb_emit_byte (mb, CEE_POP);
1285 mono_mb_emit_byte (mb, CEE_RET);
1287 mono_mb_emit_restore_result (mb, sig->ret);
1289 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1291 g_hash_table_insert (cache, sig, res);
1297 mono_remoting_wrapper (MonoMethod *method, gpointer *params)
1299 MonoMethodMessage *msg;
1300 MonoTransparentProxy *this;
1301 MonoObject *res, *exc;
1302 MonoArray *out_args;
1304 this = *((MonoTransparentProxy **)params [0]);
1307 g_assert (((MonoObject *)this)->vtable->klass == mono_defaults.transparent_proxy_class);
1309 /* skip the this pointer */
1312 if (this->klass->contextbound && this->rp->context == (MonoObject *) mono_context_get ())
1315 MonoMethodSignature *sig = method->signature;
1316 int count = sig->param_count;
1317 gpointer mparams[count];
1319 for (i=0; i<count; i++) {
1320 MonoClass *class = mono_class_from_mono_type (sig->params [i]);
1321 if (class->valuetype) {
1322 if (sig->params [i]->byref)
1323 mparams[i] = *((gpointer *)params [i]);
1325 mparams[i] = params [i];
1327 mparams[i] = *((gpointer**)params [i]);
1331 return mono_runtime_invoke (method, this->rp->unwrapped_server, mparams, NULL);
1334 msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1336 res = mono_remoting_invoke ((MonoObject *)this->rp, msg, &exc, &out_args);
1339 mono_raise_exception ((MonoException *)exc);
1341 mono_method_return_message_restore (method, params, out_args);
1347 mono_marshal_get_remoting_invoke (MonoMethod *method)
1349 MonoMethodSignature *sig;
1350 static MonoMethodSignature *csig = NULL;
1351 MonoMethodBuilder *mb;
1358 if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE)
1361 sig = method->signature;
1363 /* we cant remote methods without this pointer */
1367 cache = method->klass->image->remoting_invoke_cache;
1368 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1372 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
1373 csig->params [0] = &mono_defaults.int_class->byval_arg;
1374 csig->params [1] = &mono_defaults.int_class->byval_arg;
1375 csig->ret = &mono_defaults.object_class->byval_arg;
1379 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE);
1380 mb->method->save_lmf = 1;
1382 params_var = mono_mb_emit_save_args (mb, sig, TRUE);
1384 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1385 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1386 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
1387 mono_mb_emit_ldloc (mb, params_var);
1388 mono_mb_emit_native_call (mb, csig, mono_remoting_wrapper);
1390 if (sig->ret->type == MONO_TYPE_VOID) {
1391 mono_mb_emit_byte (mb, CEE_POP);
1392 mono_mb_emit_byte (mb, CEE_RET);
1394 mono_mb_emit_restore_result (mb, sig->ret);
1397 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1399 g_hash_table_insert (cache, method, res);
1404 mono_marshal_get_remoting_invoke_with_check (MonoMethod *method)
1406 MonoMethodSignature *sig;
1407 MonoMethodBuilder *mb;
1408 MonoMethod *res, *native;
1414 if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)
1417 sig = method->signature;
1419 /* we cant remote methods without this pointer */
1420 g_assert (sig->hasthis);
1422 cache = method->klass->image->remoting_invoke_cache;
1423 if ((res = (MonoMethod *)g_hash_table_lookup (cache, (char *)method + 1)))
1426 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK);
1428 mono_mb_emit_ldarg (mb, 0);
1429 pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
1431 native = mono_marshal_get_remoting_invoke (method);
1433 for (i = 0; i <= sig->param_count; i++)
1434 mono_mb_emit_ldarg (mb, i);
1436 mono_mb_emit_managed_call (mb, native, native->signature);
1437 mono_mb_emit_byte (mb, CEE_RET);
1439 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1441 for (i = 0; i <= sig->param_count; i++)
1442 mono_mb_emit_ldarg (mb, i);
1444 mono_mb_emit_managed_call (mb, method, method->signature);
1445 mono_mb_emit_byte (mb, CEE_RET);
1447 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1449 g_hash_table_insert (cache, (char *)method + 1, res);
1454 * the returned method invokes all methods in a multicast delegate
1457 mono_marshal_get_delegate_invoke (MonoMethod *method)
1459 MonoMethodSignature *sig, *static_sig;
1461 MonoMethodBuilder *mb;
1467 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1468 !strcmp (method->name, "Invoke"));
1470 sig = method->signature;
1472 cache = method->klass->image->delegate_invoke_cache;
1473 if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1476 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1477 static_sig = g_memdup (sig, sigsize);
1478 static_sig->hasthis = 0;
1480 name = mono_signature_to_name (sig, "invoke");
1481 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_INVOKE);
1484 /* allocate local 0 (object) */
1485 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1487 g_assert (sig->hasthis);
1491 * prev.Invoke( args .. );
1492 * return this.<target>( args .. );
1495 /* get this->prev */
1496 mono_mb_emit_ldarg (mb, 0);
1497 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoMulticastDelegate, prev));
1498 mono_mb_emit_byte (mb, CEE_LDIND_I );
1499 mono_mb_emit_stloc (mb, 0);
1501 /* if prev != null */
1502 mono_mb_emit_ldloc (mb, 0);
1503 mono_mb_emit_byte (mb, CEE_BRFALSE);
1506 mono_mb_emit_i4 (mb, 0);
1509 mono_mb_emit_ldloc (mb, 0);
1510 for (i = 0; i < sig->param_count; i++)
1511 mono_mb_emit_ldarg (mb, i + 1);
1512 mono_mb_emit_managed_call (mb, method, method->signature);
1513 if (sig->ret->type != MONO_TYPE_VOID)
1514 mono_mb_emit_byte (mb, CEE_POP);
1516 /* continued or prev == null */
1517 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1519 /* get this->target */
1520 mono_mb_emit_ldarg (mb, 0);
1521 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, target));
1522 mono_mb_emit_byte (mb, CEE_LDIND_I );
1523 mono_mb_emit_stloc (mb, 0);
1525 /* if target != null */
1526 mono_mb_emit_ldloc (mb, 0);
1527 mono_mb_emit_byte (mb, CEE_BRFALSE);
1529 mono_mb_emit_i4 (mb, 0);
1531 /* then call this->method_ptr nonstatic */
1532 mono_mb_emit_ldloc (mb, 0);
1533 for (i = 0; i < sig->param_count; ++i)
1534 mono_mb_emit_ldarg (mb, i + 1);
1535 mono_mb_emit_ldarg (mb, 0);
1536 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1537 mono_mb_emit_byte (mb, CEE_LDIND_I );
1538 mono_mb_emit_byte (mb, CEE_CALLI);
1539 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
1541 mono_mb_emit_byte (mb, CEE_BR);
1543 mono_mb_emit_i4 (mb, 0);
1545 /* else [target == null] call this->method_ptr static */
1546 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1548 for (i = 0; i < sig->param_count; ++i)
1549 mono_mb_emit_ldarg (mb, i + 1);
1550 mono_mb_emit_ldarg (mb, 0);
1551 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1552 mono_mb_emit_byte (mb, CEE_LDIND_I );
1553 mono_mb_emit_byte (mb, CEE_CALLI);
1554 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, static_sig));
1557 mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
1558 mono_mb_emit_byte (mb, CEE_RET);
1560 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1563 g_hash_table_insert (cache, sig, res);
1569 * generates IL code for the runtime invoke function
1570 * MonoObject *runtime_invoke (MonoObject *this, void **params, MonoObject **exc)
1572 * we also catch exceptions if exc != null
1575 mono_marshal_get_runtime_invoke (MonoMethod *method)
1577 MonoMethodSignature *sig, *csig;
1578 MonoExceptionClause *clause;
1579 MonoMethodHeader *header;
1580 MonoMethodBuilder *mb;
1583 static MonoString *string_dummy = NULL;
1584 int i, pos, sigsize;
1588 cache = method->klass->image->runtime_invoke_cache;
1589 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1592 /* to make it work with our special string constructors */
1594 string_dummy = mono_string_new_wrapper ("dummy");
1596 sig = method->signature;
1598 sigsize = sizeof (MonoMethodSignature) + 3 * sizeof (MonoType *);
1599 csig = g_malloc0 (sigsize);
1601 csig->param_count = 3;
1602 csig->ret = &mono_defaults.object_class->byval_arg;
1603 csig->params [0] = &mono_defaults.object_class->byval_arg;
1604 csig->params [1] = &mono_defaults.int_class->byval_arg;
1605 csig->params [2] = &mono_defaults.int_class->byval_arg;
1607 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_RUNTIME_INVOKE);
1609 /* allocate local 0 (object) tmp */
1610 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1611 /* allocate local 1 (object) exc */
1612 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1614 /* cond set *exc to null */
1615 mono_mb_emit_byte (mb, CEE_LDARG_2);
1616 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
1617 mono_mb_emit_byte (mb, 3);
1618 mono_mb_emit_byte (mb, CEE_LDARG_2);
1619 mono_mb_emit_byte (mb, CEE_LDNULL);
1620 mono_mb_emit_byte (mb, CEE_STIND_I);
1623 if (method->string_ctor) {
1624 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1625 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1626 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, string_dummy));
1628 mono_mb_emit_ldarg (mb, 0);
1629 if (method->klass->valuetype) {
1630 mono_mb_emit_byte (mb, CEE_UNBOX);
1631 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method->klass));
1636 for (i = 0; i < sig->param_count; i++) {
1637 MonoType *t = sig->params [i];
1640 mono_mb_emit_ldarg (mb, 1);
1642 mono_mb_emit_icon (mb, sizeof (gpointer) * i);
1643 mono_mb_emit_byte (mb, CEE_ADD);
1645 mono_mb_emit_byte (mb, CEE_LDIND_I);
1650 type = sig->params [i]->type;
1654 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1656 case MONO_TYPE_BOOLEAN:
1658 mono_mb_emit_byte (mb, CEE_LDIND_U1);
1661 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1664 case MONO_TYPE_CHAR:
1665 mono_mb_emit_byte (mb, CEE_LDIND_U2);
1669 mono_mb_emit_byte (mb, CEE_LDIND_I);
1672 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1675 mono_mb_emit_byte (mb, CEE_LDIND_U4);
1678 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1681 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1685 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1687 case MONO_TYPE_STRING:
1688 case MONO_TYPE_CLASS:
1689 case MONO_TYPE_ARRAY:
1691 case MONO_TYPE_SZARRAY:
1692 case MONO_TYPE_OBJECT:
1695 case MONO_TYPE_VALUETYPE:
1696 if (t->data.klass->enumtype) {
1697 type = t->data.klass->enum_basetype->type;
1700 mono_mb_emit_byte (mb, CEE_LDOBJ);
1701 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, t->data.klass));
1704 g_assert_not_reached ();
1708 if (method->string_ctor) {
1709 MonoMethodSignature *strsig;
1711 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1712 strsig = g_memdup (sig, sigsize);
1713 strsig->ret = &mono_defaults.string_class->byval_arg;
1715 mono_mb_emit_managed_call (mb, method, strsig);
1717 mono_mb_emit_managed_call (mb, method, NULL);
1719 if (sig->ret->byref) {
1721 g_assert_not_reached ();
1725 switch (sig->ret->type) {
1726 case MONO_TYPE_VOID:
1727 if (!method->string_ctor)
1728 mono_mb_emit_byte (mb, CEE_LDNULL);
1730 case MONO_TYPE_BOOLEAN:
1731 case MONO_TYPE_CHAR:
1744 case MONO_TYPE_VALUETYPE:
1745 /* box value types */
1746 mono_mb_emit_byte (mb, CEE_BOX);
1747 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (sig->ret)));
1749 case MONO_TYPE_STRING:
1750 case MONO_TYPE_CLASS:
1751 case MONO_TYPE_ARRAY:
1752 case MONO_TYPE_SZARRAY:
1753 case MONO_TYPE_OBJECT:
1758 g_assert_not_reached ();
1761 mono_mb_emit_stloc (mb, 0);
1763 mono_mb_emit_byte (mb, CEE_LEAVE);
1765 mono_mb_emit_i4 (mb, 0);
1767 clause = g_new0 (MonoExceptionClause, 1);
1768 clause->flags = MONO_EXCEPTION_CLAUSE_FILTER;
1769 clause->try_len = mb->pos;
1772 clause->token_or_filter = mb->pos;
1774 mono_mb_emit_byte (mb, CEE_POP);
1775 mono_mb_emit_byte (mb, CEE_LDARG_2);
1776 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
1777 mono_mb_emit_byte (mb, CEE_PREFIX1);
1778 mono_mb_emit_byte (mb, CEE_CGT_UN);
1779 mono_mb_emit_byte (mb, CEE_PREFIX1);
1780 mono_mb_emit_byte (mb, CEE_ENDFILTER);
1782 clause->handler_offset = mb->pos;
1785 /* store exception */
1786 mono_mb_emit_stloc (mb, 1);
1788 mono_mb_emit_byte (mb, CEE_LDARG_2);
1789 mono_mb_emit_ldloc (mb, 1);
1790 mono_mb_emit_byte (mb, CEE_STIND_I);
1792 mono_mb_emit_byte (mb, CEE_LEAVE);
1793 mono_mb_emit_i4 (mb, 0);
1795 clause->handler_len = mb->pos - clause->handler_offset;
1798 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1799 mono_mb_emit_ldloc (mb, 0);
1800 mono_mb_emit_byte (mb, CEE_RET);
1802 res = mono_mb_create_method (mb, csig, sig->param_count + 16);
1805 header = ((MonoMethodNormal *)res)->header;
1806 header->num_clauses = 1;
1807 header->clauses = clause;
1809 g_hash_table_insert (cache, method, res);
1815 * generates IL code to call managed methods from unmanaged code
1818 mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this)
1820 MonoMethodSignature *sig, *csig;
1821 MonoMethodBuilder *mb;
1825 int i, pos, sigsize, *tmp_locals;
1827 g_assert (method != NULL);
1828 g_assert (!method->signature->pinvoke);
1830 cache = method->klass->image->managed_wrapper_cache;
1831 if (!this && (res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1835 /* fime: howto free that memory ? */
1838 sig = method->signature;
1840 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_NATIVE_TO_MANAGED);
1842 /* allocate local 0 (pointer) src_ptr */
1843 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1844 /* allocate local 1 (pointer) dst_ptr */
1845 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1846 /* allocate local 2 (boolean) delete_old */
1847 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
1849 mono_mb_emit_byte (mb, CEE_LDNULL);
1850 mono_mb_emit_byte (mb, CEE_STLOC_2);
1852 /* we copy the signature, so that we can modify it */
1853 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1854 csig = g_memdup (sig, sigsize);
1858 /* fixme: howto handle this ? */
1862 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1863 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1864 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, this));
1869 g_assert_not_reached ();
1874 /* we first do all conversions */
1875 tmp_locals = alloca (sizeof (int) * sig->param_count);
1876 for (i = 0; i < sig->param_count; i ++) {
1877 MonoType *t = sig->params [i];
1882 case MONO_TYPE_VALUETYPE:
1884 klass = sig->params [i]->data.klass;
1885 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
1886 klass->blittable || klass->enumtype)
1889 tmp_locals [i] = mono_mb_add_local (mb, &klass->byval_arg);
1892 mono_mb_emit_ldarg (mb, i);
1894 mono_mb_emit_ldarg_addr (mb, i);
1895 mono_mb_emit_byte (mb, CEE_STLOC_0);
1898 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1899 mono_mb_emit_byte (mb, CEE_BRFALSE);
1901 mono_mb_emit_i4 (mb, 0);
1904 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
1905 mono_mb_emit_byte (mb, CEE_STLOC_1);
1907 /* emit valuetype convnversion code code */
1908 emit_struct_conv (mb, klass, TRUE);
1911 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1913 case MONO_TYPE_STRING:
1917 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1918 csig->params [i] = &mono_defaults.int_class->byval_arg;
1920 mono_mb_emit_ldarg (mb, i);
1921 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1922 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1923 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
1924 mono_mb_emit_stloc (mb, tmp_locals [i]);
1926 case MONO_TYPE_ARRAY:
1927 case MONO_TYPE_SZARRAY:
1931 klass = mono_class_from_mono_type (t);
1933 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1934 csig->params [i] = &mono_defaults.int_class->byval_arg;
1936 g_warning ("array marshaling not implemented");
1937 g_assert_not_reached ();
1942 for (i = 0; i < sig->param_count; i++) {
1943 MonoType *t = sig->params [i];
1946 case MONO_TYPE_BOOLEAN:
1960 mono_mb_emit_ldarg (mb, i);
1962 case MONO_TYPE_STRING:
1964 mono_mb_emit_ldarg (mb, i);
1966 g_assert (tmp_locals [i]);
1967 mono_mb_emit_ldloc (mb, tmp_locals [i]);
1970 case MONO_TYPE_CLASS:
1971 case MONO_TYPE_ARRAY:
1972 case MONO_TYPE_SZARRAY:
1973 case MONO_TYPE_OBJECT:
1974 /* fixme: conversions ? */
1975 mono_mb_emit_ldarg (mb, i);
1977 case MONO_TYPE_VALUETYPE:
1978 klass = sig->params [i]->data.klass;
1979 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
1980 klass->blittable || klass->enumtype) {
1981 mono_mb_emit_ldarg (mb, i);
1985 g_assert (tmp_locals [i]);
1987 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
1989 mono_mb_emit_ldloc (mb, tmp_locals [i]);
1992 g_warning ("type 0x%02x unknown", t->type);
1993 g_assert_not_reached ();
1997 mono_mb_emit_managed_call (mb, method, NULL);
1999 if (!sig->ret->byref) {
2000 switch (sig->ret->type) {
2001 case MONO_TYPE_VOID:
2002 case MONO_TYPE_BOOLEAN:
2016 case MONO_TYPE_OBJECT:
2017 mono_mb_emit_byte (mb, CEE_RET);
2019 case MONO_TYPE_STRING:
2020 csig->ret = &mono_defaults.int_class->byval_arg;
2022 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2023 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2024 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
2025 mono_mb_emit_byte (mb, CEE_RET);
2027 case MONO_TYPE_VALUETYPE: {
2029 klass = sig->ret->data.klass;
2030 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2031 klass->blittable || klass->enumtype)
2034 /* load pointer to returned value type */
2035 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2036 mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
2038 /* store the address of the source into local variable 0 */
2039 mono_mb_emit_byte (mb, CEE_STLOC_0);
2040 /* allocate space for the native struct and
2041 * store the address into dst_ptr */
2042 tmp = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2044 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2045 mono_mb_emit_byte (mb, CEE_PREFIX1);
2046 mono_mb_emit_byte (mb, CEE_LOCALLOC);
2047 mono_mb_emit_byte (mb, CEE_STLOC_1);
2048 mono_mb_emit_byte (mb, CEE_LDLOC_1);
2049 mono_mb_emit_stloc (mb, tmp);
2051 /* emit valuetype conversion code */
2052 emit_struct_conv (mb, klass, FALSE);
2053 mono_mb_emit_ldloc (mb, tmp);
2054 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2055 mono_mb_emit_byte (mb, CEE_MONO_RETOBJ);
2056 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2060 g_warning ("return type 0x%02x unknown", sig->ret->type);
2061 g_assert_not_reached ();
2064 mono_mb_emit_byte (mb, CEE_RET);
2067 res = mono_mb_create_method (mb, csig, sig->param_count + 16);
2071 g_hash_table_insert (cache, method, res);
2077 * mono_marshal_get_ldfld_wrapper:
2078 * @type: the type of the field
2080 * This method generates a function which can be use to load a field with type
2081 * @type from an object. The generated function has the following signature:
2082 * <@type> ldfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset)
2085 mono_marshal_get_ldfld_wrapper (MonoType *type)
2087 MonoMethodSignature *sig, *csig;
2088 MonoMethodBuilder *mb;
2091 static GHashTable *ldfld_hash = NULL;
2096 ldfld_hash = g_hash_table_new (NULL, NULL);
2102 if (type->type == MONO_TYPE_SZARRAY) {
2103 klass = mono_defaults.array_class;
2104 } else if (type->type == MONO_TYPE_VALUETYPE) {
2105 klass = type->data.klass;
2106 if (klass->enumtype) {
2107 t = klass->enum_basetype->type;
2108 klass = mono_class_from_mono_type (klass->enum_basetype);
2110 } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
2111 t == MONO_TYPE_CLASS) {
2112 klass = mono_defaults.object_class;
2113 } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
2114 klass = mono_defaults.int_class;
2116 klass = mono_class_from_mono_type (type);
2119 klass = mono_defaults.int_class;
2122 if ((res = g_hash_table_lookup (ldfld_hash, klass)))
2125 name = g_strdup_printf ("__ldfld_wrapper_%s.%s", klass->name_space, klass->name);
2126 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_LDFLD);
2129 mb->method->save_lmf = 1;
2131 sig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
2132 sig->params [0] = &mono_defaults.object_class->byval_arg;
2133 sig->params [1] = &mono_defaults.int_class->byval_arg;
2134 sig->params [2] = &mono_defaults.int_class->byval_arg;
2135 sig->params [3] = &mono_defaults.int_class->byval_arg;
2136 sig->ret = &klass->byval_arg;
2138 mono_mb_emit_ldarg (mb, 0);
2139 pos0 = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
2141 mono_mb_emit_ldarg (mb, 0);
2142 mono_mb_emit_ldarg (mb, 1);
2143 mono_mb_emit_ldarg (mb, 2);
2145 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
2146 csig->params [0] = &mono_defaults.object_class->byval_arg;
2147 csig->params [1] = &mono_defaults.int_class->byval_arg;
2148 csig->params [2] = &mono_defaults.int_class->byval_arg;
2149 csig->ret = &klass->this_arg;
2152 mono_mb_emit_native_call (mb, csig, mono_load_remote_field_new);
2154 if (klass->valuetype) {
2155 mono_mb_emit_byte (mb, CEE_UNBOX);
2156 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2157 mono_mb_emit_byte (mb, CEE_BR);
2159 mono_mb_emit_i4 (mb, 0);
2161 mono_mb_emit_byte (mb, CEE_RET);
2165 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
2167 mono_mb_emit_ldarg (mb, 0);
2168 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2169 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2170 mono_mb_emit_ldarg (mb, 3);
2171 mono_mb_emit_byte (mb, CEE_ADD);
2173 if (klass->valuetype)
2174 mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
2179 case MONO_TYPE_BOOLEAN:
2180 mono_mb_emit_byte (mb, CEE_LDIND_I1);
2182 case MONO_TYPE_CHAR:
2185 mono_mb_emit_byte (mb, CEE_LDIND_I2);
2189 mono_mb_emit_byte (mb, CEE_LDIND_I4);
2193 mono_mb_emit_byte (mb, CEE_LDIND_I8);
2196 mono_mb_emit_byte (mb, CEE_LDIND_R4);
2199 mono_mb_emit_byte (mb, CEE_LDIND_R8);
2201 case MONO_TYPE_ARRAY:
2203 case MONO_TYPE_FNPTR:
2204 case MONO_TYPE_SZARRAY:
2205 case MONO_TYPE_OBJECT:
2206 case MONO_TYPE_CLASS:
2207 case MONO_TYPE_STRING:
2210 mono_mb_emit_byte (mb, CEE_LDIND_I);
2212 case MONO_TYPE_VALUETYPE:
2213 g_assert (!klass->enumtype);
2214 mono_mb_emit_byte (mb, CEE_LDOBJ);
2215 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2218 g_warning ("type %x not implemented", type->type);
2219 g_assert_not_reached ();
2222 mono_mb_emit_byte (mb, CEE_RET);
2224 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
2227 g_hash_table_insert (ldfld_hash, klass, res);
2233 * mono_marshal_get_stfld_wrapper:
2234 * @type: the type of the field
2236 * This method generates a function which can be use to store a field with type
2237 * @type. The generated function has the following signature:
2238 * void stfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset, <@type> val)
2241 mono_marshal_get_stfld_wrapper (MonoType *type)
2243 MonoMethodSignature *sig, *csig;
2244 MonoMethodBuilder *mb;
2247 static GHashTable *stfld_hash = NULL;
2252 stfld_hash = g_hash_table_new (NULL, NULL);
2257 if (type->type == MONO_TYPE_SZARRAY) {
2258 klass = mono_defaults.array_class;
2259 } else if (type->type == MONO_TYPE_VALUETYPE) {
2260 klass = type->data.klass;
2261 if (klass->enumtype) {
2262 t = klass->enum_basetype->type;
2263 klass = mono_class_from_mono_type (klass->enum_basetype);
2265 } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
2266 t == MONO_TYPE_CLASS) {
2267 klass = mono_defaults.object_class;
2268 } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
2269 klass = mono_defaults.int_class;
2271 klass = mono_class_from_mono_type (type);
2274 klass = mono_defaults.int_class;
2277 if ((res = g_hash_table_lookup (stfld_hash, klass)))
2280 name = g_strdup_printf ("__stfld_wrapper_%s.%s", klass->name_space, klass->name);
2281 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_STFLD);
2284 mb->method->save_lmf = 1;
2286 sig = mono_metadata_signature_alloc (mono_defaults.corlib, 5);
2287 sig->params [0] = &mono_defaults.object_class->byval_arg;
2288 sig->params [1] = &mono_defaults.int_class->byval_arg;
2289 sig->params [2] = &mono_defaults.int_class->byval_arg;
2290 sig->params [3] = &mono_defaults.int_class->byval_arg;
2291 sig->params [4] = &klass->byval_arg;
2292 sig->ret = &mono_defaults.void_class->byval_arg;
2294 mono_mb_emit_ldarg (mb, 0);
2295 pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
2297 mono_mb_emit_ldarg (mb, 0);
2298 mono_mb_emit_ldarg (mb, 1);
2299 mono_mb_emit_ldarg (mb, 2);
2300 mono_mb_emit_ldarg (mb, 4);
2302 if (klass->valuetype) {
2303 mono_mb_emit_byte (mb, CEE_BOX);
2304 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2307 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
2308 csig->params [0] = &mono_defaults.object_class->byval_arg;
2309 csig->params [1] = &mono_defaults.int_class->byval_arg;
2310 csig->params [2] = &mono_defaults.int_class->byval_arg;
2311 csig->params [3] = &klass->this_arg;
2312 csig->ret = &mono_defaults.void_class->byval_arg;
2315 mono_mb_emit_native_call (mb, csig, mono_store_remote_field_new);
2317 mono_mb_emit_byte (mb, CEE_RET);
2319 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2321 mono_mb_emit_ldarg (mb, 0);
2322 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2323 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2324 mono_mb_emit_ldarg (mb, 3);
2325 mono_mb_emit_byte (mb, CEE_ADD);
2326 mono_mb_emit_ldarg (mb, 4);
2331 case MONO_TYPE_BOOLEAN:
2332 mono_mb_emit_byte (mb, CEE_STIND_I1);
2334 case MONO_TYPE_CHAR:
2337 mono_mb_emit_byte (mb, CEE_STIND_I2);
2341 mono_mb_emit_byte (mb, CEE_STIND_I4);
2345 mono_mb_emit_byte (mb, CEE_STIND_I8);
2348 mono_mb_emit_byte (mb, CEE_STIND_R4);
2351 mono_mb_emit_byte (mb, CEE_STIND_R8);
2353 case MONO_TYPE_ARRAY:
2355 case MONO_TYPE_FNPTR:
2356 case MONO_TYPE_SZARRAY:
2357 case MONO_TYPE_OBJECT:
2358 case MONO_TYPE_CLASS:
2359 case MONO_TYPE_STRING:
2362 mono_mb_emit_byte (mb, CEE_STIND_I);
2364 case MONO_TYPE_VALUETYPE:
2365 g_assert (!klass->enumtype);
2366 mono_mb_emit_byte (mb, CEE_STOBJ);
2367 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2370 g_warning ("type %x not implemented", type->type);
2371 g_assert_not_reached ();
2374 mono_mb_emit_byte (mb, CEE_RET);
2376 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
2379 g_hash_table_insert (stfld_hash, klass, res);
2385 * generates IL code for the icall wrapper (the generated method
2386 * calls the unamnaged code in func)
2389 mono_marshal_get_icall_wrapper (MonoMethodSignature *sig, const char *name, gconstpointer func)
2391 MonoMethodSignature *csig;
2392 MonoMethodBuilder *mb;
2396 g_assert (sig->pinvoke);
2398 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_MANAGED_TO_NATIVE);
2400 mb->method->save_lmf = 1;
2402 /* we copy the signature, so that we can modify it */
2403 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
2406 mono_mb_emit_byte (mb, CEE_LDARG_0);
2408 for (i = 0; i < sig->param_count; i++)
2409 mono_mb_emit_ldarg (mb, i + sig->hasthis);
2411 mono_mb_emit_native_call (mb, sig, (gpointer) func);
2413 mono_mb_emit_byte (mb, CEE_RET);
2415 csig = g_memdup (sig, sigsize);
2418 res = mono_mb_create_method (mb, csig, csig->param_count + 16);
2425 * generates IL code for the pinvoke wrapper (the generated method
2426 * calls the unamnage code in method->addr)
2429 mono_marshal_get_native_wrapper (MonoMethod *method)
2431 MonoMethodSignature *sig, *csig;
2432 MonoMethodBuilder *mb;
2433 MonoMarshalSpec **mspecs;
2437 gboolean pinvoke = FALSE;
2438 int i, pos, argnum, *tmp_locals;
2441 g_assert (method != NULL);
2442 g_assert (method->signature->pinvoke);
2444 cache = method->klass->image->native_wrapper_cache;
2445 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
2448 sig = method->signature;
2449 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
2451 if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
2452 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2455 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_MANAGED_TO_NATIVE);
2457 mb->method->save_lmf = 1;
2459 if (pinvoke && !method->addr)
2460 mono_lookup_pinvoke_call (method);
2462 if (!method->addr) {
2463 mono_mb_emit_exception (mb);
2464 csig = g_memdup (sig, sigsize);
2466 res = mono_mb_create_method (mb, csig, csig->param_count + 16);
2468 g_hash_table_insert (cache, method, res);
2472 /* internal calls: we simply push all arguments and call the method (no conversions) */
2473 if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
2475 /* hack - string constructors returns a value */
2476 if (method->string_ctor) {
2477 csig = g_memdup (sig, sigsize);
2478 csig->ret = &mono_defaults.string_class->byval_arg;
2483 mono_mb_emit_byte (mb, CEE_LDARG_0);
2485 for (i = 0; i < sig->param_count; i++)
2486 mono_mb_emit_ldarg (mb, i + sig->hasthis);
2488 g_assert (method->addr);
2489 mono_mb_emit_native_call (mb, csig, method->addr);
2491 mono_mb_emit_byte (mb, CEE_RET);
2493 csig = g_memdup (csig, sigsize);
2495 res = mono_mb_create_method (mb, csig, csig->param_count + 16);
2497 g_hash_table_insert (cache, method, res);
2503 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
2504 mono_method_get_marshal_info (method, mspecs);
2506 /* pinvoke: we need to convert the arguments if necessary */
2508 /* we copy the signature, so that we can set pinvoke to 0 */
2509 csig = g_memdup (sig, sigsize);
2512 /* we allocate local for use with emit_struct_conv() */
2513 /* allocate local 0 (pointer) src_ptr */
2514 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2515 /* allocate local 1 (pointer) dst_ptr */
2516 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2517 /* allocate local 2 (boolean) delete_old */
2518 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2520 /* delete_old = FALSE */
2521 mono_mb_emit_icon (mb, 0);
2522 mono_mb_emit_byte (mb, CEE_STLOC_2);
2524 if (!MONO_TYPE_IS_VOID(sig->ret)) {
2525 /* allocate local 3 to store the return value */
2526 mono_mb_add_local (mb, sig->ret);
2529 /* we first do all conversions */
2530 tmp_locals = alloca (sizeof (int) * sig->param_count);
2531 for (i = 0; i < sig->param_count; i ++) {
2532 MonoType *t = sig->params [i];
2533 MonoMarshalSpec *spec = mspecs [i + 1];
2535 argnum = i + sig->hasthis;
2539 case MONO_TYPE_VALUETYPE:
2540 klass = t->data.klass;
2542 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2543 klass->blittable || klass->enumtype)
2546 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2548 /* store the address of the source into local variable 0 */
2550 mono_mb_emit_ldarg (mb, argnum);
2552 mono_mb_emit_ldarg_addr (mb, argnum);
2554 mono_mb_emit_byte (mb, CEE_STLOC_0);
2556 /* allocate space for the native struct and
2557 * store the address into local variable 1 (dest) */
2558 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2559 mono_mb_emit_byte (mb, CEE_PREFIX1);
2560 mono_mb_emit_byte (mb, CEE_LOCALLOC);
2561 mono_mb_emit_stloc (mb, tmp_locals [i]);
2564 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2565 mono_mb_emit_byte (mb, CEE_BRFALSE);
2567 mono_mb_emit_i4 (mb, 0);
2571 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2572 mono_mb_emit_byte (mb, CEE_STLOC_1);
2574 /* emit valuetype conversion code */
2575 emit_struct_conv (mb, klass, FALSE);
2578 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2580 case MONO_TYPE_STRING:
2584 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2585 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2587 mono_mb_emit_ldarg (mb, argnum);
2588 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2589 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2592 switch (spec->native) {
2593 case MONO_NATIVE_LPWSTR:
2594 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPWSTR);
2596 case MONO_NATIVE_LPSTR:
2597 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
2600 g_warning ("marshalling conversion %d not implemented", spec->native);
2601 g_assert_not_reached ();
2604 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
2607 mono_mb_emit_stloc (mb, tmp_locals [i]);
2609 case MONO_TYPE_CLASS:
2613 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2614 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2616 if (t->data.klass->delegate) {
2617 mono_mb_emit_ldarg (mb, argnum);
2618 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2619 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2620 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_DEL_FTN);
2621 mono_mb_emit_stloc (mb, tmp_locals [i]);
2622 } else if (t->data.klass == mono_defaults.stringbuilder_class) {
2623 mono_mb_emit_ldarg (mb, argnum);
2624 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2625 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2626 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_SB_LPSTR);
2627 mono_mb_emit_stloc (mb, tmp_locals [i]);
2629 mono_mb_emit_ldarg (mb, argnum);
2630 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2631 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2632 /* fixme: convert to what ? */
2633 mono_mb_emit_stloc (mb, tmp_locals [i]);
2637 case MONO_TYPE_OBJECT:
2640 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2641 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2643 * FIXME: this may need special handling to inspect the type
2646 mono_mb_emit_ldarg (mb, argnum);
2647 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2648 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2649 /* fixme: convert to what ? */
2650 mono_mb_emit_stloc (mb, tmp_locals [i]);
2652 case MONO_TYPE_ARRAY:
2653 case MONO_TYPE_SZARRAY:
2657 klass = mono_class_from_mono_type (t);
2659 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2660 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2662 mono_mb_emit_ldarg (mb, argnum);
2663 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2664 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2665 if (klass->element_class == mono_defaults.string_class)
2666 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STRARRAY_STRLPARRAY);
2668 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_ARRAY_LPARRAY);
2669 mono_mb_emit_stloc (mb, tmp_locals [i]);
2674 /* push all arguments */
2677 mono_mb_emit_byte (mb, CEE_LDARG_0);
2679 for (i = 0; i < sig->param_count; i++) {
2680 MonoType *t = sig->params [i];
2682 argnum = i + sig->hasthis;
2685 case MONO_TYPE_BOOLEAN:
2687 g_warning ("byref boolean marshalling not inplemented");
2688 mono_mb_emit_ldarg (mb, argnum);
2703 mono_mb_emit_ldarg (mb, argnum);
2705 case MONO_TYPE_VALUETYPE:
2706 klass = sig->params [i]->data.klass;
2707 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2708 klass->blittable || klass->enumtype) {
2709 mono_mb_emit_ldarg (mb, argnum);
2712 g_assert (tmp_locals [i]);
2713 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2715 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2716 mono_mb_emit_byte (mb, CEE_MONO_LDNATIVEOBJ);
2717 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2720 case MONO_TYPE_STRING:
2722 mono_mb_emit_ldarg (mb, argnum);
2724 g_assert (tmp_locals [i]);
2725 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2728 case MONO_TYPE_CLASS:
2729 case MONO_TYPE_OBJECT:
2731 mono_mb_emit_ldarg (mb, argnum);
2733 g_assert (tmp_locals [i]);
2734 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2737 case MONO_TYPE_CHAR:
2738 /* fixme: dont know how to marshal that. We cant simply
2739 * convert it to a one byte UTF8 character, because an
2740 * unicode character may need more that one byte in UTF8 */
2741 mono_mb_emit_ldarg (mb, argnum);
2743 case MONO_TYPE_ARRAY:
2744 case MONO_TYPE_SZARRAY:
2746 mono_mb_emit_ldarg (mb, argnum);
2748 g_assert (tmp_locals [i]);
2749 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2752 case MONO_TYPE_TYPEDBYREF:
2753 case MONO_TYPE_FNPTR:
2755 g_warning ("type 0x%02x unknown", t->type);
2756 g_assert_not_reached ();
2760 /* call the native method */
2761 mono_mb_emit_native_call (mb, csig, method->addr);
2763 /* convert and the result */
2764 if (!sig->ret->byref) {
2765 MonoMarshalSpec *spec = mspecs [0];
2766 type = sig->ret->type;
2770 case MONO_TYPE_VOID:
2785 /* no conversions necessary */
2786 mono_mb_emit_byte (mb, CEE_STLOC_3);
2788 case MONO_TYPE_BOOLEAN:
2789 /* maybe we need to make sure that it fits within 8 bits */
2790 mono_mb_emit_byte (mb, CEE_STLOC_3);
2792 case MONO_TYPE_VALUETYPE:
2793 klass = sig->ret->data.klass;
2794 if (klass->enumtype) {
2795 type = sig->ret->data.klass->enum_basetype->type;
2799 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2801 mono_mb_emit_byte (mb, CEE_STLOC_3);
2804 /* load pointer to returned value type */
2805 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2806 mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
2807 /* store the address of the source into local variable 0 */
2808 mono_mb_emit_byte (mb, CEE_STLOC_0);
2810 mono_mb_emit_ldloc_addr (mb, 3);
2811 mono_mb_emit_byte (mb, CEE_STLOC_1);
2813 /* emit valuetype conversion code */
2814 emit_struct_conv (mb, sig->ret->data.klass, TRUE);
2816 case MONO_TYPE_STRING:
2817 /* maybe we should free strings here */
2818 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2819 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2821 switch (spec->native) {
2822 case MONO_NATIVE_LPWSTR:
2823 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPWSTR_STR);
2826 g_warning ("marshalling conversion not implemented");
2827 g_assert_not_reached ();
2830 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
2832 mono_mb_emit_byte (mb, CEE_STLOC_3);
2834 case MONO_TYPE_ARRAY:
2835 case MONO_TYPE_SZARRAY:
2836 case MONO_TYPE_CLASS:
2837 case MONO_TYPE_OBJECT:
2838 /* fixme: we need conversions here */
2839 mono_mb_emit_byte (mb, CEE_STLOC_3);
2841 case MONO_TYPE_CHAR:
2842 /* fixme: we need conversions here */
2843 mono_mb_emit_byte (mb, CEE_STLOC_3);
2845 case MONO_TYPE_TYPEDBYREF:
2846 case MONO_TYPE_FNPTR:
2848 g_warning ("return type 0x%02x unknown", sig->ret->type);
2849 g_assert_not_reached ();
2852 mono_mb_emit_byte (mb, CEE_STLOC_3);
2855 /* we need to convert byref arguments back and free string arrays */
2856 for (i = 0; i < sig->param_count; i++) {
2857 MonoType *t = sig->params [i];
2859 argnum = i + sig->hasthis;
2862 case MONO_TYPE_STRING:
2866 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2867 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2868 mono_mb_emit_byte (mb, CEE_MONO_FREE);
2871 case MONO_TYPE_CLASS:
2872 case MONO_TYPE_OBJECT:
2876 if (t->data.klass == mono_defaults.stringbuilder_class) {
2877 mono_mb_emit_ldarg (mb, argnum);
2878 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2879 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2880 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
2881 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_SB);
2882 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2883 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2884 mono_mb_emit_byte (mb, CEE_MONO_FREE);
2887 case MONO_TYPE_VALUETYPE:
2891 klass = t->data.klass;
2892 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2893 klass->blittable || klass->enumtype)
2896 /* dst = argument */
2897 mono_mb_emit_ldarg (mb, argnum);
2898 mono_mb_emit_byte (mb, CEE_STLOC_1);
2900 mono_mb_emit_byte (mb, CEE_LDLOC_1);
2901 mono_mb_emit_byte (mb, CEE_BRFALSE);
2903 mono_mb_emit_i4 (mb, 0);
2905 /* src = tmp_locals [i] */
2906 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2907 mono_mb_emit_byte (mb, CEE_STLOC_0);
2909 /* emit valuetype conversion code */
2910 emit_struct_conv (mb, klass, TRUE);
2912 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2914 case MONO_TYPE_SZARRAY:
2918 klass = mono_class_from_mono_type (t);
2920 if (klass->element_class == mono_defaults.string_class) {
2921 g_assert (tmp_locals [i]);
2923 mono_mb_emit_ldarg (mb, argnum);
2924 mono_mb_emit_byte (mb, CEE_BRFALSE);
2926 mono_mb_emit_i4 (mb, 0);
2928 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2929 mono_mb_emit_ldarg (mb, argnum);
2930 mono_mb_emit_byte (mb, CEE_LDLEN);
2931 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2932 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
2933 mono_mb_emit_byte (mb, MONO_MARSHAL_FREE_ARRAY);
2935 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2943 if (!MONO_TYPE_IS_VOID(sig->ret))
2944 mono_mb_emit_byte (mb, CEE_LDLOC_3);
2946 mono_mb_emit_byte (mb, CEE_RET);
2948 csig = g_memdup (sig, sigsize);
2950 res = mono_mb_create_method (mb, csig, csig->param_count + 16);
2953 g_hash_table_insert (cache, method, res);
2955 for (i = sig->param_count; i >= 0; i--)
2956 g_free (mspecs [i]);
2963 * generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld)
2966 mono_marshal_get_struct_to_ptr (MonoClass *klass)
2968 MonoMethodBuilder *mb;
2969 static MonoMethod *stoptr = NULL;
2972 g_assert (klass != NULL);
2974 if (klass->str_to_ptr)
2975 return klass->str_to_ptr;
2978 stoptr = mono_find_method_by_name (mono_defaults.marshal_class, "StructureToPtr", 3);
2981 mb = mono_mb_new (klass, stoptr->name, MONO_WRAPPER_UNKNOWN);
2983 if (klass->blittable) {
2984 mono_mb_emit_byte (mb, CEE_LDARG_1);
2985 mono_mb_emit_byte (mb, CEE_LDARG_0);
2986 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
2987 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
2988 mono_mb_emit_byte (mb, CEE_PREFIX1);
2989 mono_mb_emit_byte (mb, CEE_CPBLK);
2992 /* allocate local 0 (pointer) src_ptr */
2993 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2994 /* allocate local 1 (pointer) dst_ptr */
2995 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2996 /* allocate local 2 (boolean) delete_old */
2997 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2998 mono_mb_emit_byte (mb, CEE_LDARG_2);
2999 mono_mb_emit_byte (mb, CEE_STLOC_2);
3001 /* initialize src_ptr to point to the start of object data */
3002 mono_mb_emit_byte (mb, CEE_LDARG_0);
3003 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3004 mono_mb_emit_byte (mb, CEE_STLOC_0);
3006 /* initialize dst_ptr */
3007 mono_mb_emit_byte (mb, CEE_LDARG_1);
3008 mono_mb_emit_byte (mb, CEE_STLOC_1);
3010 emit_struct_conv (mb, klass, FALSE);
3013 mono_mb_emit_byte (mb, CEE_RET);
3015 res = mono_mb_create_method (mb, stoptr->signature, 0);
3018 klass->str_to_ptr = res;
3023 * generates IL code for PtrToStructure (IntPtr src, object structure)
3026 mono_marshal_get_ptr_to_struct (MonoClass *klass)
3028 MonoMethodBuilder *mb;
3029 static MonoMethod *ptostr = NULL;
3032 g_assert (klass != NULL);
3034 if (klass->ptr_to_str)
3035 return klass->ptr_to_str;
3038 ptostr = mono_find_method_by_name (mono_defaults.marshal_class, "PtrToStructure", 2);
3041 mb = mono_mb_new (klass, ptostr->name, MONO_WRAPPER_UNKNOWN);
3043 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable) {
3044 mono_mb_emit_byte (mb, CEE_LDARG_1);
3045 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3046 mono_mb_emit_byte (mb, CEE_LDARG_0);
3047 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
3048 mono_mb_emit_byte (mb, CEE_PREFIX1);
3049 mono_mb_emit_byte (mb, CEE_CPBLK);
3052 /* allocate local 0 (pointer) src_ptr */
3053 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3054 /* allocate local 1 (pointer) dst_ptr */
3055 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3057 /* initialize src_ptr to point to the start of object data */
3058 mono_mb_emit_byte (mb, CEE_LDARG_0);
3059 mono_mb_emit_byte (mb, CEE_STLOC_0);
3061 /* initialize dst_ptr */
3062 mono_mb_emit_byte (mb, CEE_LDARG_1);
3063 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3064 mono_mb_emit_byte (mb, CEE_STLOC_1);
3066 emit_struct_conv (mb, klass, TRUE);
3069 mono_mb_emit_byte (mb, CEE_RET);
3071 res = mono_mb_create_method (mb, ptostr->signature, 0);
3074 klass->ptr_to_str = res;
3078 static MonoReflectionType *
3079 type_from_handle (MonoType *handle)
3081 MonoDomain *domain = mono_domain_get ();
3082 MonoClass *klass = mono_class_from_mono_type (handle);
3084 MONO_ARCH_SAVE_REGS;
3086 mono_class_init (klass);
3087 return mono_type_get_object (domain, handle);
3091 * generates IL code for the synchronized wrapper: the generated method
3092 * calls METHOD while locking 'this' or the parent type.
3095 mono_marshal_get_synchronized_wrapper (MonoMethod *method)
3097 static MonoMethodSignature *from_handle_sig = NULL;
3098 static MonoMethod *enter_method, *exit_method;
3099 MonoMethodSignature *sig;
3100 MonoExceptionClause *clause;
3101 MonoMethodHeader *header;
3102 MonoMethodBuilder *mb;
3105 int i, pos, this_local, ret_local;
3109 if (method->wrapper_type == MONO_WRAPPER_SYNCHRONIZED)
3112 cache = method->klass->image->synchronized_cache;
3113 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
3116 sig = method->signature;
3118 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_SYNCHRONIZED);
3121 if (!MONO_TYPE_IS_VOID (sig->ret))
3122 ret_local = mono_mb_add_local (mb, sig->ret);
3125 this_local = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
3127 clause = g_new0 (MonoExceptionClause, 1);
3128 clause->flags = MONO_EXCEPTION_CLAUSE_FINALLY;
3130 if (!enter_method) {
3131 MonoMethodDesc *desc;
3133 desc = mono_method_desc_new ("Monitor:Enter", FALSE);
3134 enter_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
3135 g_assert (enter_method);
3136 mono_method_desc_free (desc);
3137 desc = mono_method_desc_new ("Monitor:Exit", FALSE);
3138 exit_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
3139 g_assert (exit_method);
3140 mono_method_desc_free (desc);
3143 * GetTypeFromHandle isn't called as a managed method because it has
3144 * a funky calling sequence, e.g. ldtoken+GetTypeFromHandle gets
3145 * transformed into something else by the JIT.
3147 from_handle_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
3148 from_handle_sig->params [0] = &mono_defaults.object_class->byval_arg;
3149 from_handle_sig->ret = &mono_defaults.object_class->byval_arg;
3152 /* Push this or the type object */
3153 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3154 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3155 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
3156 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, &method->klass->byval_arg));
3157 mono_mb_emit_native_call (mb, from_handle_sig, type_from_handle);
3160 mono_mb_emit_ldarg (mb, 0);
3161 mono_mb_emit_stloc (mb, this_local);
3163 /* Call Monitor::Enter() */
3164 mono_mb_emit_ldloc (mb, this_local);
3165 mono_mb_emit_managed_call (mb, enter_method, NULL);
3167 clause->try_offset = mb->pos;
3169 /* Call the method */
3171 mono_mb_emit_ldarg (mb, 0);
3172 for (i = 0; i < sig->param_count; i++)
3173 mono_mb_emit_ldarg (mb, i + (sig->hasthis == TRUE));
3174 mono_mb_emit_managed_call (mb, method, method->signature);
3175 if (!MONO_TYPE_IS_VOID (sig->ret))
3176 mono_mb_emit_stloc (mb, ret_local);
3178 mono_mb_emit_byte (mb, CEE_LEAVE);
3180 mono_mb_emit_i4 (mb, 0);
3182 clause->try_len = mb->pos - clause->try_offset;
3183 clause->handler_offset = mb->pos;
3185 /* Call Monitor::Exit() */
3186 mono_mb_emit_ldloc (mb, this_local);
3187 // mono_mb_emit_native_call (mb, exit_sig, mono_monitor_exit);
3188 mono_mb_emit_managed_call (mb, exit_method, NULL);
3189 mono_mb_emit_byte (mb, CEE_ENDFINALLY);
3191 clause->handler_len = mb->pos - clause->handler_offset;
3193 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3194 if (!MONO_TYPE_IS_VOID (sig->ret))
3195 mono_mb_emit_ldloc (mb, ret_local);
3196 mono_mb_emit_byte (mb, CEE_RET);
3198 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
3201 header = ((MonoMethodNormal *)res)->header;
3202 header->num_clauses = 1;
3203 header->clauses = clause;
3205 g_hash_table_insert (cache, method, res);
3210 /* FIXME: on win32 we should probably use GlobalAlloc(). */
3212 mono_marshal_alloc (gpointer size)
3214 MONO_ARCH_SAVE_REGS;
3216 return g_try_malloc ((gulong)size);
3220 mono_marshal_free (gpointer ptr)
3222 MONO_ARCH_SAVE_REGS;
3228 mono_marshal_free_array (gpointer *ptr, int size)
3235 for (i = 0; i < size; i++)
3241 mono_marshal_realloc (gpointer ptr, gpointer size)
3243 MONO_ARCH_SAVE_REGS;
3245 return g_try_realloc (ptr, (gulong)size);
3249 mono_marshal_string_array (MonoArray *array)
3257 len = mono_array_length (array);
3259 result = g_malloc (sizeof (char *) * (len + 1));
3260 for (i = 0; i < len; ++i) {
3261 MonoString *s = (MonoString *)mono_array_get (array, gpointer, i);
3262 result [i] = s ? mono_string_to_utf8 (s): NULL;
3264 /* null terminate the array */
3271 ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArray *src, gint32 start_index,
3272 gpointer dest, gint32 length)
3277 MONO_ARCH_SAVE_REGS;
3279 MONO_CHECK_ARG_NULL (src);
3280 MONO_CHECK_ARG_NULL (dest);
3282 g_assert (src->obj.vtable->klass->rank == 1);
3283 g_assert (start_index >= 0);
3284 g_assert (length >= 0);
3285 g_assert (start_index + length <= mono_array_length (src));
3287 element_size = mono_array_element_size (src->obj.vtable->klass);
3289 source_addr = mono_array_addr_with_size (src, element_size, start_index);
3291 memcpy (dest, source_addr, length * element_size);
3295 ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer src, gint32 start_index,
3296 MonoArray *dest, gint32 length)
3301 MONO_ARCH_SAVE_REGS;
3303 MONO_CHECK_ARG_NULL (src);
3304 MONO_CHECK_ARG_NULL (dest);
3306 g_assert (dest->obj.vtable->klass->rank == 1);
3307 g_assert (start_index >= 0);
3308 g_assert (length >= 0);
3309 g_assert (start_index + length <= mono_array_length (dest));
3311 element_size = mono_array_element_size (dest->obj.vtable->klass);
3313 dest_addr = mono_array_addr_with_size (dest, element_size, start_index);
3315 memcpy (dest_addr, src, length * element_size);
3319 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr, gint32 offset)
3323 MONO_ARCH_SAVE_REGS;
3325 return *(gpointer*)(p + offset);
3329 ves_icall_System_Runtime_InteropServices_Marshal_ReadByte (gpointer ptr, gint32 offset)
3333 MONO_ARCH_SAVE_REGS;
3335 return *(unsigned char*)(p + offset);
3339 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt16 (gpointer ptr, gint32 offset)
3343 MONO_ARCH_SAVE_REGS;
3345 return *(gint16*)(p + offset);
3349 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt32 (gpointer ptr, gint32 offset)
3353 MONO_ARCH_SAVE_REGS;
3355 return *(gint32*)(p + offset);
3359 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt64 (gpointer ptr, gint32 offset)
3363 MONO_ARCH_SAVE_REGS;
3365 return *(gint64*)(p + offset);
3369 ves_icall_System_Runtime_InteropServices_Marshal_WriteByte (gpointer ptr, gint32 offset, unsigned char val)
3373 MONO_ARCH_SAVE_REGS;
3375 *(unsigned char*)(p + offset) = val;
3379 ves_icall_System_Runtime_InteropServices_Marshal_WriteIntPtr (gpointer ptr, gint32 offset, gpointer val)
3383 MONO_ARCH_SAVE_REGS;
3385 *(gpointer*)(p + offset) = val;
3389 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt16 (gpointer ptr, gint32 offset, gint16 val)
3393 MONO_ARCH_SAVE_REGS;
3395 *(gint16*)(p + offset) = val;
3399 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt32 (gpointer ptr, gint32 offset, gint32 val)
3403 MONO_ARCH_SAVE_REGS;
3405 *(gint32*)(p + offset) = val;
3409 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt64 (gpointer ptr, gint32 offset, gint64 val)
3413 MONO_ARCH_SAVE_REGS;
3415 *(gint64*)(p + offset) = val;
3419 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (char *ptr)
3421 MONO_ARCH_SAVE_REGS;
3423 return mono_string_new (mono_domain_get (), ptr);
3427 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len (char *ptr, gint32 len)
3429 MONO_ARCH_SAVE_REGS;
3431 return mono_string_new_len (mono_domain_get (), ptr, len);
3435 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni (guint16 *ptr)
3437 MonoDomain *domain = mono_domain_get ();
3441 MONO_ARCH_SAVE_REGS;
3446 return mono_string_new_utf16 (domain, ptr, len);
3450 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len (guint16 *ptr, gint32 len)
3452 MonoDomain *domain = mono_domain_get ();
3454 MONO_ARCH_SAVE_REGS;
3456 return mono_string_new_utf16 (domain, ptr, len);
3460 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR (gpointer ptr)
3462 MONO_ARCH_SAVE_REGS;
3464 g_warning ("PtrToStringBSTR not implemented");
3465 g_assert_not_reached ();
3471 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
3473 MONO_ARCH_SAVE_REGS;
3475 return (GetLastError ());
3479 ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype)
3483 MONO_ARCH_SAVE_REGS;
3485 MONO_CHECK_ARG_NULL (rtype);
3487 klass = mono_class_from_mono_type (rtype->type);
3489 return mono_class_native_size (klass, NULL);
3493 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old)
3498 MONO_ARCH_SAVE_REGS;
3500 MONO_CHECK_ARG_NULL (obj);
3501 MONO_CHECK_ARG_NULL (dst);
3503 method = mono_marshal_get_struct_to_ptr (obj->vtable->klass);
3507 pa [2] = &delete_old;
3509 mono_runtime_invoke (method, NULL, pa, NULL);
3513 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, MonoObject *dst)
3518 MONO_ARCH_SAVE_REGS;
3520 MONO_CHECK_ARG_NULL (src);
3521 MONO_CHECK_ARG_NULL (dst);
3523 method = mono_marshal_get_ptr_to_struct (dst->vtable->klass);
3528 mono_runtime_invoke (method, NULL, pa, NULL);
3532 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer src, MonoReflectionType *type)
3534 MonoDomain *domain = mono_domain_get ();
3537 MONO_ARCH_SAVE_REGS;
3539 MONO_CHECK_ARG_NULL (src);
3540 MONO_CHECK_ARG_NULL (type);
3542 res = mono_object_new (domain, mono_class_from_mono_type (type->type));
3544 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (src, res);
3550 ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *type, MonoString *field_name)
3552 MonoMarshalType *info;
3555 int i, match_index = -1;
3557 MONO_ARCH_SAVE_REGS;
3559 MONO_CHECK_ARG_NULL (type);
3560 MONO_CHECK_ARG_NULL (field_name);
3562 fname = mono_string_to_utf8 (field_name);
3563 klass = mono_class_from_mono_type (type->type);
3565 while(klass && match_index == -1) {
3566 for (i = 0; i < klass->field.count; ++i) {
3567 if (*fname == *klass->fields [i].name && strcmp (fname, klass->fields [i].name) == 0) {
3573 if(match_index == -1)
3574 klass = klass->parent;
3579 if(match_index == -1) {
3583 /* Get back original class instance */
3584 klass = mono_class_from_mono_type (type->type);
3586 tmp = g_strdup_printf ("Field passed in is not a marshaled member of the type %s", klass->name);
3587 exc = mono_get_exception_argument ("fieldName", tmp);
3590 mono_raise_exception ((MonoException*)exc);
3593 info = mono_marshal_load_type_info (klass);
3594 return info->fields [match_index].offset;
3598 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString *string)
3600 MONO_ARCH_SAVE_REGS;
3602 return mono_string_to_utf8 (string);
3606 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni (MonoString *string)
3608 MONO_ARCH_SAVE_REGS;
3610 return g_memdup (mono_string_chars (string), mono_string_length (string)*2);
3614 mono_struct_delete_old (MonoClass *klass, char *ptr)
3616 MonoMarshalType *info;
3619 info = mono_marshal_load_type_info (klass);
3621 for (i = 0; i < info->num_fields; i++) {
3622 MonoMarshalNative ntype;
3623 MonoMarshalConv conv;
3624 MonoType *ftype = info->fields [i].field->type;
3627 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
3630 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE,
3631 klass->unicode, &conv);
3633 cpos = ptr + info->fields [i].offset;
3636 case MONO_MARSHAL_CONV_NONE:
3637 if (MONO_TYPE_ISSTRUCT (ftype)) {
3638 mono_struct_delete_old (ftype->data.klass, cpos);
3642 case MONO_MARSHAL_CONV_STR_LPWSTR:
3643 case MONO_MARSHAL_CONV_STR_LPSTR:
3644 case MONO_MARSHAL_CONV_STR_LPTSTR:
3645 case MONO_MARSHAL_CONV_STR_BSTR:
3646 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
3647 case MONO_MARSHAL_CONV_STR_TBSTR:
3648 g_free (*(gpointer *)cpos);
3657 ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure (gpointer src, MonoReflectionType *type)
3661 MONO_ARCH_SAVE_REGS;
3663 MONO_CHECK_ARG_NULL (src);
3664 MONO_CHECK_ARG_NULL (type);
3666 klass = mono_class_from_mono_type (type->type);
3668 mono_struct_delete_old (klass, (char *)src);