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"
24 //#define DEBUG_RUNTIME_CODE
26 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
30 #include "mono/cil/opcode.def"
35 struct _MonoMethodBuilder {
39 guint32 code_size, pos;
44 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object);
47 mono_find_method_by_name (MonoClass *klass, const char *name, int param_count)
49 MonoMethod *res = NULL;
52 for (i = 0; i < klass->method.count; ++i) {
53 if (klass->methods [i]->name[0] == name [0] &&
54 !strcmp (name, klass->methods [i]->name) &&
55 klass->methods [i]->signature->param_count == param_count) {
56 res = klass->methods [i];
63 #ifdef DEBUG_RUNTIME_CODE
65 indenter (MonoDisHelper *dh, MonoMethod *method, guint32 ip_offset)
67 return g_strdup (" ");
70 static MonoDisHelper marshal_dh = {
80 /* This mutex protects the various marshalling related caches in MonoImage */
81 static CRITICAL_SECTION marshal_mutex;
83 /* Maps wrapper methods to the methods they wrap */
84 static MonoGHashTable *wrapper_hash;
86 static guint32 last_error_tls_id;
89 mono_marshal_init (void)
91 static gboolean module_initialized = FALSE;
93 if (!module_initialized) {
94 module_initialized = TRUE;
95 InitializeCriticalSection (&marshal_mutex);
96 wrapper_hash = mono_g_hash_table_new (NULL, NULL);
97 last_error_tls_id = TlsAlloc ();
102 mono_delegate_to_ftnptr (MonoDelegate *delegate)
104 MonoMethod *method, *wrapper, *invoke;
105 MonoMarshalSpec **mspecs;
112 if (delegate->delegate_trampoline)
113 return delegate->delegate_trampoline;
115 klass = ((MonoObject *)delegate)->vtable->klass;
116 g_assert (klass->delegate);
119 method = delegate->method_info->method;
120 invoke = mono_find_method_by_name (klass, "Invoke", method->signature->param_count);
122 mspecs = g_new (MonoMarshalSpec*, invoke->signature->param_count + 1);
123 mono_method_get_marshal_info (invoke, mspecs);
125 wrapper = mono_marshal_get_managed_wrapper (method, delegate->target, mspecs);
127 for (i = invoke->signature->param_count; i >= 0; i--)
131 delegate->delegate_trampoline = mono_compile_method (wrapper);
133 return delegate->delegate_trampoline;
137 mono_array_to_savearray (MonoArray *array)
142 g_assert_not_reached ();
147 mono_array_to_lparray (MonoArray *array)
152 /* fixme: maybe we need to make a copy */
153 return array->vector;
157 mono_string_utf8_to_builder (MonoStringBuilder *sb, char *text)
159 GError *error = NULL;
169 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
171 if (items_written > sb->capacity)
172 items_written = sb->capacity;
175 memcpy (sb->chars->vector, ut, items_written * 2);
176 sb->length = items_written;
178 g_error_free (error);
184 mono_string_builder_to_utf8 (MonoStringBuilder *sb)
191 res = g_malloc (sb->capacity + 1);
193 /* fixme: copy the content of the string builder? */
200 mono_string_to_ansibstr (MonoString *string_obj)
202 g_error ("implement me");
207 mono_string_to_bstr (MonoString *string_obj)
209 g_error ("implement me");
214 mono_string_to_byvalstr (gpointer dst, MonoString *src, int size)
219 g_assert (dst != NULL);
222 memset (dst, 0, size);
227 s = mono_string_to_utf8 (src);
228 len = MIN (size, strlen (s));
229 memcpy (dst, s, len);
232 *((char *)dst + size - 1) = 0;
236 mono_string_to_byvalwstr (gpointer dst, MonoString *src, int size)
240 g_assert (dst != NULL);
244 memset (dst, 0, size);
248 len = MIN (size, (mono_string_length (src) * 2));
249 memcpy (dst, mono_string_chars (src), len);
251 *((char *)dst + size - 1) = 0;
252 *((char *)dst + size - 2) = 0;
256 mono_mb_free (MonoMethodBuilder *mb)
258 g_list_free (mb->locals_list);
263 mono_mb_new (MonoClass *klass, const char *name, MonoWrapperType type)
265 MonoMethodBuilder *mb;
268 g_assert (klass != NULL);
269 g_assert (name != NULL);
271 mb = g_new0 (MonoMethodBuilder, 1);
273 mb->method = m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
276 m->name = g_strdup (name);
278 m->inline_count = -1;
279 m->wrapper_type = type;
282 mb->code = g_malloc (mb->code_size);
288 mono_mb_add_local (MonoMethodBuilder *mb, MonoType *type)
290 int res = mb->locals;
292 g_assert (mb != NULL);
293 g_assert (type != NULL);
295 mb->locals_list = g_list_append (mb->locals_list, type);
302 mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack)
304 MonoMethodHeader *header;
308 g_assert (mb != NULL);
310 ((MonoMethodNormal *)mb->method)->header = header = (MonoMethodHeader *)
311 g_malloc0 (sizeof (MonoMethodHeader) + mb->locals * sizeof (MonoType *));
316 header->max_stack = max_stack;
318 for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
319 header->locals [i] = (MonoType *)l->data;
322 mb->method->signature = signature;
323 header->code = mb->code;
324 header->code_size = mb->pos;
325 header->num_locals = mb->locals;
327 #ifdef DEBUG_RUNTIME_CODE
328 printf ("RUNTIME CODE FOR %s\n", mono_method_full_name (mb->method, TRUE));
329 printf ("%s\n", mono_disasm_code (&marshal_dh, mb->method, mb->code, mb->code + mb->pos));
336 mono_mb_add_data (MonoMethodBuilder *mb, gpointer data)
338 MonoMethodWrapper *mw;
340 g_assert (mb != NULL);
342 mw = (MonoMethodWrapper *)mb->method;
344 mw->data = g_list_append (mw->data, data);
346 return g_list_length (mw->data);
350 mono_mb_patch_addr (MonoMethodBuilder *mb, int pos, int value)
352 mb->code [pos] = value & 0xff;
353 mb->code [pos + 1] = (value >> 8) & 0xff;
354 mb->code [pos + 2] = (value >> 16) & 0xff;
355 mb->code [pos + 3] = (value >> 24) & 0xff;
359 mono_mb_patch_addr_s (MonoMethodBuilder *mb, int pos, gint8 value)
361 *((gint8 *)(&mb->code [pos])) = value;
365 mono_mb_emit_byte (MonoMethodBuilder *mb, guint8 op)
367 if (mb->pos >= mb->code_size) {
369 mb->code = g_realloc (mb->code, mb->code_size);
372 mb->code [mb->pos++] = op;
376 mono_mb_emit_ldflda (MonoMethodBuilder *mb, gint32 offset)
378 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
379 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
382 mono_mb_emit_icon (mb, offset);
383 mono_mb_emit_byte (mb, CEE_ADD);
388 mono_mb_emit_proxy_check (MonoMethodBuilder *mb, int branch_code)
391 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoObject, vtable));
392 mono_mb_emit_byte (mb, CEE_LDIND_I);
393 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoVTable, klass));
394 mono_mb_emit_byte (mb, CEE_ADD);
395 mono_mb_emit_byte (mb, CEE_LDIND_I);
396 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
397 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
398 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_defaults.transparent_proxy_class));
399 mono_mb_emit_byte (mb, branch_code);
401 mono_mb_emit_i4 (mb, 0);
406 mono_mb_emit_i4 (MonoMethodBuilder *mb, gint32 data)
408 if ((mb->pos + 4) >= mb->code_size) {
410 mb->code = g_realloc (mb->code, mb->code_size);
413 mono_mb_patch_addr (mb, mb->pos, data);
418 mono_mb_emit_i2 (MonoMethodBuilder *mb, gint16 data)
420 if ((mb->pos + 2) >= mb->code_size) {
422 mb->code = g_realloc (mb->code, mb->code_size);
425 mb->code [mb->pos] = data & 0xff;
426 mb->code [mb->pos + 1] = (data >> 8) & 0xff;
431 mono_mb_emit_ldstr (MonoMethodBuilder *mb, char *str)
433 mono_mb_emit_byte (mb, CEE_LDSTR);
434 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, str));
439 mono_mb_emit_ldarg (MonoMethodBuilder *mb, guint argnum)
442 mono_mb_emit_byte (mb, CEE_LDARG_0 + argnum);
443 } else if (argnum < 256) {
444 mono_mb_emit_byte (mb, CEE_LDARG_S);
445 mono_mb_emit_byte (mb, argnum);
447 mono_mb_emit_byte (mb, CEE_PREFIX1);
448 mono_mb_emit_byte (mb, CEE_LDARG);
449 mono_mb_emit_i2 (mb, argnum);
454 mono_mb_emit_ldarg_addr (MonoMethodBuilder *mb, guint argnum)
457 mono_mb_emit_byte (mb, CEE_LDARGA_S);
458 mono_mb_emit_byte (mb, argnum);
460 mono_mb_emit_byte (mb, CEE_PREFIX1);
461 mono_mb_emit_byte (mb, CEE_LDARGA);
462 mono_mb_emit_i2 (mb, argnum);
467 mono_mb_emit_ldloc_addr (MonoMethodBuilder *mb, guint locnum)
470 mono_mb_emit_byte (mb, CEE_LDLOCA_S);
471 mono_mb_emit_byte (mb, locnum);
473 mono_mb_emit_byte (mb, CEE_PREFIX1);
474 mono_mb_emit_byte (mb, CEE_LDLOCA);
475 mono_mb_emit_i2 (mb, locnum);
480 mono_mb_emit_ldloc (MonoMethodBuilder *mb, guint num)
483 mono_mb_emit_byte (mb, CEE_LDLOC_0 + num);
484 } else if (num < 256) {
485 mono_mb_emit_byte (mb, CEE_LDLOC_S);
486 mono_mb_emit_byte (mb, num);
488 mono_mb_emit_byte (mb, CEE_PREFIX1);
489 mono_mb_emit_byte (mb, CEE_LDLOC);
490 mono_mb_emit_i2 (mb, num);
495 mono_mb_emit_stloc (MonoMethodBuilder *mb, guint num)
498 mono_mb_emit_byte (mb, CEE_STLOC_0 + num);
499 } else if (num < 256) {
500 mono_mb_emit_byte (mb, CEE_STLOC_S);
501 mono_mb_emit_byte (mb, num);
503 mono_mb_emit_byte (mb, CEE_PREFIX1);
504 mono_mb_emit_byte (mb, CEE_STLOC);
505 mono_mb_emit_i2 (mb, num);
510 mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value)
512 if (value >= -1 && value < 8) {
513 mono_mb_emit_byte (mb, CEE_LDC_I4_0 + value);
514 } else if (value >= -128 && value <= 127) {
515 mono_mb_emit_byte (mb, CEE_LDC_I4_S);
516 mono_mb_emit_byte (mb, value);
518 mono_mb_emit_byte (mb, CEE_LDC_I4);
519 mono_mb_emit_i4 (mb, value);
524 mono_mb_emit_branch (MonoMethodBuilder *mb, guint8 op)
527 mono_mb_emit_byte (mb, op);
529 mono_mb_emit_i4 (mb, 0);
534 mono_mb_emit_managed_call (MonoMethodBuilder *mb, MonoMethod *method, MonoMethodSignature *opt_sig)
537 opt_sig = method->signature;
538 mono_mb_emit_byte (mb, CEE_PREFIX1);
539 mono_mb_emit_byte (mb, CEE_LDFTN);
540 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
541 mono_mb_emit_byte (mb, CEE_CALLI);
542 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, opt_sig));
546 mono_mb_emit_native_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, gpointer func)
548 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
549 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
550 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, func));
551 mono_mb_emit_byte (mb, CEE_CALLI);
552 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
556 mono_mb_emit_exception (MonoMethodBuilder *mb, const char *exc_name)
558 /* fixme: we need a better way to throw exception,
559 * supporting several exception types and messages */
560 MonoMethod *ctor = NULL;
562 MonoClass *mme = mono_class_from_name (mono_defaults.corlib, "System", exc_name);
564 mono_class_init (mme);
565 for (i = 0; i < mme->method.count; ++i) {
566 if (strcmp (mme->methods [i]->name, ".ctor") == 0 && mme->methods [i]->signature->param_count == 0) {
567 ctor = mme->methods [i];
572 mono_mb_emit_byte (mb, CEE_NEWOBJ);
573 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, ctor));
574 mono_mb_emit_byte (mb, CEE_THROW);
579 mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint16 local, gint32 incr)
581 mono_mb_emit_ldloc (mb, local);
582 mono_mb_emit_icon (mb, incr);
583 mono_mb_emit_byte (mb, CEE_ADD);
584 mono_mb_emit_stloc (mb, local);
588 emit_ptr_to_str_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv,
589 int usize, int msize, MonoMarshalSpec *mspec)
592 case MONO_MARSHAL_CONV_BOOL_I4:
593 mono_mb_emit_byte (mb, CEE_LDLOC_1);
594 mono_mb_emit_byte (mb, CEE_LDLOC_0);
595 mono_mb_emit_byte (mb, CEE_LDIND_I4);
596 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
597 mono_mb_emit_byte (mb, 3);
598 mono_mb_emit_byte (mb, CEE_LDC_I4_1);
599 mono_mb_emit_byte (mb, CEE_BR_S);
600 mono_mb_emit_byte (mb, 1);
601 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
602 mono_mb_emit_byte (mb, CEE_STIND_I1);
604 case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
605 mono_mb_emit_byte (mb, CEE_LDLOC_1);
606 mono_mb_emit_byte (mb, CEE_LDLOC_0);
607 mono_mb_emit_byte (mb, CEE_LDIND_I2);
608 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
609 mono_mb_emit_byte (mb, 3);
610 mono_mb_emit_byte (mb, CEE_LDC_I4_1);
611 mono_mb_emit_byte (mb, CEE_BR_S);
612 mono_mb_emit_byte (mb, 1);
613 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
614 mono_mb_emit_byte (mb, CEE_STIND_I1);
616 case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
620 if (type->type == MONO_TYPE_SZARRAY) {
621 eclass = type->data.klass;
623 g_assert_not_reached ();
626 if (eclass->valuetype)
627 esize = mono_class_instance_size (eclass) - sizeof (MonoObject);
629 esize = sizeof (gpointer);
631 /* create a new array */
632 mono_mb_emit_byte (mb, CEE_LDLOC_1);
633 mono_mb_emit_icon (mb, mspec->data.array_data.num_elem);
634 mono_mb_emit_byte (mb, CEE_NEWARR);
635 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eclass));
636 mono_mb_emit_byte (mb, CEE_STIND_I);
638 /* copy the elements */
639 mono_mb_emit_byte (mb, CEE_LDLOC_1);
640 mono_mb_emit_byte (mb, CEE_LDIND_I);
641 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
642 mono_mb_emit_byte (mb, CEE_ADD);
643 mono_mb_emit_byte (mb, CEE_LDLOC_0);
644 mono_mb_emit_icon (mb, mspec->data.array_data.num_elem * esize);
645 mono_mb_emit_byte (mb, CEE_PREFIX1);
646 mono_mb_emit_byte (mb, CEE_CPBLK);
650 case MONO_MARSHAL_CONV_STR_BYVALSTR:
651 mono_mb_emit_byte (mb, CEE_LDLOC_1);
652 mono_mb_emit_byte (mb, CEE_LDLOC_0);
653 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
654 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
655 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
656 mono_mb_emit_byte (mb, CEE_STIND_I);
658 case MONO_MARSHAL_CONV_STR_LPTSTR:
659 case MONO_MARSHAL_CONV_STR_LPSTR:
660 mono_mb_emit_byte (mb, CEE_LDLOC_1);
661 mono_mb_emit_byte (mb, CEE_LDLOC_0);
662 mono_mb_emit_byte (mb, CEE_LDIND_I);
663 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
664 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
665 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
666 mono_mb_emit_byte (mb, CEE_STIND_I);
668 case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
669 MonoClass *klass = mono_class_from_mono_type (type);
670 int src_var, dst_var;
672 src_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
673 dst_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
675 /* *dst = new object */
676 mono_mb_emit_byte (mb, CEE_LDLOC_1);
677 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
678 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
679 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
680 mono_mb_emit_byte (mb, CEE_STIND_I);
682 /* save the old src pointer */
683 mono_mb_emit_byte (mb, CEE_LDLOC_0);
684 mono_mb_emit_stloc (mb, src_var);
685 /* save the old dst pointer */
686 mono_mb_emit_byte (mb, CEE_LDLOC_1);
687 mono_mb_emit_stloc (mb, dst_var);
689 /* dst = pointer to newly created object data */
690 mono_mb_emit_byte (mb, CEE_LDLOC_1);
691 mono_mb_emit_byte (mb, CEE_LDIND_I);
692 mono_mb_emit_icon (mb, sizeof (MonoObject));
693 mono_mb_emit_byte (mb, CEE_ADD);
694 mono_mb_emit_byte (mb, CEE_STLOC_1);
696 emit_struct_conv (mb, klass, TRUE);
698 /* restore the old src pointer */
699 mono_mb_emit_ldloc (mb, src_var);
700 mono_mb_emit_byte (mb, CEE_STLOC_0);
701 /* restore the old dst pointer */
702 mono_mb_emit_ldloc (mb, dst_var);
703 mono_mb_emit_byte (mb, CEE_STLOC_1);
706 case MONO_MARSHAL_CONV_DEL_FTN: {
707 // fixme: we never convert functions back to delegates, dont
708 // know if thats the correct behaviour
711 case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
712 g_error ("Structure field of type %s can't be marshalled as LPArray", mono_class_from_mono_type (type)->name);
714 case MONO_MARSHAL_CONV_STR_LPWSTR:
715 case MONO_MARSHAL_CONV_STR_BSTR:
716 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
717 case MONO_MARSHAL_CONV_STR_TBSTR:
718 case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
719 case MONO_MARSHAL_CONV_STR_BYVALWSTR:
721 g_warning ("marshaling conversion %d not implemented", conv);
722 g_assert_not_reached ();
727 emit_str_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, int usize, int msize,
728 MonoMarshalSpec *mspec)
733 case MONO_MARSHAL_CONV_BOOL_I4:
734 mono_mb_emit_byte (mb, CEE_LDLOC_1);
735 mono_mb_emit_byte (mb, CEE_LDLOC_0);
736 mono_mb_emit_byte (mb, CEE_LDIND_U1);
737 mono_mb_emit_byte (mb, CEE_STIND_I4);
739 case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
740 mono_mb_emit_byte (mb, CEE_LDLOC_1);
741 mono_mb_emit_byte (mb, CEE_LDLOC_0);
742 mono_mb_emit_byte (mb, CEE_LDIND_U1);
743 mono_mb_emit_byte (mb, CEE_NEG);
744 mono_mb_emit_byte (mb, CEE_STIND_I2);
746 case MONO_MARSHAL_CONV_STR_LPWSTR:
747 case MONO_MARSHAL_CONV_STR_LPSTR:
748 case MONO_MARSHAL_CONV_STR_LPTSTR:
749 case MONO_MARSHAL_CONV_STR_BSTR:
750 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
751 case MONO_MARSHAL_CONV_STR_TBSTR:
752 /* free space if free == true */
753 mono_mb_emit_byte (mb, CEE_LDLOC_2);
754 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
755 mono_mb_emit_byte (mb, 4);
756 mono_mb_emit_byte (mb, CEE_LDLOC_1);
757 mono_mb_emit_byte (mb, CEE_LDIND_I);
758 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
759 mono_mb_emit_byte (mb, CEE_MONO_FREE);
761 mono_mb_emit_byte (mb, CEE_LDLOC_1);
762 mono_mb_emit_byte (mb, CEE_LDLOC_0);
763 mono_mb_emit_byte (mb, CEE_LDIND_I);
764 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
765 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
766 mono_mb_emit_byte (mb, conv);
767 mono_mb_emit_byte (mb, CEE_STIND_I);
769 case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
770 case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
771 case MONO_MARSHAL_CONV_DEL_FTN:
772 mono_mb_emit_byte (mb, CEE_LDLOC_1);
773 mono_mb_emit_byte (mb, CEE_LDLOC_0);
774 mono_mb_emit_byte (mb, CEE_LDIND_I);
775 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
776 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
777 mono_mb_emit_byte (mb, conv);
778 mono_mb_emit_byte (mb, CEE_STIND_I);
780 case MONO_MARSHAL_CONV_STR_BYVALSTR:
781 case MONO_MARSHAL_CONV_STR_BYVALWSTR: {
785 mono_mb_emit_byte (mb, CEE_LDLOC_1); /* dst */
786 mono_mb_emit_byte (mb, CEE_LDLOC_0);
787 mono_mb_emit_byte (mb, CEE_LDIND_I); /* src String */
788 mono_mb_emit_icon (mb, usize);
789 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
790 mono_mb_emit_byte (mb, CEE_MONO_PROC3);
791 mono_mb_emit_byte (mb, conv);
794 case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
798 if (type->type == MONO_TYPE_SZARRAY) {
799 eclass = type->data.klass;
801 g_assert_not_reached ();
804 if (eclass->valuetype)
805 esize = mono_class_native_size (eclass, NULL);
807 esize = sizeof (gpointer);
812 mono_mb_emit_byte (mb, CEE_LDLOC_0);
813 mono_mb_emit_byte (mb, CEE_LDIND_I);
814 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
816 mono_mb_emit_byte (mb, 0);
818 mono_mb_emit_byte (mb, CEE_LDLOC_1);
819 mono_mb_emit_byte (mb, CEE_LDLOC_0);
820 mono_mb_emit_byte (mb, CEE_LDIND_I);
821 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
822 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
823 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
824 mono_mb_emit_byte (mb, CEE_ADD);
825 mono_mb_emit_icon (mb, mspec->data.array_data.num_elem * esize);
826 mono_mb_emit_byte (mb, CEE_PREFIX1);
827 mono_mb_emit_byte (mb, CEE_CPBLK);
828 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
831 case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
832 int src_var, dst_var;
834 src_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
835 dst_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
837 mono_mb_emit_byte (mb, CEE_LDLOC_0);
838 mono_mb_emit_byte (mb, CEE_LDIND_I);
839 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
841 mono_mb_emit_byte (mb, 0);
843 /* save the old src pointer */
844 mono_mb_emit_byte (mb, CEE_LDLOC_0);
845 mono_mb_emit_stloc (mb, src_var);
846 /* save the old dst pointer */
847 mono_mb_emit_byte (mb, CEE_LDLOC_1);
848 mono_mb_emit_stloc (mb, dst_var);
850 /* src = pointer to object data */
851 mono_mb_emit_byte (mb, CEE_LDLOC_0);
852 mono_mb_emit_byte (mb, CEE_LDIND_I);
853 mono_mb_emit_icon (mb, sizeof (MonoObject));
854 mono_mb_emit_byte (mb, CEE_ADD);
855 mono_mb_emit_byte (mb, CEE_STLOC_0);
857 emit_struct_conv (mb, mono_class_from_mono_type (type), FALSE);
859 /* restore the old src pointer */
860 mono_mb_emit_ldloc (mb, src_var);
861 mono_mb_emit_byte (mb, CEE_STLOC_0);
862 /* restore the old dst pointer */
863 mono_mb_emit_ldloc (mb, dst_var);
864 mono_mb_emit_byte (mb, CEE_STLOC_1);
866 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
870 g_warning ("marshalling conversion %d not implemented", conv);
871 g_assert_not_reached ();
876 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
878 MonoMarshalType *info;
882 emit_struct_conv(mb, klass->parent, to_object);
884 info = mono_marshal_load_type_info (klass);
886 if (info->native_size == 0)
889 if (klass->blittable) {
890 mono_mb_emit_byte (mb, CEE_LDLOC_1);
891 mono_mb_emit_byte (mb, CEE_LDLOC_0);
892 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
893 mono_mb_emit_byte (mb, CEE_PREFIX1);
894 mono_mb_emit_byte (mb, CEE_CPBLK);
898 for (i = 0; i < info->num_fields; i++) {
899 MonoMarshalNative ntype;
900 MonoMarshalConv conv;
901 MonoType *ftype = info->fields [i].field->type;
904 gboolean last_field = i < (info->num_fields -1) ? 0 : 1;
906 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
909 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, klass->unicode, &conv);
912 msize = klass->instance_size - info->fields [i].field->offset;
913 usize = info->native_size - info->fields [i].offset;
915 msize = info->fields [i + 1].field->offset - info->fields [i].field->offset;
916 usize = info->fields [i + 1].offset - info->fields [i].offset;
918 g_assert ((msize >= 0) && (usize >= 0));
921 case MONO_MARSHAL_CONV_NONE: {
924 if (ftype->byref || ftype->type == MONO_TYPE_I ||
925 ftype->type == MONO_TYPE_U) {
926 mono_mb_emit_byte (mb, CEE_LDLOC_1);
927 mono_mb_emit_byte (mb, CEE_LDLOC_0);
928 mono_mb_emit_byte (mb, CEE_LDIND_I);
929 mono_mb_emit_byte (mb, CEE_STIND_I);
938 #if SIZEOF_VOID_P == 4
941 mono_mb_emit_byte (mb, CEE_LDLOC_1);
942 mono_mb_emit_byte (mb, CEE_LDLOC_0);
943 mono_mb_emit_byte (mb, CEE_LDIND_I4);
944 mono_mb_emit_byte (mb, CEE_STIND_I4);
948 case MONO_TYPE_BOOLEAN:
949 mono_mb_emit_byte (mb, CEE_LDLOC_1);
950 mono_mb_emit_byte (mb, CEE_LDLOC_0);
951 mono_mb_emit_byte (mb, CEE_LDIND_I1);
952 mono_mb_emit_byte (mb, CEE_STIND_I1);
957 mono_mb_emit_byte (mb, CEE_LDLOC_1);
958 mono_mb_emit_byte (mb, CEE_LDLOC_0);
959 mono_mb_emit_byte (mb, CEE_LDIND_I2);
960 mono_mb_emit_byte (mb, CEE_STIND_I2);
964 #if SIZEOF_VOID_P == 8
967 mono_mb_emit_byte (mb, CEE_LDLOC_1);
968 mono_mb_emit_byte (mb, CEE_LDLOC_0);
969 mono_mb_emit_byte (mb, CEE_LDIND_I8);
970 mono_mb_emit_byte (mb, CEE_STIND_I8);
973 mono_mb_emit_byte (mb, CEE_LDLOC_1);
974 mono_mb_emit_byte (mb, CEE_LDLOC_0);
975 mono_mb_emit_byte (mb, CEE_LDIND_R4);
976 mono_mb_emit_byte (mb, CEE_STIND_R4);
979 mono_mb_emit_byte (mb, CEE_LDLOC_1);
980 mono_mb_emit_byte (mb, CEE_LDLOC_0);
981 mono_mb_emit_byte (mb, CEE_LDIND_R8);
982 mono_mb_emit_byte (mb, CEE_STIND_R8);
984 case MONO_TYPE_VALUETYPE:
985 if (ftype->data.klass->enumtype) {
986 t = ftype->data.klass->enum_basetype->type;
989 emit_struct_conv (mb, ftype->data.klass, to_object);
992 g_warning ("marshaling type %02x not implemented", ftype->type);
993 g_assert_not_reached ();
999 emit_ptr_to_str_conv (mb, ftype, conv, usize, msize, info->fields [i].mspec);
1001 emit_str_to_ptr_conv (mb, ftype, conv, usize, msize, info->fields [i].mspec);
1005 mono_mb_emit_add_to_local (mb, 0, usize);
1006 mono_mb_emit_add_to_local (mb, 1, msize);
1008 mono_mb_emit_add_to_local (mb, 0, msize);
1009 mono_mb_emit_add_to_local (mb, 1, usize);
1014 static MonoAsyncResult *
1015 mono_delegate_begin_invoke (MonoDelegate *delegate, gpointer *params)
1017 MonoMethodMessage *msg;
1018 MonoDelegate *async_callback;
1022 MonoMethod *method = NULL;
1025 g_assert (delegate);
1027 if (delegate->target && mono_object_class (delegate->target) == mono_defaults.transparent_proxy_class) {
1029 MonoTransparentProxy* tp = (MonoTransparentProxy *)delegate->target;
1030 if (!tp->klass->contextbound || tp->rp->context != (MonoObject *) mono_context_get ()) {
1032 // If the target is a proxy, make a direct call. Is proxy's work
1033 // to make the call asynchronous.
1035 MonoAsyncResult *ares;
1037 MonoArray *out_args;
1039 method = delegate->method_info->method;
1041 msg = mono_method_call_message_new (method, params, NULL, &async_callback, &state);
1042 handle = CreateEvent (NULL, TRUE, FALSE, NULL);
1043 ares = mono_async_result_new (mono_domain_get (), handle, state, handle);
1044 ares->async_delegate = (MonoObject *)async_callback;
1045 msg->async_result = ares;
1046 msg->call_type = CallType_BeginInvoke;
1048 mono_remoting_invoke ((MonoObject *)tp->rp, msg, &exc, &out_args);
1053 klass = delegate->object.vtable->klass;
1055 method = mono_get_delegate_invoke (klass);
1056 for (i = 0; i < klass->method.count; ++i) {
1057 if (klass->methods [i]->name[0] == 'B' &&
1058 !strcmp ("BeginInvoke", klass->methods [i]->name)) {
1059 method = klass->methods [i];
1064 g_assert (method != NULL);
1066 im = mono_get_delegate_invoke (method->klass);
1067 msg = mono_method_call_message_new (method, params, im, &async_callback, &state);
1069 return mono_thread_pool_add ((MonoObject *)delegate, msg, async_callback, state);
1073 mono_mb_emit_save_args (MonoMethodBuilder *mb, MonoMethodSignature *sig, gboolean save_this)
1075 int i, params_var, tmp_var;
1077 /* allocate local (pointer) *params[] */
1078 params_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1079 /* allocate local (pointer) tmp */
1080 tmp_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1082 /* alloate space on stack to store an array of pointers to the arguments */
1083 mono_mb_emit_icon (mb, sizeof (gpointer) * (sig->param_count + 1));
1084 mono_mb_emit_byte (mb, CEE_PREFIX1);
1085 mono_mb_emit_byte (mb, CEE_LOCALLOC);
1086 mono_mb_emit_stloc (mb, params_var);
1089 mono_mb_emit_ldloc (mb, params_var);
1090 mono_mb_emit_stloc (mb, tmp_var);
1092 if (save_this && sig->hasthis) {
1093 mono_mb_emit_ldloc (mb, tmp_var);
1094 mono_mb_emit_ldarg_addr (mb, 0);
1095 mono_mb_emit_byte (mb, CEE_STIND_I);
1096 /* tmp = tmp + sizeof (gpointer) */
1097 if (sig->param_count)
1098 mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
1102 for (i = 0; i < sig->param_count; i++) {
1103 mono_mb_emit_ldloc (mb, tmp_var);
1104 mono_mb_emit_ldarg_addr (mb, i + sig->hasthis);
1105 mono_mb_emit_byte (mb, CEE_STIND_I);
1106 /* tmp = tmp + sizeof (gpointer) */
1107 if (i < (sig->param_count - 1))
1108 mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
1115 mono_signature_to_name (MonoMethodSignature *sig, const char *prefix)
1119 GString *res = g_string_new ("");
1122 g_string_append (res, prefix);
1123 g_string_append_c (res, '_');
1126 mono_type_get_desc (res, sig->ret, FALSE);
1128 for (i = 0; i < sig->param_count; ++i) {
1129 g_string_append_c (res, '_');
1130 mono_type_get_desc (res, sig->params [i], FALSE);
1133 g_string_free (res, FALSE);
1137 static inline MonoMethod*
1138 mono_marshal_find_in_cache (GHashTable *cache, gpointer key)
1142 EnterCriticalSection (&marshal_mutex);
1143 res = g_hash_table_lookup (cache, key);
1144 LeaveCriticalSection (&marshal_mutex);
1148 /* Create the method from the builder and place it in the cache */
1149 static inline MonoMethod*
1150 mono_mb_create_and_cache (GHashTable *cache, gpointer key,
1151 MonoMethodBuilder *mb, MonoMethodSignature *sig,
1156 EnterCriticalSection (&marshal_mutex);
1157 res = g_hash_table_lookup (cache, key);
1159 /* This does not acquire any locks */
1160 res = mono_mb_create_method (mb, sig, max_stack);
1161 g_hash_table_insert (cache, key, res);
1162 mono_g_hash_table_insert (wrapper_hash, res, key);
1165 /* Somebody created it before us */
1167 LeaveCriticalSection (&marshal_mutex);
1173 mono_marshal_method_from_wrapper (MonoMethod *wrapper)
1178 (wrapper->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK) ||
1179 (wrapper->wrapper_type == MONO_WRAPPER_SYNCHRONIZED));
1181 EnterCriticalSection (&marshal_mutex);
1182 res = mono_g_hash_table_lookup (wrapper_hash, wrapper);
1183 LeaveCriticalSection (&marshal_mutex);
1185 if (wrapper->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)
1186 /* See mono_marshal_get_remoting_invoke_with_check */
1187 return (MonoMethod*)((char*)res - 1);
1193 mono_marshal_get_delegate_begin_invoke (MonoMethod *method)
1195 MonoMethodSignature *sig;
1196 static MonoMethodSignature *csig = NULL;
1197 MonoMethodBuilder *mb;
1203 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1204 !strcmp (method->name, "BeginInvoke"));
1206 sig = method->signature;
1208 cache = method->klass->image->delegate_begin_invoke_cache;
1209 if ((res = mono_marshal_find_in_cache (cache, sig)))
1212 g_assert (sig->hasthis);
1215 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1216 csig = g_malloc0 (sigsize);
1218 /* MonoAsyncResult * begin_invoke (MonoDelegate *delegate, gpointer params[]) */
1219 csig->param_count = 2;
1220 csig->ret = &mono_defaults.object_class->byval_arg;
1221 csig->params [0] = &mono_defaults.object_class->byval_arg;
1222 csig->params [1] = &mono_defaults.int_class->byval_arg;
1225 name = mono_signature_to_name (sig, "begin_invoke");
1226 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_BEGIN_INVOKE);
1229 mb->method->save_lmf = 1;
1231 params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1233 mono_mb_emit_ldarg (mb, 0);
1234 mono_mb_emit_ldloc (mb, params_var);
1235 mono_mb_emit_native_call (mb, csig, mono_delegate_begin_invoke);
1236 mono_mb_emit_byte (mb, CEE_RET);
1238 res = mono_mb_create_and_cache (cache, sig, mb, sig, sig->param_count + 16);
1244 mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params)
1246 MonoDomain *domain = mono_domain_get ();
1247 MonoAsyncResult *ares;
1248 MonoMethod *method = NULL;
1249 MonoMethodSignature *sig;
1250 MonoMethodMessage *msg;
1251 MonoObject *res, *exc;
1252 MonoArray *out_args;
1256 g_assert (delegate);
1258 if (!delegate->method_info || !delegate->method_info->method)
1259 g_assert_not_reached ();
1261 klass = delegate->object.vtable->klass;
1263 for (i = 0; i < klass->method.count; ++i) {
1264 if (klass->methods [i]->name[0] == 'E' &&
1265 !strcmp ("EndInvoke", klass->methods [i]->name)) {
1266 method = klass->methods [i];
1271 g_assert (method != NULL);
1273 sig = method->signature;
1275 msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1277 ares = mono_array_get (msg->args, gpointer, sig->param_count - 1);
1280 if (delegate->target && mono_object_class (delegate->target) == mono_defaults.transparent_proxy_class) {
1281 MonoTransparentProxy* tp = (MonoTransparentProxy *)delegate->target;
1282 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
1283 mono_message_init (domain, msg, delegate->method_info, NULL);
1284 msg->call_type = CallType_EndInvoke;
1285 msg->async_result = ares;
1286 res = mono_remoting_invoke ((MonoObject *)tp->rp, msg, &exc, &out_args);
1289 res = mono_thread_pool_finish (ares, &out_args, &exc);
1292 char *strace = mono_string_to_utf8 (((MonoException*)exc)->stack_trace);
1294 tmp = g_strdup_printf ("%s\nException Rethrown at:\n", strace);
1296 ((MonoException*)exc)->stack_trace = mono_string_new (domain, tmp);
1298 mono_raise_exception ((MonoException*)exc);
1301 mono_method_return_message_restore (method, params, out_args);
1306 mono_mb_emit_restore_result (MonoMethodBuilder *mb, MonoType *return_type)
1308 if (return_type->byref)
1309 return_type = &mono_defaults.int_class->byval_arg;
1310 else if (return_type->type == MONO_TYPE_VALUETYPE && return_type->data.klass->enumtype)
1311 return_type = return_type->data.klass->enum_basetype;
1313 switch (return_type->type) {
1314 case MONO_TYPE_VOID:
1315 g_assert_not_reached ();
1318 case MONO_TYPE_STRING:
1319 case MONO_TYPE_CLASS:
1320 case MONO_TYPE_OBJECT:
1321 case MONO_TYPE_ARRAY:
1322 case MONO_TYPE_SZARRAY:
1326 case MONO_TYPE_BOOLEAN:
1327 mono_mb_emit_byte (mb, CEE_UNBOX);
1328 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1329 mono_mb_emit_byte (mb, CEE_LDIND_U1);
1332 mono_mb_emit_byte (mb, CEE_UNBOX);
1333 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1334 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1337 case MONO_TYPE_CHAR:
1338 mono_mb_emit_byte (mb, CEE_UNBOX);
1339 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1340 mono_mb_emit_byte (mb, CEE_LDIND_U2);
1343 mono_mb_emit_byte (mb, CEE_UNBOX);
1344 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1345 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1349 mono_mb_emit_byte (mb, CEE_UNBOX);
1350 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1351 mono_mb_emit_byte (mb, CEE_LDIND_I);
1354 mono_mb_emit_byte (mb, CEE_UNBOX);
1355 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1356 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1359 mono_mb_emit_byte (mb, CEE_UNBOX);
1360 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1361 mono_mb_emit_byte (mb, CEE_LDIND_U4);
1365 mono_mb_emit_byte (mb, CEE_UNBOX);
1366 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1367 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1370 mono_mb_emit_byte (mb, CEE_UNBOX);
1371 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1372 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1375 mono_mb_emit_byte (mb, CEE_UNBOX);
1376 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1377 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1379 case MONO_TYPE_VALUETYPE: {
1381 mono_mb_emit_byte (mb, CEE_UNBOX);
1382 class = mono_mb_add_data (mb, mono_class_from_mono_type (return_type));
1383 mono_mb_emit_i4 (mb, class);
1384 mono_mb_emit_byte (mb, CEE_LDOBJ);
1385 mono_mb_emit_i4 (mb, class);
1389 g_warning ("type 0x%x not handled", return_type->type);
1390 g_assert_not_reached ();
1393 mono_mb_emit_byte (mb, CEE_RET);
1397 mono_marshal_get_delegate_end_invoke (MonoMethod *method)
1399 MonoMethodSignature *sig;
1400 static MonoMethodSignature *csig = NULL;
1401 MonoMethodBuilder *mb;
1407 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1408 !strcmp (method->name, "EndInvoke"));
1410 sig = method->signature;
1412 cache = method->klass->image->delegate_end_invoke_cache;
1413 if ((res = mono_marshal_find_in_cache (cache, sig)))
1416 g_assert (sig->hasthis);
1419 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1420 csig = g_malloc0 (sigsize);
1422 /* MonoObject *end_invoke (MonoDelegate *delegate, gpointer params[]) */
1423 csig->param_count = 2;
1424 csig->ret = &mono_defaults.object_class->byval_arg;
1425 csig->params [0] = &mono_defaults.object_class->byval_arg;
1426 csig->params [1] = &mono_defaults.int_class->byval_arg;
1429 name = mono_signature_to_name (sig, "end_invoke");
1430 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_END_INVOKE);
1433 mb->method->save_lmf = 1;
1435 params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1437 mono_mb_emit_ldarg (mb, 0);
1438 mono_mb_emit_ldloc (mb, params_var);
1439 mono_mb_emit_native_call (mb, csig, mono_delegate_end_invoke);
1441 if (sig->ret->type == MONO_TYPE_VOID) {
1442 mono_mb_emit_byte (mb, CEE_POP);
1443 mono_mb_emit_byte (mb, CEE_RET);
1445 mono_mb_emit_restore_result (mb, sig->ret);
1447 res = mono_mb_create_and_cache (cache, sig,
1448 mb, sig, sig->param_count + 16);
1455 mono_remoting_wrapper (MonoMethod *method, gpointer *params)
1457 MonoMethodMessage *msg;
1458 MonoTransparentProxy *this;
1459 MonoObject *res, *exc;
1460 MonoArray *out_args;
1462 this = *((MonoTransparentProxy **)params [0]);
1465 g_assert (((MonoObject *)this)->vtable->klass == mono_defaults.transparent_proxy_class);
1467 /* skip the this pointer */
1470 if (this->klass->contextbound && this->rp->context == (MonoObject *) mono_context_get ())
1473 MonoMethodSignature *sig = method->signature;
1474 int count = sig->param_count;
1475 gpointer* mparams = (gpointer*) alloca(count*sizeof(gpointer));
1477 for (i=0; i<count; i++) {
1478 MonoClass *class = mono_class_from_mono_type (sig->params [i]);
1479 if (class->valuetype) {
1480 if (sig->params [i]->byref)
1481 mparams[i] = *((gpointer *)params [i]);
1483 mparams[i] = params [i];
1485 mparams[i] = *((gpointer**)params [i]);
1489 return mono_runtime_invoke (method, this->rp->unwrapped_server, mparams, NULL);
1492 msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1494 res = mono_remoting_invoke ((MonoObject *)this->rp, msg, &exc, &out_args);
1497 mono_raise_exception ((MonoException *)exc);
1499 mono_method_return_message_restore (method, params, out_args);
1505 mono_marshal_get_remoting_invoke (MonoMethod *method)
1507 MonoMethodSignature *sig;
1508 static MonoMethodSignature *csig = NULL;
1509 MonoMethodBuilder *mb;
1516 if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE)
1519 sig = method->signature;
1521 /* we cant remote methods without this pointer */
1525 cache = method->klass->image->remoting_invoke_cache;
1526 if ((res = mono_marshal_find_in_cache (cache, method)))
1530 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
1531 csig->params [0] = &mono_defaults.int_class->byval_arg;
1532 csig->params [1] = &mono_defaults.int_class->byval_arg;
1533 csig->ret = &mono_defaults.object_class->byval_arg;
1537 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE);
1538 mb->method->save_lmf = 1;
1540 params_var = mono_mb_emit_save_args (mb, sig, TRUE);
1542 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1543 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1544 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
1545 mono_mb_emit_ldloc (mb, params_var);
1546 mono_mb_emit_native_call (mb, csig, mono_remoting_wrapper);
1548 if (sig->ret->type == MONO_TYPE_VOID) {
1549 mono_mb_emit_byte (mb, CEE_POP);
1550 mono_mb_emit_byte (mb, CEE_RET);
1552 mono_mb_emit_restore_result (mb, sig->ret);
1555 res = mono_mb_create_and_cache (cache, method, mb, sig, sig->param_count + 16);
1562 mono_marshal_get_remoting_invoke_with_check (MonoMethod *method)
1564 MonoMethodSignature *sig;
1565 MonoMethodBuilder *mb;
1566 MonoMethod *res, *native;
1572 if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)
1575 sig = method->signature;
1577 /* we cant remote methods without this pointer */
1578 g_assert (sig->hasthis);
1580 cache = method->klass->image->remoting_invoke_cache;
1581 if ((res = mono_marshal_find_in_cache (cache, (char *)method + 1)))
1584 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK);
1586 mono_mb_emit_ldarg (mb, 0);
1587 pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
1589 native = mono_marshal_get_remoting_invoke (method);
1591 for (i = 0; i <= sig->param_count; i++)
1592 mono_mb_emit_ldarg (mb, i);
1594 mono_mb_emit_managed_call (mb, native, native->signature);
1595 mono_mb_emit_byte (mb, CEE_RET);
1597 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1599 for (i = 0; i <= sig->param_count; i++)
1600 mono_mb_emit_ldarg (mb, i);
1602 mono_mb_emit_managed_call (mb, method, method->signature);
1603 mono_mb_emit_byte (mb, CEE_RET);
1605 res = mono_mb_create_and_cache (cache, (char*)method + 1,
1606 mb, sig, sig->param_count + 16);
1613 * the returned method invokes all methods in a multicast delegate
1616 mono_marshal_get_delegate_invoke (MonoMethod *method)
1618 MonoMethodSignature *sig, *static_sig;
1620 MonoMethodBuilder *mb;
1626 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1627 !strcmp (method->name, "Invoke"));
1629 sig = method->signature;
1631 cache = method->klass->image->delegate_invoke_cache;
1632 if ((res = mono_marshal_find_in_cache (cache, sig)))
1635 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1636 static_sig = g_memdup (sig, sigsize);
1637 static_sig->hasthis = 0;
1639 name = mono_signature_to_name (sig, "invoke");
1640 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_INVOKE);
1643 /* allocate local 0 (object) */
1644 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1646 g_assert (sig->hasthis);
1650 * prev.Invoke( args .. );
1651 * return this.<target>( args .. );
1654 /* get this->prev */
1655 mono_mb_emit_ldarg (mb, 0);
1656 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoMulticastDelegate, prev));
1657 mono_mb_emit_byte (mb, CEE_LDIND_I );
1658 mono_mb_emit_stloc (mb, 0);
1660 /* if prev != null */
1661 mono_mb_emit_ldloc (mb, 0);
1662 mono_mb_emit_byte (mb, CEE_BRFALSE);
1665 mono_mb_emit_i4 (mb, 0);
1668 mono_mb_emit_ldloc (mb, 0);
1669 for (i = 0; i < sig->param_count; i++)
1670 mono_mb_emit_ldarg (mb, i + 1);
1671 mono_mb_emit_managed_call (mb, method, method->signature);
1672 if (sig->ret->type != MONO_TYPE_VOID)
1673 mono_mb_emit_byte (mb, CEE_POP);
1675 /* continued or prev == null */
1676 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1678 /* get this->target */
1679 mono_mb_emit_ldarg (mb, 0);
1680 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, target));
1681 mono_mb_emit_byte (mb, CEE_LDIND_I );
1682 mono_mb_emit_stloc (mb, 0);
1684 /* if target != null */
1685 mono_mb_emit_ldloc (mb, 0);
1686 mono_mb_emit_byte (mb, CEE_BRFALSE);
1688 mono_mb_emit_i4 (mb, 0);
1690 /* then call this->method_ptr nonstatic */
1691 mono_mb_emit_ldloc (mb, 0);
1692 for (i = 0; i < sig->param_count; ++i)
1693 mono_mb_emit_ldarg (mb, i + 1);
1694 mono_mb_emit_ldarg (mb, 0);
1695 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1696 mono_mb_emit_byte (mb, CEE_LDIND_I );
1697 mono_mb_emit_byte (mb, CEE_CALLI);
1698 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
1700 mono_mb_emit_byte (mb, CEE_BR);
1702 mono_mb_emit_i4 (mb, 0);
1704 /* else [target == null] call this->method_ptr static */
1705 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1707 for (i = 0; i < sig->param_count; ++i)
1708 mono_mb_emit_ldarg (mb, i + 1);
1709 mono_mb_emit_ldarg (mb, 0);
1710 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1711 mono_mb_emit_byte (mb, CEE_LDIND_I );
1712 mono_mb_emit_byte (mb, CEE_CALLI);
1713 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, static_sig));
1716 mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
1717 mono_mb_emit_byte (mb, CEE_RET);
1719 res = mono_mb_create_and_cache (cache, sig,
1720 mb, sig, sig->param_count + 16);
1727 * generates IL code for the runtime invoke function
1728 * MonoObject *runtime_invoke (MonoObject *this, void **params, MonoObject **exc)
1730 * we also catch exceptions if exc != null
1733 mono_marshal_get_runtime_invoke (MonoMethod *method)
1735 MonoMethodSignature *sig, *csig;
1736 MonoExceptionClause *clause;
1737 MonoMethodHeader *header;
1738 MonoMethodBuilder *mb;
1741 static MonoString *string_dummy = NULL;
1742 int i, pos, sigsize;
1746 cache = method->klass->image->runtime_invoke_cache;
1747 if ((res = mono_marshal_find_in_cache (cache, method)))
1750 /* to make it work with our special string constructors */
1752 string_dummy = mono_string_new_wrapper ("dummy");
1754 sig = method->signature;
1756 sigsize = sizeof (MonoMethodSignature) + 3 * sizeof (MonoType *);
1757 csig = g_malloc0 (sigsize);
1759 csig->param_count = 3;
1760 csig->ret = &mono_defaults.object_class->byval_arg;
1761 csig->params [0] = &mono_defaults.object_class->byval_arg;
1762 csig->params [1] = &mono_defaults.int_class->byval_arg;
1763 csig->params [2] = &mono_defaults.int_class->byval_arg;
1765 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_RUNTIME_INVOKE);
1767 /* allocate local 0 (object) tmp */
1768 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1769 /* allocate local 1 (object) exc */
1770 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1772 /* cond set *exc to null */
1773 mono_mb_emit_byte (mb, CEE_LDARG_2);
1774 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
1775 mono_mb_emit_byte (mb, 3);
1776 mono_mb_emit_byte (mb, CEE_LDARG_2);
1777 mono_mb_emit_byte (mb, CEE_LDNULL);
1778 mono_mb_emit_byte (mb, CEE_STIND_I);
1781 if (method->string_ctor) {
1782 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1783 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1784 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, string_dummy));
1786 mono_mb_emit_ldarg (mb, 0);
1787 if (method->klass->valuetype) {
1788 mono_mb_emit_byte (mb, CEE_UNBOX);
1789 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method->klass));
1794 for (i = 0; i < sig->param_count; i++) {
1795 MonoType *t = sig->params [i];
1798 mono_mb_emit_ldarg (mb, 1);
1800 mono_mb_emit_icon (mb, sizeof (gpointer) * i);
1801 mono_mb_emit_byte (mb, CEE_ADD);
1803 mono_mb_emit_byte (mb, CEE_LDIND_I);
1808 type = sig->params [i]->type;
1812 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1814 case MONO_TYPE_BOOLEAN:
1816 mono_mb_emit_byte (mb, CEE_LDIND_U1);
1819 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1822 case MONO_TYPE_CHAR:
1823 mono_mb_emit_byte (mb, CEE_LDIND_U2);
1827 mono_mb_emit_byte (mb, CEE_LDIND_I);
1830 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1833 mono_mb_emit_byte (mb, CEE_LDIND_U4);
1836 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1839 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1843 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1845 case MONO_TYPE_STRING:
1846 case MONO_TYPE_CLASS:
1847 case MONO_TYPE_ARRAY:
1849 case MONO_TYPE_SZARRAY:
1850 case MONO_TYPE_OBJECT:
1853 case MONO_TYPE_VALUETYPE:
1854 if (t->data.klass->enumtype) {
1855 type = t->data.klass->enum_basetype->type;
1858 mono_mb_emit_byte (mb, CEE_LDOBJ);
1859 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, t->data.klass));
1862 g_assert_not_reached ();
1866 if (method->string_ctor) {
1867 MonoMethodSignature *strsig;
1869 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1870 strsig = g_memdup (sig, sigsize);
1871 strsig->ret = &mono_defaults.string_class->byval_arg;
1873 mono_mb_emit_managed_call (mb, method, strsig);
1875 mono_mb_emit_managed_call (mb, method, NULL);
1877 if (sig->ret->byref) {
1879 g_assert_not_reached ();
1883 switch (sig->ret->type) {
1884 case MONO_TYPE_VOID:
1885 if (!method->string_ctor)
1886 mono_mb_emit_byte (mb, CEE_LDNULL);
1888 case MONO_TYPE_BOOLEAN:
1889 case MONO_TYPE_CHAR:
1902 case MONO_TYPE_VALUETYPE:
1903 /* box value types */
1904 mono_mb_emit_byte (mb, CEE_BOX);
1905 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (sig->ret)));
1907 case MONO_TYPE_STRING:
1908 case MONO_TYPE_CLASS:
1909 case MONO_TYPE_ARRAY:
1910 case MONO_TYPE_SZARRAY:
1911 case MONO_TYPE_OBJECT:
1916 g_assert_not_reached ();
1919 mono_mb_emit_stloc (mb, 0);
1921 mono_mb_emit_byte (mb, CEE_LEAVE);
1923 mono_mb_emit_i4 (mb, 0);
1925 clause = g_new0 (MonoExceptionClause, 1);
1926 clause->flags = MONO_EXCEPTION_CLAUSE_FILTER;
1927 clause->try_len = mb->pos;
1930 clause->token_or_filter = mb->pos;
1932 mono_mb_emit_byte (mb, CEE_POP);
1933 mono_mb_emit_byte (mb, CEE_LDARG_2);
1934 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
1935 mono_mb_emit_byte (mb, CEE_PREFIX1);
1936 mono_mb_emit_byte (mb, CEE_CGT_UN);
1937 mono_mb_emit_byte (mb, CEE_PREFIX1);
1938 mono_mb_emit_byte (mb, CEE_ENDFILTER);
1940 clause->handler_offset = mb->pos;
1943 /* store exception */
1944 mono_mb_emit_stloc (mb, 1);
1946 mono_mb_emit_byte (mb, CEE_LDARG_2);
1947 mono_mb_emit_ldloc (mb, 1);
1948 mono_mb_emit_byte (mb, CEE_STIND_I);
1950 mono_mb_emit_byte (mb, CEE_LEAVE);
1951 mono_mb_emit_i4 (mb, 0);
1953 clause->handler_len = mb->pos - clause->handler_offset;
1956 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1957 mono_mb_emit_ldloc (mb, 0);
1958 mono_mb_emit_byte (mb, CEE_RET);
1960 res = mono_mb_create_and_cache (cache, method,
1961 mb, csig, sig->param_count + 16);
1964 header = ((MonoMethodNormal *)res)->header;
1965 header->num_clauses = 1;
1966 header->clauses = clause;
1972 * generates IL code to call managed methods from unmanaged code
1975 mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this, MonoMarshalSpec **mspecs)
1977 MonoMethodSignature *sig, *csig;
1978 MonoMethodBuilder *mb;
1982 int i, pos, sigsize, *tmp_locals;
1983 static MonoMethodSignature *alloc_sig = NULL;
1986 g_assert (method != NULL);
1987 g_assert (!method->signature->pinvoke);
1989 cache = method->klass->image->managed_wrapper_cache;
1990 if (!this && (res = mono_marshal_find_in_cache (cache, method)))
1993 /* Under MS, the allocation should be done using CoTaskMemAlloc */
1995 alloc_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
1996 alloc_sig->params [0] = &mono_defaults.int_class->byval_arg;
1997 alloc_sig->ret = &mono_defaults.int_class->byval_arg;
1998 alloc_sig->pinvoke = 1;
2002 /* fime: howto free that memory ? */
2005 sig = method->signature;
2007 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_NATIVE_TO_MANAGED);
2009 /* allocate local 0 (pointer) src_ptr */
2010 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2011 /* allocate local 1 (pointer) dst_ptr */
2012 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2013 /* allocate local 2 (boolean) delete_old */
2014 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2016 if (!MONO_TYPE_IS_VOID(sig->ret)) {
2017 /* allocate local 3 to store the return value */
2018 mono_mb_add_local (mb, sig->ret);
2021 mono_mb_emit_byte (mb, CEE_LDNULL);
2022 mono_mb_emit_byte (mb, CEE_STLOC_2);
2024 /* we copy the signature, so that we can modify it */
2025 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
2026 csig = g_memdup (sig, sigsize);
2030 #ifdef PLATFORM_WIN32
2032 * Under windows, delegates passed to native code must use the STDCALL
2033 * calling convention.
2035 csig->call_convention = MONO_CALL_STDCALL;
2038 /* fixme: howto handle this ? */
2042 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2043 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
2044 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, this));
2049 g_assert_not_reached ();
2054 /* we first do all conversions */
2055 tmp_locals = alloca (sizeof (int) * sig->param_count);
2056 for (i = 0; i < sig->param_count; i ++) {
2057 MonoType *t = sig->params [i];
2058 MonoMarshalSpec *spec = mspecs [i + 1];
2062 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
2065 MonoMethod *marshal_native_to_managed;
2066 MonoMethod *get_instance;
2068 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
2069 g_assert (mtype != NULL);
2070 mklass = mono_class_from_mono_type (mtype);
2071 g_assert (mklass != NULL);
2073 marshal_native_to_managed = mono_find_method_by_name (mklass, "MarshalNativeToManaged", 1);
2074 g_assert (marshal_native_to_managed);
2075 get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
2076 g_assert (get_instance);
2079 case MONO_TYPE_CLASS:
2080 case MONO_TYPE_OBJECT:
2081 case MONO_TYPE_STRING:
2082 case MONO_TYPE_ARRAY:
2083 case MONO_TYPE_SZARRAY:
2087 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2089 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
2091 mono_mb_emit_byte (mb, CEE_CALL);
2092 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
2094 mono_mb_emit_ldarg (mb, i);
2096 mono_mb_emit_byte (mb, CEE_CALLVIRT);
2097 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_native_to_managed));
2099 mono_mb_emit_stloc (mb, tmp_locals [i]);
2102 g_warning ("custom marshalling of type %x is currently not supported", t->type);
2103 g_assert_not_reached ();
2110 case MONO_TYPE_CLASS: {
2111 klass = t->data.klass;
2113 /* FIXME: Raise a MarshalDirectiveException here */
2114 g_assert ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT);
2116 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2118 if (t->attrs & PARAM_ATTRIBUTE_OUT) {
2119 mono_mb_emit_byte (mb, CEE_LDNULL);
2120 mono_mb_emit_stloc (mb, tmp_locals [i]);
2125 mono_mb_emit_ldarg (mb, i);
2129 /* Check for NULL and raise an exception */
2130 mono_mb_emit_byte (mb, CEE_BRTRUE);
2132 mono_mb_emit_i4 (mb, 0);
2134 mono_mb_emit_exception (mb, "ArgumentNullException");
2136 mono_mb_patch_addr (mb, pos2, mb->pos - (pos2 + 4));
2137 mono_mb_emit_ldarg (mb, i);
2138 mono_mb_emit_byte (mb, CEE_LDIND_I);
2141 mono_mb_emit_byte (mb, CEE_STLOC_0);
2143 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
2144 mono_mb_emit_stloc (mb, tmp_locals [i]);
2146 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2147 mono_mb_emit_byte (mb, CEE_BRFALSE);
2149 mono_mb_emit_i4 (mb, 0);
2151 /* Create and set dst */
2152 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2153 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
2154 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2155 mono_mb_emit_stloc (mb, tmp_locals [i]);
2156 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2157 mono_mb_emit_icon (mb, sizeof (MonoObject));
2158 mono_mb_emit_byte (mb, CEE_ADD);
2159 mono_mb_emit_byte (mb, CEE_STLOC_1);
2161 /* emit valuetype conversion code */
2162 emit_struct_conv (mb, klass, TRUE);
2164 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2167 case MONO_TYPE_VALUETYPE:
2169 klass = sig->params [i]->data.klass;
2170 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2171 klass->blittable || klass->enumtype)
2174 tmp_locals [i] = mono_mb_add_local (mb, &klass->byval_arg);
2177 mono_mb_emit_ldarg (mb, i);
2179 mono_mb_emit_ldarg_addr (mb, i);
2180 mono_mb_emit_byte (mb, CEE_STLOC_0);
2183 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2184 mono_mb_emit_byte (mb, CEE_BRFALSE);
2186 mono_mb_emit_i4 (mb, 0);
2189 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2190 mono_mb_emit_byte (mb, CEE_STLOC_1);
2192 /* emit valuetype convnversion code code */
2193 emit_struct_conv (mb, klass, TRUE);
2196 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2198 case MONO_TYPE_STRING:
2202 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2203 csig->params [i] = &mono_defaults.int_class->byval_arg;
2205 mono_mb_emit_ldarg (mb, i);
2206 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2207 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2208 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
2209 mono_mb_emit_stloc (mb, tmp_locals [i]);
2211 case MONO_TYPE_ARRAY:
2212 case MONO_TYPE_SZARRAY:
2216 klass = mono_class_from_mono_type (t);
2218 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2219 csig->params [i] = &mono_defaults.int_class->byval_arg;
2221 g_warning ("array marshaling not implemented");
2222 g_assert_not_reached ();
2227 for (i = 0; i < sig->param_count; i++) {
2228 MonoType *t = sig->params [i];
2231 case MONO_TYPE_BOOLEAN:
2245 mono_mb_emit_ldarg (mb, i);
2247 case MONO_TYPE_STRING:
2249 mono_mb_emit_ldarg (mb, i);
2251 g_assert (tmp_locals [i]);
2252 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2255 case MONO_TYPE_CLASS:
2257 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2259 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2261 case MONO_TYPE_ARRAY:
2262 case MONO_TYPE_SZARRAY:
2263 case MONO_TYPE_OBJECT:
2265 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2267 mono_mb_emit_ldarg (mb, i);
2269 case MONO_TYPE_VALUETYPE:
2270 klass = sig->params [i]->data.klass;
2271 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2272 klass->blittable || klass->enumtype) {
2273 mono_mb_emit_ldarg (mb, i);
2277 g_assert (tmp_locals [i]);
2279 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2281 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2284 g_warning ("type 0x%02x unknown", t->type);
2285 g_assert_not_reached ();
2289 mono_mb_emit_managed_call (mb, method, NULL);
2291 if (!sig->ret->byref) {
2292 switch (sig->ret->type) {
2293 case MONO_TYPE_VOID:
2295 case MONO_TYPE_BOOLEAN:
2309 case MONO_TYPE_OBJECT:
2310 mono_mb_emit_byte (mb, CEE_STLOC_3);
2312 case MONO_TYPE_STRING:
2313 csig->ret = &mono_defaults.int_class->byval_arg;
2315 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2316 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2317 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
2318 mono_mb_emit_byte (mb, CEE_STLOC_3);
2320 case MONO_TYPE_VALUETYPE:
2321 klass = sig->ret->data.klass;
2322 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2323 klass->blittable || klass->enumtype)
2326 /* load pointer to returned value type */
2327 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2328 mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
2330 /* store the address of the source into local variable 0 */
2331 mono_mb_emit_byte (mb, CEE_STLOC_0);
2332 /* allocate space for the native struct and
2333 * store the address into dst_ptr */
2334 retobj_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2335 g_assert (retobj_var);
2336 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2337 mono_mb_emit_native_call (mb, alloc_sig, mono_marshal_alloc);
2338 mono_mb_emit_byte (mb, CEE_STLOC_1);
2339 mono_mb_emit_byte (mb, CEE_LDLOC_1);
2340 mono_mb_emit_stloc (mb, retobj_var);
2342 /* emit valuetype conversion code */
2343 emit_struct_conv (mb, klass, FALSE);
2345 case MONO_TYPE_CLASS: {
2348 klass = sig->ret->data.klass;
2350 /* FIXME: Raise a MarshalDirectiveException here */
2351 g_assert ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT);
2353 mono_mb_emit_byte (mb, CEE_STLOC_0);
2354 /* Check for null */
2355 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2356 pos = mono_mb_emit_branch (mb, CEE_BRTRUE);
2357 mono_mb_emit_byte (mb, CEE_LDNULL);
2358 mono_mb_emit_byte (mb, CEE_STLOC_3);
2359 pos2 = mono_mb_emit_branch (mb, CEE_BR);
2361 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2364 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2365 mono_mb_emit_icon (mb, sizeof (MonoObject));
2366 mono_mb_emit_byte (mb, CEE_ADD);
2367 mono_mb_emit_byte (mb, CEE_STLOC_0);
2369 /* Allocate and set dest */
2370 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2371 mono_mb_emit_native_call (mb, alloc_sig, mono_marshal_alloc);
2372 mono_mb_emit_byte (mb, CEE_DUP);
2373 mono_mb_emit_byte (mb, CEE_STLOC_1);
2374 mono_mb_emit_byte (mb, CEE_STLOC_3);
2376 emit_struct_conv (mb, klass, FALSE);
2378 mono_mb_patch_addr (mb, pos2, mb->pos - (pos2 + 4));
2382 g_warning ("return type 0x%02x unknown", sig->ret->type);
2383 g_assert_not_reached ();
2386 mono_mb_emit_byte (mb, CEE_STLOC_3);
2389 /* Convert byref arguments back */
2390 for (i = 0; i < sig->param_count; i ++) {
2391 MonoType *t = sig->params [i];
2397 case MONO_TYPE_CLASS: {
2400 klass = t->data.klass;
2402 /* Check for null */
2403 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2404 pos = mono_mb_emit_branch (mb, CEE_BRTRUE);
2405 mono_mb_emit_ldarg (mb, i);
2406 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
2407 mono_mb_emit_byte (mb, CEE_STIND_I);
2408 pos2 = mono_mb_emit_branch (mb, CEE_BR);
2410 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2413 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2414 mono_mb_emit_icon (mb, sizeof (MonoObject));
2415 mono_mb_emit_byte (mb, CEE_ADD);
2416 mono_mb_emit_byte (mb, CEE_STLOC_0);
2418 /* Allocate and set dest */
2419 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2420 mono_mb_emit_native_call (mb, alloc_sig, mono_marshal_alloc);
2421 mono_mb_emit_byte (mb, CEE_STLOC_1);
2423 /* Update argument pointer */
2424 mono_mb_emit_ldarg (mb, i);
2425 mono_mb_emit_byte (mb, CEE_LDLOC_1);
2426 mono_mb_emit_byte (mb, CEE_STIND_I);
2428 /* emit valuetype conversion code */
2429 emit_struct_conv (mb, klass, FALSE);
2431 mono_mb_patch_addr (mb, pos2, mb->pos - (pos2 + 4));
2438 mono_mb_emit_ldloc (mb, retobj_var);
2439 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2440 mono_mb_emit_byte (mb, CEE_MONO_RETOBJ);
2441 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2444 if (!MONO_TYPE_IS_VOID(sig->ret))
2445 mono_mb_emit_byte (mb, CEE_LDLOC_3);
2446 mono_mb_emit_byte (mb, CEE_RET);
2450 res = mono_mb_create_and_cache (cache, method,
2451 mb, csig, sig->param_count + 16);
2453 res = mono_mb_create_method (mb, csig, sig->param_count + 16);
2456 //printf ("CODE FOR %s: \n%s.\n", mono_method_full_name (res, TRUE), mono_disasm_code (0, res, ((MonoMethodNormal*)res)->header->code, ((MonoMethodNormal*)res)->header->code + ((MonoMethodNormal*)res)->header->code_size));
2462 * mono_marshal_get_ldfld_wrapper:
2463 * @type: the type of the field
2465 * This method generates a function which can be use to load a field with type
2466 * @type from an object. The generated function has the following signature:
2467 * <@type> ldfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset)
2470 mono_marshal_get_ldfld_wrapper (MonoType *type)
2472 MonoMethodSignature *sig, *csig;
2473 MonoMethodBuilder *mb;
2476 static GHashTable *ldfld_hash = NULL;
2483 if (type->type == MONO_TYPE_SZARRAY) {
2484 klass = mono_defaults.array_class;
2485 } else if (type->type == MONO_TYPE_VALUETYPE) {
2486 klass = type->data.klass;
2487 if (klass->enumtype) {
2488 t = klass->enum_basetype->type;
2489 klass = mono_class_from_mono_type (klass->enum_basetype);
2491 } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
2492 t == MONO_TYPE_CLASS) {
2493 klass = mono_defaults.object_class;
2494 } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
2495 klass = mono_defaults.int_class;
2497 klass = mono_class_from_mono_type (type);
2500 klass = mono_defaults.int_class;
2503 EnterCriticalSection (&marshal_mutex);
2505 ldfld_hash = g_hash_table_new (NULL, NULL);
2506 res = g_hash_table_lookup (ldfld_hash, klass);
2507 LeaveCriticalSection (&marshal_mutex);
2511 name = g_strdup_printf ("__ldfld_wrapper_%s.%s", klass->name_space, klass->name);
2512 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_LDFLD);
2515 mb->method->save_lmf = 1;
2517 sig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
2518 sig->params [0] = &mono_defaults.object_class->byval_arg;
2519 sig->params [1] = &mono_defaults.int_class->byval_arg;
2520 sig->params [2] = &mono_defaults.int_class->byval_arg;
2521 sig->params [3] = &mono_defaults.int_class->byval_arg;
2522 sig->ret = &klass->byval_arg;
2524 mono_mb_emit_ldarg (mb, 0);
2525 pos0 = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
2527 mono_mb_emit_ldarg (mb, 0);
2528 mono_mb_emit_ldarg (mb, 1);
2529 mono_mb_emit_ldarg (mb, 2);
2531 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
2532 csig->params [0] = &mono_defaults.object_class->byval_arg;
2533 csig->params [1] = &mono_defaults.int_class->byval_arg;
2534 csig->params [2] = &mono_defaults.int_class->byval_arg;
2535 csig->ret = &klass->this_arg;
2538 mono_mb_emit_native_call (mb, csig, mono_load_remote_field_new);
2540 if (klass->valuetype) {
2541 mono_mb_emit_byte (mb, CEE_UNBOX);
2542 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2543 mono_mb_emit_byte (mb, CEE_BR);
2545 mono_mb_emit_i4 (mb, 0);
2547 mono_mb_emit_byte (mb, CEE_RET);
2551 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
2553 mono_mb_emit_ldarg (mb, 0);
2554 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2555 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2556 mono_mb_emit_ldarg (mb, 3);
2557 mono_mb_emit_byte (mb, CEE_ADD);
2559 if (klass->valuetype)
2560 mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
2565 case MONO_TYPE_BOOLEAN:
2566 mono_mb_emit_byte (mb, CEE_LDIND_I1);
2568 case MONO_TYPE_CHAR:
2571 mono_mb_emit_byte (mb, CEE_LDIND_I2);
2575 mono_mb_emit_byte (mb, CEE_LDIND_I4);
2579 mono_mb_emit_byte (mb, CEE_LDIND_I8);
2582 mono_mb_emit_byte (mb, CEE_LDIND_R4);
2585 mono_mb_emit_byte (mb, CEE_LDIND_R8);
2587 case MONO_TYPE_ARRAY:
2589 case MONO_TYPE_FNPTR:
2590 case MONO_TYPE_SZARRAY:
2591 case MONO_TYPE_OBJECT:
2592 case MONO_TYPE_CLASS:
2593 case MONO_TYPE_STRING:
2596 mono_mb_emit_byte (mb, CEE_LDIND_I);
2598 case MONO_TYPE_VALUETYPE:
2599 g_assert (!klass->enumtype);
2600 mono_mb_emit_byte (mb, CEE_LDOBJ);
2601 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2604 g_warning ("type %x not implemented", type->type);
2605 g_assert_not_reached ();
2608 mono_mb_emit_byte (mb, CEE_RET);
2610 res = mono_mb_create_and_cache (ldfld_hash, klass,
2611 mb, sig, sig->param_count + 16);
2618 * mono_marshal_get_stfld_wrapper:
2619 * @type: the type of the field
2621 * This method generates a function which can be use to store a field with type
2622 * @type. The generated function has the following signature:
2623 * void stfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset, <@type> val)
2626 mono_marshal_get_stfld_wrapper (MonoType *type)
2628 MonoMethodSignature *sig, *csig;
2629 MonoMethodBuilder *mb;
2632 static GHashTable *stfld_hash = NULL;
2639 if (type->type == MONO_TYPE_SZARRAY) {
2640 klass = mono_defaults.array_class;
2641 } else if (type->type == MONO_TYPE_VALUETYPE) {
2642 klass = type->data.klass;
2643 if (klass->enumtype) {
2644 t = klass->enum_basetype->type;
2645 klass = mono_class_from_mono_type (klass->enum_basetype);
2647 } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
2648 t == MONO_TYPE_CLASS) {
2649 klass = mono_defaults.object_class;
2650 } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
2651 klass = mono_defaults.int_class;
2653 klass = mono_class_from_mono_type (type);
2656 klass = mono_defaults.int_class;
2659 EnterCriticalSection (&marshal_mutex);
2661 stfld_hash = g_hash_table_new (NULL, NULL);
2662 res = g_hash_table_lookup (stfld_hash, klass);
2663 LeaveCriticalSection (&marshal_mutex);
2667 name = g_strdup_printf ("__stfld_wrapper_%s.%s", klass->name_space, klass->name);
2668 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_STFLD);
2671 mb->method->save_lmf = 1;
2673 sig = mono_metadata_signature_alloc (mono_defaults.corlib, 5);
2674 sig->params [0] = &mono_defaults.object_class->byval_arg;
2675 sig->params [1] = &mono_defaults.int_class->byval_arg;
2676 sig->params [2] = &mono_defaults.int_class->byval_arg;
2677 sig->params [3] = &mono_defaults.int_class->byval_arg;
2678 sig->params [4] = &klass->byval_arg;
2679 sig->ret = &mono_defaults.void_class->byval_arg;
2681 mono_mb_emit_ldarg (mb, 0);
2682 pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
2684 mono_mb_emit_ldarg (mb, 0);
2685 mono_mb_emit_ldarg (mb, 1);
2686 mono_mb_emit_ldarg (mb, 2);
2687 mono_mb_emit_ldarg (mb, 4);
2689 if (klass->valuetype) {
2690 mono_mb_emit_byte (mb, CEE_BOX);
2691 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2694 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
2695 csig->params [0] = &mono_defaults.object_class->byval_arg;
2696 csig->params [1] = &mono_defaults.int_class->byval_arg;
2697 csig->params [2] = &mono_defaults.int_class->byval_arg;
2698 csig->params [3] = &klass->this_arg;
2699 csig->ret = &mono_defaults.void_class->byval_arg;
2702 mono_mb_emit_native_call (mb, csig, mono_store_remote_field_new);
2704 mono_mb_emit_byte (mb, CEE_RET);
2706 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2708 mono_mb_emit_ldarg (mb, 0);
2709 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2710 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2711 mono_mb_emit_ldarg (mb, 3);
2712 mono_mb_emit_byte (mb, CEE_ADD);
2713 mono_mb_emit_ldarg (mb, 4);
2718 case MONO_TYPE_BOOLEAN:
2719 mono_mb_emit_byte (mb, CEE_STIND_I1);
2721 case MONO_TYPE_CHAR:
2724 mono_mb_emit_byte (mb, CEE_STIND_I2);
2728 mono_mb_emit_byte (mb, CEE_STIND_I4);
2732 mono_mb_emit_byte (mb, CEE_STIND_I8);
2735 mono_mb_emit_byte (mb, CEE_STIND_R4);
2738 mono_mb_emit_byte (mb, CEE_STIND_R8);
2740 case MONO_TYPE_ARRAY:
2742 case MONO_TYPE_FNPTR:
2743 case MONO_TYPE_SZARRAY:
2744 case MONO_TYPE_OBJECT:
2745 case MONO_TYPE_CLASS:
2746 case MONO_TYPE_STRING:
2749 mono_mb_emit_byte (mb, CEE_STIND_I);
2751 case MONO_TYPE_VALUETYPE:
2752 g_assert (!klass->enumtype);
2753 mono_mb_emit_byte (mb, CEE_STOBJ);
2754 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2757 g_warning ("type %x not implemented", type->type);
2758 g_assert_not_reached ();
2761 mono_mb_emit_byte (mb, CEE_RET);
2763 res = mono_mb_create_and_cache (stfld_hash, klass,
2764 mb, sig, sig->param_count + 16);
2771 * generates IL code for the icall wrapper (the generated method
2772 * calls the unmanaged code in func)
2775 mono_marshal_get_icall_wrapper (MonoMethodSignature *sig, const char *name, gconstpointer func)
2777 MonoMethodSignature *csig;
2778 MonoMethodBuilder *mb;
2782 g_assert (sig->pinvoke);
2784 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_MANAGED_TO_NATIVE);
2786 mb->method->save_lmf = 1;
2788 /* we copy the signature, so that we can modify it */
2789 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
2792 mono_mb_emit_byte (mb, CEE_LDARG_0);
2794 for (i = 0; i < sig->param_count; i++)
2795 mono_mb_emit_ldarg (mb, i + sig->hasthis);
2797 mono_mb_emit_native_call (mb, sig, (gpointer) func);
2799 mono_mb_emit_byte (mb, CEE_RET);
2801 csig = g_memdup (sig, sigsize);
2804 res = mono_mb_create_method (mb, csig, csig->param_count + 16);
2811 * generates IL code for the pinvoke wrapper (the generated method
2812 * calls the unmanaged code in method->addr)
2815 mono_marshal_get_native_wrapper (MonoMethod *method)
2817 MonoMethodSignature *sig, *csig;
2818 MonoMethodPInvoke *piinfo;
2819 MonoMethodBuilder *mb;
2820 MonoMarshalSpec **mspecs;
2824 gboolean pinvoke = FALSE;
2825 int i, pos, argnum, *tmp_locals;
2828 g_assert (method != NULL);
2829 g_assert (method->signature->pinvoke);
2831 cache = method->klass->image->native_wrapper_cache;
2832 if ((res = mono_marshal_find_in_cache (cache, method)))
2835 sig = method->signature;
2836 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
2838 if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
2839 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2842 if (!method->addr) {
2844 mono_lookup_pinvoke_call (method);
2846 method->addr = mono_lookup_internal_call (method);
2849 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_MANAGED_TO_NATIVE);
2851 mb->method->save_lmf = 1;
2853 piinfo = (MonoMethodPInvoke *)method;
2855 if (!method->addr) {
2856 mono_mb_emit_exception (mb, "MissingMethodException");
2857 csig = g_memdup (sig, sigsize);
2859 res = mono_mb_create_and_cache (cache, method,
2860 mb, csig, csig->param_count + 16);
2865 /* internal calls: we simply push all arguments and call the method (no conversions) */
2866 if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
2868 /* hack - string constructors returns a value */
2869 if (method->string_ctor) {
2870 csig = g_memdup (sig, sigsize);
2871 csig->ret = &mono_defaults.string_class->byval_arg;
2876 mono_mb_emit_byte (mb, CEE_LDARG_0);
2878 for (i = 0; i < sig->param_count; i++)
2879 mono_mb_emit_ldarg (mb, i + sig->hasthis);
2881 g_assert (method->addr);
2882 mono_mb_emit_native_call (mb, csig, method->addr);
2884 mono_mb_emit_byte (mb, CEE_RET);
2886 csig = g_memdup (csig, sigsize);
2888 res = mono_mb_create_and_cache (cache, method,
2889 mb, csig, csig->param_count + 16);
2896 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
2897 mono_method_get_marshal_info (method, mspecs);
2899 /* pinvoke: we need to convert the arguments if necessary */
2901 /* we copy the signature, so that we can set pinvoke to 0 */
2902 csig = g_memdup (sig, sigsize);
2905 /* we allocate local for use with emit_struct_conv() */
2906 /* allocate local 0 (pointer) src_ptr */
2907 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2908 /* allocate local 1 (pointer) dst_ptr */
2909 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2910 /* allocate local 2 (boolean) delete_old */
2911 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2913 /* delete_old = FALSE */
2914 mono_mb_emit_icon (mb, 0);
2915 mono_mb_emit_byte (mb, CEE_STLOC_2);
2917 if (!MONO_TYPE_IS_VOID(sig->ret)) {
2918 /* allocate local 3 to store the return value */
2919 mono_mb_add_local (mb, sig->ret);
2922 /* we first do all conversions */
2923 tmp_locals = alloca (sizeof (int) * sig->param_count);
2925 for (i = 0; i < sig->param_count; i ++) {
2926 MonoType *t = sig->params [i];
2927 MonoMarshalSpec *spec = mspecs [i + 1];
2929 argnum = i + sig->hasthis;
2932 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
2935 MonoMethod *marshal_managed_to_native;
2936 MonoMethod *get_instance;
2938 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
2939 g_assert (mtype != NULL);
2940 mklass = mono_class_from_mono_type (mtype);
2941 g_assert (mklass != NULL);
2943 marshal_managed_to_native = mono_find_method_by_name (mklass, "MarshalManagedToNative", 1);
2944 g_assert (marshal_managed_to_native);
2945 get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
2946 g_assert (get_instance);
2949 case MONO_TYPE_CLASS:
2950 case MONO_TYPE_OBJECT:
2951 case MONO_TYPE_STRING:
2952 case MONO_TYPE_ARRAY:
2953 case MONO_TYPE_SZARRAY:
2957 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2959 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
2961 mono_mb_emit_byte (mb, CEE_CALL);
2962 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
2964 mono_mb_emit_ldarg (mb, argnum);
2966 mono_mb_emit_byte (mb, CEE_CALLVIRT);
2967 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_managed_to_native));
2969 mono_mb_emit_stloc (mb, tmp_locals [i]);
2972 g_warning ("custom marshalling of type %x is currently not supported", t->type);
2973 g_assert_not_reached ();
2981 case MONO_TYPE_VALUETYPE:
2982 klass = t->data.klass;
2984 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2985 klass->blittable || klass->enumtype)
2988 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2990 /* store the address of the source into local variable 0 */
2992 mono_mb_emit_ldarg (mb, argnum);
2994 mono_mb_emit_ldarg_addr (mb, argnum);
2996 mono_mb_emit_byte (mb, CEE_STLOC_0);
2998 /* allocate space for the native struct and
2999 * store the address into local variable 1 (dest) */
3000 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
3001 mono_mb_emit_byte (mb, CEE_PREFIX1);
3002 mono_mb_emit_byte (mb, CEE_LOCALLOC);
3003 mono_mb_emit_stloc (mb, tmp_locals [i]);
3006 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3007 mono_mb_emit_byte (mb, CEE_BRFALSE);
3009 mono_mb_emit_i4 (mb, 0);
3013 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3014 mono_mb_emit_byte (mb, CEE_STLOC_1);
3016 /* emit valuetype conversion code */
3017 emit_struct_conv (mb, klass, FALSE);
3020 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3022 case MONO_TYPE_STRING:
3023 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3024 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3027 if (t->attrs & PARAM_ATTRIBUTE_OUT)
3030 mono_mb_emit_ldarg (mb, argnum);
3031 mono_mb_emit_byte (mb, CEE_LDIND_I);
3033 mono_mb_emit_ldarg (mb, argnum);
3036 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3037 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3040 switch (spec->native) {
3041 case MONO_NATIVE_LPWSTR:
3042 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPWSTR);
3044 case MONO_NATIVE_LPSTR:
3045 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
3048 g_warning ("marshalling conversion %d not implemented", spec->native);
3049 g_assert_not_reached ();
3052 switch (piinfo->piflags & PINVOKE_ATTRIBUTE_CHAR_SET_MASK) {
3053 case PINVOKE_ATTRIBUTE_CHAR_SET_ANSI:
3054 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
3056 case PINVOKE_ATTRIBUTE_CHAR_SET_UNICODE:
3057 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPWSTR);
3059 case PINVOKE_ATTRIBUTE_CHAR_SET_AUTO:
3060 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPTSTR);
3063 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
3068 mono_mb_emit_stloc (mb, tmp_locals [i]);
3070 case MONO_TYPE_CLASS:
3071 case MONO_TYPE_OBJECT:
3072 klass = t->data.klass;
3074 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3075 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3077 if (klass->delegate) {
3078 g_assert (!t->byref);
3079 mono_mb_emit_ldarg (mb, argnum);
3080 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3081 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3082 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_DEL_FTN);
3083 mono_mb_emit_stloc (mb, tmp_locals [i]);
3084 } else if (klass == mono_defaults.stringbuilder_class) {
3085 g_assert (!t->byref);
3086 mono_mb_emit_ldarg (mb, argnum);
3087 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3088 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3089 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_SB_LPSTR);
3090 mono_mb_emit_stloc (mb, tmp_locals [i]);
3092 mono_mb_emit_byte (mb, CEE_LDNULL);
3093 mono_mb_emit_stloc (mb, tmp_locals [i]);
3096 /* we dont need any conversions for out parameters */
3097 if (t->attrs & PARAM_ATTRIBUTE_OUT)
3100 mono_mb_emit_ldarg (mb, argnum);
3101 mono_mb_emit_byte (mb, CEE_LDIND_I);
3104 mono_mb_emit_ldarg (mb, argnum);
3105 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3106 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
3109 /* store the address of the source into local variable 0 */
3110 mono_mb_emit_byte (mb, CEE_STLOC_0);
3111 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3112 mono_mb_emit_byte (mb, CEE_BRFALSE);
3114 mono_mb_emit_i4 (mb, 0);
3116 /* allocate space for the native struct and store the address */
3117 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
3118 mono_mb_emit_byte (mb, CEE_PREFIX1);
3119 mono_mb_emit_byte (mb, CEE_LOCALLOC);
3120 mono_mb_emit_stloc (mb, tmp_locals [i]);
3122 /* set the src_ptr */
3123 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3124 mono_mb_emit_icon (mb, sizeof (MonoObject));
3125 mono_mb_emit_byte (mb, CEE_ADD);
3126 mono_mb_emit_byte (mb, CEE_STLOC_0);
3129 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3130 mono_mb_emit_byte (mb, CEE_STLOC_1);
3132 /* emit valuetype conversion code */
3133 emit_struct_conv (mb, klass, FALSE);
3135 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3139 case MONO_TYPE_ARRAY:
3140 case MONO_TYPE_SZARRAY:
3144 klass = mono_class_from_mono_type (t);
3146 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3147 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3149 if (klass->element_class == mono_defaults.string_class) {
3150 mono_mb_emit_ldarg (mb, argnum);
3151 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3152 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3154 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STRARRAY_STRLPARRAY);
3155 mono_mb_emit_stloc (mb, tmp_locals [i]);
3157 else if (klass->element_class->blittable) {
3158 mono_mb_emit_ldarg (mb, argnum);
3159 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3160 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3162 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_ARRAY_LPARRAY);
3163 mono_mb_emit_stloc (mb, tmp_locals [i]);
3167 guint32 label1, label2, label3;
3168 int index_var, dest_ptr;
3170 dest_ptr = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3173 mono_mb_emit_ldarg (mb, argnum);
3174 mono_mb_emit_stloc (mb, tmp_locals [i]);
3175 mono_mb_emit_ldarg (mb, argnum);
3176 mono_mb_emit_byte (mb, CEE_BRFALSE);
3178 mono_mb_emit_i4 (mb, 0);
3180 /* allocate space for the native struct and store the address */
3181 eklass = klass->element_class;
3182 mono_mb_emit_icon (mb, mono_class_native_size (eklass, NULL));
3183 mono_mb_emit_ldarg (mb, argnum);
3184 mono_mb_emit_byte (mb, CEE_LDLEN);
3185 mono_mb_emit_byte (mb, CEE_MUL);
3186 mono_mb_emit_byte (mb, CEE_PREFIX1);
3187 mono_mb_emit_byte (mb, CEE_LOCALLOC);
3188 mono_mb_emit_stloc (mb, tmp_locals [i]);
3190 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3191 mono_mb_emit_stloc (mb, dest_ptr);
3193 /* Emit marshalling loop */
3194 index_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3195 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
3196 mono_mb_emit_stloc (mb, index_var);
3198 mono_mb_emit_ldloc (mb, index_var);
3199 mono_mb_emit_ldarg (mb, argnum);
3200 mono_mb_emit_byte (mb, CEE_LDLEN);
3201 mono_mb_emit_byte (mb, CEE_BGE);
3203 mono_mb_emit_i4 (mb, 0);
3205 /* Emit marshalling code */
3207 /* set the src_ptr */
3208 mono_mb_emit_ldarg (mb, argnum);
3209 mono_mb_emit_ldloc (mb, index_var);
3210 mono_mb_emit_byte (mb, CEE_LDELEMA);
3211 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eklass));
3212 mono_mb_emit_byte (mb, CEE_STLOC_0);
3215 mono_mb_emit_ldloc (mb, dest_ptr);
3216 mono_mb_emit_byte (mb, CEE_STLOC_1);
3218 /* emit valuetype conversion code */
3219 emit_struct_conv (mb, eklass, FALSE);
3221 mono_mb_emit_add_to_local (mb, index_var, 1);
3222 mono_mb_emit_add_to_local (mb, dest_ptr, mono_class_native_size (eklass, NULL));
3224 mono_mb_emit_byte (mb, CEE_BR);
3225 mono_mb_emit_i4 (mb, label2 - (mb->pos + 4));
3227 mono_mb_patch_addr (mb, label1, mb->pos - (label1 + 4));
3228 mono_mb_patch_addr (mb, label3, mb->pos - (label3 + 4));
3232 case MONO_TYPE_BOOLEAN: {
3233 MonoType *local_type;
3234 int variant_bool = 0;
3238 local_type = &mono_defaults.int32_class->byval_arg;
3240 switch (spec->native) {
3241 case MONO_NATIVE_I1:
3242 local_type = &mono_defaults.byte_class->byval_arg;
3244 case MONO_NATIVE_VARIANTBOOL:
3245 local_type = &mono_defaults.int16_class->byval_arg;
3249 g_warning ("marshalling bool as native type %x is currently not supported", spec->native);
3253 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3254 tmp_locals [i] = mono_mb_add_local (mb, local_type);
3255 mono_mb_emit_ldarg (mb, argnum);
3256 mono_mb_emit_byte (mb, CEE_LDIND_I1);
3258 mono_mb_emit_byte (mb, CEE_NEG);
3259 mono_mb_emit_stloc (mb, tmp_locals [i]);
3265 /* push all arguments */
3268 mono_mb_emit_byte (mb, CEE_LDARG_0);
3270 for (i = 0; i < sig->param_count; i++) {
3271 MonoType *t = sig->params [i];
3273 argnum = i + sig->hasthis;
3276 case MONO_TYPE_BOOLEAN:
3278 g_assert (tmp_locals [i]);
3279 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
3281 mono_mb_emit_ldarg (mb, argnum);
3296 mono_mb_emit_ldarg (mb, argnum);
3298 case MONO_TYPE_VALUETYPE:
3299 klass = sig->params [i]->data.klass;
3300 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3301 klass->blittable || klass->enumtype) {
3302 mono_mb_emit_ldarg (mb, argnum);
3305 g_assert (tmp_locals [i]);
3306 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3308 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3309 mono_mb_emit_byte (mb, CEE_MONO_LDNATIVEOBJ);
3310 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3313 case MONO_TYPE_STRING:
3314 case MONO_TYPE_CLASS:
3315 case MONO_TYPE_OBJECT:
3316 g_assert (tmp_locals [i]);
3318 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
3320 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3322 case MONO_TYPE_CHAR:
3323 /* fixme: dont know how to marshal that. We cant simply
3324 * convert it to a one byte UTF8 character, because an
3325 * unicode character may need more that one byte in UTF8 */
3326 mono_mb_emit_ldarg (mb, argnum);
3328 case MONO_TYPE_ARRAY:
3329 case MONO_TYPE_SZARRAY:
3331 mono_mb_emit_ldarg (mb, argnum);
3333 g_assert (tmp_locals [i]);
3334 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3337 case MONO_TYPE_TYPEDBYREF:
3338 case MONO_TYPE_FNPTR:
3340 g_warning ("type 0x%02x unknown", t->type);
3341 g_assert_not_reached ();
3345 /* call the native method */
3346 mono_mb_emit_native_call (mb, csig, method->addr);
3348 /* Set LastError if needed */
3349 if (piinfo->piflags & PINVOKE_ATTRIBUTE_SUPPORTS_LAST_ERROR) {
3350 MonoMethodSignature *lasterr_sig;
3352 lasterr_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
3353 lasterr_sig->ret = &mono_defaults.void_class->byval_arg;
3354 lasterr_sig->pinvoke = 1;
3356 mono_mb_emit_native_call (mb, lasterr_sig, mono_marshal_set_last_error);
3359 /* convert the result */
3360 if (!sig->ret->byref) {
3361 MonoMarshalSpec *spec = mspecs [0];
3362 type = sig->ret->type;
3364 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
3367 MonoMethod *marshal_native_to_managed;
3368 MonoMethod *get_instance;
3370 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
3371 g_assert (mtype != NULL);
3372 mklass = mono_class_from_mono_type (mtype);
3373 g_assert (mklass != NULL);
3375 marshal_native_to_managed = mono_find_method_by_name (mklass, "MarshalNativeToManaged", 1);
3376 g_assert (marshal_native_to_managed);
3377 get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
3378 g_assert (get_instance);
3381 case MONO_TYPE_CLASS:
3382 case MONO_TYPE_OBJECT:
3383 case MONO_TYPE_STRING:
3384 case MONO_TYPE_ARRAY:
3385 case MONO_TYPE_SZARRAY:
3386 mono_mb_emit_byte (mb, CEE_STLOC_3);
3388 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
3390 mono_mb_emit_byte (mb, CEE_CALL);
3391 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
3393 mono_mb_emit_byte (mb, CEE_LDLOC_3);
3395 mono_mb_emit_byte (mb, CEE_CALLVIRT);
3396 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_native_to_managed));
3398 mono_mb_emit_byte (mb, CEE_STLOC_3);
3401 g_warning ("custom marshalling of type %x is currently not supported", type);
3402 g_assert_not_reached ();
3409 case MONO_TYPE_VOID:
3424 /* no conversions necessary */
3425 mono_mb_emit_byte (mb, CEE_STLOC_3);
3427 case MONO_TYPE_BOOLEAN:
3428 /* maybe we need to make sure that it fits within 8 bits */
3429 mono_mb_emit_byte (mb, CEE_STLOC_3);
3431 case MONO_TYPE_VALUETYPE:
3432 klass = sig->ret->data.klass;
3433 if (klass->enumtype) {
3434 type = sig->ret->data.klass->enum_basetype->type;
3438 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3440 mono_mb_emit_byte (mb, CEE_STLOC_3);
3443 /* load pointer to returned value type */
3444 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3445 mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
3446 /* store the address of the source into local variable 0 */
3447 mono_mb_emit_byte (mb, CEE_STLOC_0);
3449 mono_mb_emit_ldloc_addr (mb, 3);
3450 mono_mb_emit_byte (mb, CEE_STLOC_1);
3452 /* emit valuetype conversion code */
3453 emit_struct_conv (mb, sig->ret->data.klass, TRUE);
3455 case MONO_TYPE_STRING:
3456 #ifdef GTK_SHARP_FIXED
3457 mono_mb_emit_byte (mb, CEE_STLOC_0);
3458 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3461 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3462 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3464 switch (spec->native) {
3465 case MONO_NATIVE_LPWSTR:
3466 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPWSTR_STR);
3469 g_warning ("marshalling conversion not implemented");
3470 g_assert_not_reached ();
3473 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
3475 mono_mb_emit_byte (mb, CEE_STLOC_3);
3477 #ifdef GTK_SHARP_FIXED
3478 /* free the string */
3479 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3480 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3481 mono_mb_emit_byte (mb, CEE_MONO_FREE);
3484 case MONO_TYPE_CLASS:
3485 case MONO_TYPE_OBJECT:
3486 klass = sig->ret->data.klass;
3489 mono_mb_emit_byte (mb, CEE_STLOC_0);
3491 mono_mb_emit_byte (mb, CEE_LDNULL);
3492 mono_mb_emit_byte (mb, CEE_STLOC_3);
3495 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3496 mono_mb_emit_byte (mb, CEE_BRFALSE);
3498 mono_mb_emit_i4 (mb, 0);
3500 /* allocate result object */
3502 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3503 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
3504 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3505 mono_mb_emit_byte (mb, CEE_STLOC_3);
3509 mono_mb_emit_byte (mb, CEE_LDLOC_3);
3510 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3511 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
3512 mono_mb_emit_icon (mb, sizeof (MonoObject));
3513 mono_mb_emit_byte (mb, CEE_ADD);
3514 mono_mb_emit_byte (mb, CEE_STLOC_1);
3516 /* emit conversion code */
3517 emit_struct_conv (mb, klass, TRUE);
3519 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3521 case MONO_TYPE_ARRAY:
3522 case MONO_TYPE_SZARRAY:
3523 /* fixme: we need conversions here */
3524 mono_mb_emit_byte (mb, CEE_STLOC_3);
3526 case MONO_TYPE_CHAR:
3527 /* fixme: we need conversions here */
3528 mono_mb_emit_byte (mb, CEE_STLOC_3);
3530 case MONO_TYPE_TYPEDBYREF:
3531 case MONO_TYPE_FNPTR:
3533 g_warning ("return type 0x%02x unknown", sig->ret->type);
3534 g_assert_not_reached ();
3538 mono_mb_emit_byte (mb, CEE_STLOC_3);
3541 /* we need to convert byref arguments back and free string arrays */
3542 for (i = 0; i < sig->param_count; i++) {
3543 MonoType *t = sig->params [i];
3545 argnum = i + sig->hasthis;
3548 case MONO_TYPE_STRING:
3549 if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT)) {
3550 mono_mb_emit_ldarg (mb, argnum);
3551 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3552 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3553 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3554 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
3555 mono_mb_emit_byte (mb, CEE_STIND_I);
3557 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3558 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3559 mono_mb_emit_byte (mb, CEE_MONO_FREE);
3562 case MONO_TYPE_CLASS:
3563 case MONO_TYPE_OBJECT:
3564 if (t->data.klass == mono_defaults.stringbuilder_class) {
3565 g_assert (!t->byref);
3566 mono_mb_emit_ldarg (mb, argnum);
3567 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3568 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3569 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
3570 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_SB);
3571 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3572 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3573 mono_mb_emit_byte (mb, CEE_MONO_FREE);
3577 if (!(t->byref || (t->attrs & PARAM_ATTRIBUTE_OUT)))
3580 if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT)) {
3581 /* allocate a new object new object */
3582 mono_mb_emit_ldarg (mb, argnum);
3583 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3584 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
3585 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3586 mono_mb_emit_byte (mb, CEE_STIND_I);
3589 /* dst = *argument */
3590 mono_mb_emit_ldarg (mb, argnum);
3593 mono_mb_emit_byte (mb, CEE_LDIND_I);
3595 mono_mb_emit_byte (mb, CEE_STLOC_1);
3597 mono_mb_emit_byte (mb, CEE_LDLOC_1);
3598 mono_mb_emit_byte (mb, CEE_BRFALSE);
3600 mono_mb_emit_i4 (mb, 0);
3602 mono_mb_emit_byte (mb, CEE_LDLOC_1);
3603 mono_mb_emit_icon (mb, sizeof (MonoObject));
3604 mono_mb_emit_byte (mb, CEE_ADD);
3605 mono_mb_emit_byte (mb, CEE_STLOC_1);
3607 /* src = tmp_locals [i] */
3608 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3609 mono_mb_emit_byte (mb, CEE_STLOC_0);
3611 /* emit valuetype conversion code */
3612 emit_struct_conv (mb, klass, TRUE);
3614 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3616 case MONO_TYPE_VALUETYPE:
3620 klass = t->data.klass;
3621 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3622 klass->blittable || klass->enumtype)
3625 /* dst = argument */
3626 mono_mb_emit_ldarg (mb, argnum);
3627 mono_mb_emit_byte (mb, CEE_STLOC_1);
3629 mono_mb_emit_byte (mb, CEE_LDLOC_1);
3630 mono_mb_emit_byte (mb, CEE_BRFALSE);
3632 mono_mb_emit_i4 (mb, 0);
3634 /* src = tmp_locals [i] */
3635 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3636 mono_mb_emit_byte (mb, CEE_STLOC_0);
3638 /* emit valuetype conversion code */
3639 emit_struct_conv (mb, klass, TRUE);
3641 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3643 case MONO_TYPE_SZARRAY:
3647 klass = mono_class_from_mono_type (t);
3649 if (klass->element_class == mono_defaults.string_class) {
3650 g_assert (tmp_locals [i]);
3652 mono_mb_emit_ldarg (mb, argnum);
3653 mono_mb_emit_byte (mb, CEE_BRFALSE);
3655 mono_mb_emit_i4 (mb, 0);
3657 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3658 mono_mb_emit_ldarg (mb, argnum);
3659 mono_mb_emit_byte (mb, CEE_LDLEN);
3660 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3661 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
3662 mono_mb_emit_byte (mb, MONO_MARSHAL_FREE_ARRAY);
3664 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3667 if (t->attrs & PARAM_ATTRIBUTE_OUT) {
3668 /* FIXME: Optimize blittable case */
3670 guint32 label1, label2, label3;
3671 int index_var, src_ptr;
3673 eklass = klass->element_class;
3674 src_ptr = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3677 mono_mb_emit_ldarg (mb, argnum);
3678 mono_mb_emit_byte (mb, CEE_BRFALSE);
3680 mono_mb_emit_i4 (mb, 0);
3682 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3683 mono_mb_emit_stloc (mb, src_ptr);
3685 /* Emit marshalling loop */
3686 index_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3687 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
3688 mono_mb_emit_stloc (mb, index_var);
3690 mono_mb_emit_ldloc (mb, index_var);
3691 mono_mb_emit_ldarg (mb, argnum);
3692 mono_mb_emit_byte (mb, CEE_LDLEN);
3693 mono_mb_emit_byte (mb, CEE_BGE);
3695 mono_mb_emit_i4 (mb, 0);
3697 /* Emit marshalling code */
3699 /* set the src_ptr */
3700 mono_mb_emit_ldloc (mb, src_ptr);
3701 mono_mb_emit_byte (mb, CEE_STLOC_0);
3704 mono_mb_emit_ldarg (mb, argnum);
3705 mono_mb_emit_ldloc (mb, index_var);
3706 mono_mb_emit_byte (mb, CEE_LDELEMA);
3707 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eklass));
3708 mono_mb_emit_byte (mb, CEE_STLOC_1);
3710 /* emit valuetype conversion code */
3711 emit_struct_conv (mb, eklass, TRUE);
3713 mono_mb_emit_add_to_local (mb, index_var, 1);
3714 mono_mb_emit_add_to_local (mb, src_ptr, mono_class_native_size (eklass, NULL));
3716 mono_mb_emit_byte (mb, CEE_BR);
3717 mono_mb_emit_i4 (mb, label2 - (mb->pos + 4));
3719 mono_mb_patch_addr (mb, label1, mb->pos - (label1 + 4));
3720 mono_mb_patch_addr (mb, label3, mb->pos - (label3 + 4));
3723 case MONO_TYPE_BOOLEAN:
3726 mono_mb_emit_ldarg (mb, argnum);
3727 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3728 if (mspecs [i + 1] != NULL && mspecs [i + 1]->native == MONO_NATIVE_VARIANTBOOL)
3729 mono_mb_emit_byte (mb, CEE_NEG);
3730 mono_mb_emit_byte (mb, CEE_STIND_I1);
3734 if (!MONO_TYPE_IS_VOID(sig->ret))
3735 mono_mb_emit_byte (mb, CEE_LDLOC_3);
3737 mono_mb_emit_byte (mb, CEE_RET);
3739 csig = g_memdup (sig, sigsize);
3741 res = mono_mb_create_and_cache (cache, method,
3742 mb, csig, csig->param_count + 16);
3745 for (i = sig->param_count; i >= 0; i--)
3746 g_free (mspecs [i]);
3749 //printf ("CODE FOR %s: \n%s.\n", mono_method_full_name (res, TRUE), mono_disasm_code (0, res, ((MonoMethodNormal*)res)->header->code, ((MonoMethodNormal*)res)->header->code + ((MonoMethodNormal*)res)->header->code_size));
3755 * generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld)
3758 mono_marshal_get_struct_to_ptr (MonoClass *klass)
3760 MonoMethodBuilder *mb;
3761 static MonoMethod *stoptr = NULL;
3764 g_assert (klass != NULL);
3766 if (klass->str_to_ptr)
3767 return klass->str_to_ptr;
3770 stoptr = mono_find_method_by_name (mono_defaults.marshal_class, "StructureToPtr", 3);
3773 mb = mono_mb_new (klass, stoptr->name, MONO_WRAPPER_UNKNOWN);
3775 if (klass->blittable) {
3776 mono_mb_emit_byte (mb, CEE_LDARG_1);
3777 mono_mb_emit_byte (mb, CEE_LDARG_0);
3778 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3779 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
3780 mono_mb_emit_byte (mb, CEE_PREFIX1);
3781 mono_mb_emit_byte (mb, CEE_CPBLK);
3784 /* allocate local 0 (pointer) src_ptr */
3785 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3786 /* allocate local 1 (pointer) dst_ptr */
3787 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3788 /* allocate local 2 (boolean) delete_old */
3789 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
3790 mono_mb_emit_byte (mb, CEE_LDARG_2);
3791 mono_mb_emit_byte (mb, CEE_STLOC_2);
3793 /* initialize src_ptr to point to the start of object data */
3794 mono_mb_emit_byte (mb, CEE_LDARG_0);
3795 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3796 mono_mb_emit_byte (mb, CEE_STLOC_0);
3798 /* initialize dst_ptr */
3799 mono_mb_emit_byte (mb, CEE_LDARG_1);
3800 mono_mb_emit_byte (mb, CEE_STLOC_1);
3802 emit_struct_conv (mb, klass, FALSE);
3805 mono_mb_emit_byte (mb, CEE_RET);
3807 res = mono_mb_create_method (mb, stoptr->signature, 0);
3810 klass->str_to_ptr = res;
3815 * generates IL code for PtrToStructure (IntPtr src, object structure)
3818 mono_marshal_get_ptr_to_struct (MonoClass *klass)
3820 MonoMethodBuilder *mb;
3821 static MonoMethod *ptostr = NULL;
3824 g_assert (klass != NULL);
3826 if (klass->ptr_to_str)
3827 return klass->ptr_to_str;
3830 ptostr = mono_find_method_by_name (mono_defaults.marshal_class, "PtrToStructure", 2);
3833 mb = mono_mb_new (klass, ptostr->name, MONO_WRAPPER_UNKNOWN);
3835 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable) {
3836 mono_mb_emit_byte (mb, CEE_LDARG_1);
3837 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3838 mono_mb_emit_byte (mb, CEE_LDARG_0);
3839 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
3840 mono_mb_emit_byte (mb, CEE_PREFIX1);
3841 mono_mb_emit_byte (mb, CEE_CPBLK);
3844 /* allocate local 0 (pointer) src_ptr */
3845 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3846 /* allocate local 1 (pointer) dst_ptr */
3847 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3849 /* initialize src_ptr to point to the start of object data */
3850 mono_mb_emit_byte (mb, CEE_LDARG_0);
3851 mono_mb_emit_byte (mb, CEE_STLOC_0);
3853 /* initialize dst_ptr */
3854 mono_mb_emit_byte (mb, CEE_LDARG_1);
3855 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3856 mono_mb_emit_byte (mb, CEE_STLOC_1);
3858 emit_struct_conv (mb, klass, TRUE);
3861 mono_mb_emit_byte (mb, CEE_RET);
3863 res = mono_mb_create_method (mb, ptostr->signature, 0);
3866 klass->ptr_to_str = res;
3870 static MonoReflectionType *
3871 type_from_handle (MonoType *handle)
3873 MonoDomain *domain = mono_domain_get ();
3874 MonoClass *klass = mono_class_from_mono_type (handle);
3876 MONO_ARCH_SAVE_REGS;
3878 mono_class_init (klass);
3879 return mono_type_get_object (domain, handle);
3883 * generates IL code for the synchronized wrapper: the generated method
3884 * calls METHOD while locking 'this' or the parent type.
3887 mono_marshal_get_synchronized_wrapper (MonoMethod *method)
3889 static MonoMethodSignature *from_handle_sig = NULL;
3890 static MonoMethod *enter_method, *exit_method;
3891 MonoMethodSignature *sig;
3892 MonoExceptionClause *clause;
3893 MonoMethodHeader *header;
3894 MonoMethodBuilder *mb;
3897 int i, pos, this_local, ret_local;
3901 if (method->wrapper_type == MONO_WRAPPER_SYNCHRONIZED)
3904 cache = method->klass->image->synchronized_cache;
3905 if ((res = mono_marshal_find_in_cache (cache, method)))
3908 sig = method->signature;
3910 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_SYNCHRONIZED);
3913 if (!MONO_TYPE_IS_VOID (sig->ret))
3914 ret_local = mono_mb_add_local (mb, sig->ret);
3917 this_local = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
3919 clause = g_new0 (MonoExceptionClause, 1);
3920 clause->flags = MONO_EXCEPTION_CLAUSE_FINALLY;
3922 if (!enter_method) {
3923 MonoMethodDesc *desc;
3925 desc = mono_method_desc_new ("Monitor:Enter", FALSE);
3926 enter_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
3927 g_assert (enter_method);
3928 mono_method_desc_free (desc);
3929 desc = mono_method_desc_new ("Monitor:Exit", FALSE);
3930 exit_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
3931 g_assert (exit_method);
3932 mono_method_desc_free (desc);
3935 * GetTypeFromHandle isn't called as a managed method because it has
3936 * a funky calling sequence, e.g. ldtoken+GetTypeFromHandle gets
3937 * transformed into something else by the JIT.
3939 from_handle_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
3940 from_handle_sig->params [0] = &mono_defaults.object_class->byval_arg;
3941 from_handle_sig->ret = &mono_defaults.object_class->byval_arg;
3944 /* Push this or the type object */
3945 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3946 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3947 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
3948 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, &method->klass->byval_arg));
3949 mono_mb_emit_native_call (mb, from_handle_sig, type_from_handle);
3952 mono_mb_emit_ldarg (mb, 0);
3953 mono_mb_emit_stloc (mb, this_local);
3955 /* Call Monitor::Enter() */
3956 mono_mb_emit_ldloc (mb, this_local);
3957 mono_mb_emit_managed_call (mb, enter_method, NULL);
3959 clause->try_offset = mb->pos;
3961 /* Call the method */
3963 mono_mb_emit_ldarg (mb, 0);
3964 for (i = 0; i < sig->param_count; i++)
3965 mono_mb_emit_ldarg (mb, i + (sig->hasthis == TRUE));
3966 mono_mb_emit_managed_call (mb, method, method->signature);
3967 if (!MONO_TYPE_IS_VOID (sig->ret))
3968 mono_mb_emit_stloc (mb, ret_local);
3970 mono_mb_emit_byte (mb, CEE_LEAVE);
3972 mono_mb_emit_i4 (mb, 0);
3974 clause->try_len = mb->pos - clause->try_offset;
3975 clause->handler_offset = mb->pos;
3977 /* Call Monitor::Exit() */
3978 mono_mb_emit_ldloc (mb, this_local);
3979 // mono_mb_emit_native_call (mb, exit_sig, mono_monitor_exit);
3980 mono_mb_emit_managed_call (mb, exit_method, NULL);
3981 mono_mb_emit_byte (mb, CEE_ENDFINALLY);
3983 clause->handler_len = mb->pos - clause->handler_offset;
3985 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3986 if (!MONO_TYPE_IS_VOID (sig->ret))
3987 mono_mb_emit_ldloc (mb, ret_local);
3988 mono_mb_emit_byte (mb, CEE_RET);
3990 res = mono_mb_create_and_cache (cache, method,
3991 mb, sig, sig->param_count + 16);
3994 header = ((MonoMethodNormal *)res)->header;
3995 header->num_clauses = 1;
3996 header->clauses = clause;
4001 /* FIXME: on win32 we should probably use GlobalAlloc(). */
4003 mono_marshal_alloc (gpointer size)
4005 MONO_ARCH_SAVE_REGS;
4007 return g_try_malloc ((gulong)size);
4011 mono_marshal_free (gpointer ptr)
4013 MONO_ARCH_SAVE_REGS;
4019 mono_marshal_free_array (gpointer *ptr, int size)
4026 for (i = 0; i < size; i++)
4032 mono_marshal_realloc (gpointer ptr, gpointer size)
4034 MONO_ARCH_SAVE_REGS;
4036 return g_try_realloc (ptr, (gulong)size);
4040 mono_marshal_string_array (MonoArray *array)
4048 len = mono_array_length (array);
4050 result = g_malloc (sizeof (char *) * (len + 1));
4051 for (i = 0; i < len; ++i) {
4052 MonoString *s = (MonoString *)mono_array_get (array, gpointer, i);
4053 result [i] = s ? mono_string_to_utf8 (s): NULL;
4055 /* null terminate the array */
4062 mono_marshal_set_last_error (void)
4065 TlsSetValue (last_error_tls_id, (gpointer)GetLastError ());
4067 TlsSetValue (last_error_tls_id, (gpointer)errno);
4072 ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArray *src, gint32 start_index,
4073 gpointer dest, gint32 length)
4078 MONO_ARCH_SAVE_REGS;
4080 MONO_CHECK_ARG_NULL (src);
4081 MONO_CHECK_ARG_NULL (dest);
4083 g_assert (src->obj.vtable->klass->rank == 1);
4084 g_assert (start_index >= 0);
4085 g_assert (length >= 0);
4086 g_assert (start_index + length <= mono_array_length (src));
4088 element_size = mono_array_element_size (src->obj.vtable->klass);
4090 source_addr = mono_array_addr_with_size (src, element_size, start_index);
4092 memcpy (dest, source_addr, length * element_size);
4096 ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer src, gint32 start_index,
4097 MonoArray *dest, gint32 length)
4102 MONO_ARCH_SAVE_REGS;
4104 MONO_CHECK_ARG_NULL (src);
4105 MONO_CHECK_ARG_NULL (dest);
4107 g_assert (dest->obj.vtable->klass->rank == 1);
4108 g_assert (start_index >= 0);
4109 g_assert (length >= 0);
4110 g_assert (start_index + length <= mono_array_length (dest));
4112 element_size = mono_array_element_size (dest->obj.vtable->klass);
4114 dest_addr = mono_array_addr_with_size (dest, element_size, start_index);
4116 memcpy (dest_addr, src, length * element_size);
4120 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr, gint32 offset)
4124 MONO_ARCH_SAVE_REGS;
4126 return *(gpointer*)(p + offset);
4130 ves_icall_System_Runtime_InteropServices_Marshal_ReadByte (gpointer ptr, gint32 offset)
4134 MONO_ARCH_SAVE_REGS;
4136 return *(unsigned char*)(p + offset);
4140 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt16 (gpointer ptr, gint32 offset)
4144 MONO_ARCH_SAVE_REGS;
4146 return *(gint16*)(p + offset);
4150 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt32 (gpointer ptr, gint32 offset)
4154 MONO_ARCH_SAVE_REGS;
4156 return *(gint32*)(p + offset);
4160 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt64 (gpointer ptr, gint32 offset)
4164 MONO_ARCH_SAVE_REGS;
4166 return *(gint64*)(p + offset);
4170 ves_icall_System_Runtime_InteropServices_Marshal_WriteByte (gpointer ptr, gint32 offset, unsigned char val)
4174 MONO_ARCH_SAVE_REGS;
4176 *(unsigned char*)(p + offset) = val;
4180 ves_icall_System_Runtime_InteropServices_Marshal_WriteIntPtr (gpointer ptr, gint32 offset, gpointer val)
4184 MONO_ARCH_SAVE_REGS;
4186 *(gpointer*)(p + offset) = val;
4190 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt16 (gpointer ptr, gint32 offset, gint16 val)
4194 MONO_ARCH_SAVE_REGS;
4196 *(gint16*)(p + offset) = val;
4200 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt32 (gpointer ptr, gint32 offset, gint32 val)
4204 MONO_ARCH_SAVE_REGS;
4206 *(gint32*)(p + offset) = val;
4210 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt64 (gpointer ptr, gint32 offset, gint64 val)
4214 MONO_ARCH_SAVE_REGS;
4216 *(gint64*)(p + offset) = val;
4220 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (char *ptr)
4222 MONO_ARCH_SAVE_REGS;
4224 return mono_string_new (mono_domain_get (), ptr);
4228 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len (char *ptr, gint32 len)
4230 MONO_ARCH_SAVE_REGS;
4232 return mono_string_new_len (mono_domain_get (), ptr, len);
4236 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni (guint16 *ptr)
4238 MonoDomain *domain = mono_domain_get ();
4242 MONO_ARCH_SAVE_REGS;
4247 return mono_string_new_utf16 (domain, ptr, len);
4251 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len (guint16 *ptr, gint32 len)
4253 MonoDomain *domain = mono_domain_get ();
4255 MONO_ARCH_SAVE_REGS;
4257 return mono_string_new_utf16 (domain, ptr, len);
4261 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR (gpointer ptr)
4263 MONO_ARCH_SAVE_REGS;
4265 g_warning ("PtrToStringBSTR not implemented");
4266 g_assert_not_reached ();
4272 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
4274 MONO_ARCH_SAVE_REGS;
4276 return ((guint32)TlsGetValue (last_error_tls_id));
4280 ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype)
4284 MONO_ARCH_SAVE_REGS;
4286 MONO_CHECK_ARG_NULL (rtype);
4288 klass = mono_class_from_mono_type (rtype->type);
4290 return mono_class_native_size (klass, NULL);
4294 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old)
4299 MONO_ARCH_SAVE_REGS;
4301 MONO_CHECK_ARG_NULL (obj);
4302 MONO_CHECK_ARG_NULL (dst);
4304 method = mono_marshal_get_struct_to_ptr (obj->vtable->klass);
4308 pa [2] = &delete_old;
4310 mono_runtime_invoke (method, NULL, pa, NULL);
4314 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, MonoObject *dst)
4319 MONO_ARCH_SAVE_REGS;
4321 MONO_CHECK_ARG_NULL (src);
4322 MONO_CHECK_ARG_NULL (dst);
4324 method = mono_marshal_get_ptr_to_struct (dst->vtable->klass);
4329 mono_runtime_invoke (method, NULL, pa, NULL);
4333 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer src, MonoReflectionType *type)
4335 MonoDomain *domain = mono_domain_get ();
4338 MONO_ARCH_SAVE_REGS;
4340 MONO_CHECK_ARG_NULL (src);
4341 MONO_CHECK_ARG_NULL (type);
4343 res = mono_object_new (domain, mono_class_from_mono_type (type->type));
4345 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (src, res);
4351 ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *type, MonoString *field_name)
4353 MonoMarshalType *info;
4356 int i, match_index = -1;
4358 MONO_ARCH_SAVE_REGS;
4360 MONO_CHECK_ARG_NULL (type);
4361 MONO_CHECK_ARG_NULL (field_name);
4363 fname = mono_string_to_utf8 (field_name);
4364 klass = mono_class_from_mono_type (type->type);
4366 while(klass && match_index == -1) {
4367 for (i = 0; i < klass->field.count; ++i) {
4368 if (*fname == *klass->fields [i].name && strcmp (fname, klass->fields [i].name) == 0) {
4374 if(match_index == -1)
4375 klass = klass->parent;
4380 if(match_index == -1) {
4384 /* Get back original class instance */
4385 klass = mono_class_from_mono_type (type->type);
4387 tmp = g_strdup_printf ("Field passed in is not a marshaled member of the type %s", klass->name);
4388 exc = mono_get_exception_argument ("fieldName", tmp);
4391 mono_raise_exception ((MonoException*)exc);
4394 info = mono_marshal_load_type_info (klass);
4395 return info->fields [match_index].offset;
4399 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString *string)
4401 MONO_ARCH_SAVE_REGS;
4403 return mono_string_to_utf8 (string);
4407 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni (MonoString *string)
4409 MONO_ARCH_SAVE_REGS;
4411 return g_memdup (mono_string_chars (string), mono_string_length (string)*2);
4415 mono_struct_delete_old (MonoClass *klass, char *ptr)
4417 MonoMarshalType *info;
4420 info = mono_marshal_load_type_info (klass);
4422 for (i = 0; i < info->num_fields; i++) {
4423 MonoMarshalNative ntype;
4424 MonoMarshalConv conv;
4425 MonoType *ftype = info->fields [i].field->type;
4428 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
4431 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE,
4432 klass->unicode, &conv);
4434 cpos = ptr + info->fields [i].offset;
4437 case MONO_MARSHAL_CONV_NONE:
4438 if (MONO_TYPE_ISSTRUCT (ftype)) {
4439 mono_struct_delete_old (ftype->data.klass, cpos);
4443 case MONO_MARSHAL_CONV_STR_LPWSTR:
4444 case MONO_MARSHAL_CONV_STR_LPSTR:
4445 case MONO_MARSHAL_CONV_STR_LPTSTR:
4446 case MONO_MARSHAL_CONV_STR_BSTR:
4447 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
4448 case MONO_MARSHAL_CONV_STR_TBSTR:
4449 g_free (*(gpointer *)cpos);
4458 ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure (gpointer src, MonoReflectionType *type)
4462 MONO_ARCH_SAVE_REGS;
4464 MONO_CHECK_ARG_NULL (src);
4465 MONO_CHECK_ARG_NULL (type);
4467 klass = mono_class_from_mono_type (type->type);
4469 mono_struct_delete_old (klass, (char *)src);
4473 mono_marshal_load_type_info (MonoClass* klass)
4475 int i, j, count = 0, native_size = 0;
4476 MonoMarshalType *info;
4479 g_assert (klass != NULL);
4481 if (klass->marshal_info)
4482 return klass->marshal_info;
4485 mono_class_init (klass);
4487 for (i = 0; i < klass->field.count; ++i) {
4488 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
4493 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
4495 klass->marshal_info = info = g_malloc0 (sizeof (MonoMarshalType) + sizeof (MonoMarshalField) * count);
4496 info->num_fields = count;
4498 /* Try to find a size for this type in metadata */
4499 mono_metadata_packing_from_typedef (klass->image, klass->type_token, NULL, &native_size);
4501 if (klass->parent) {
4502 int parent_size = mono_class_native_size (klass->parent, NULL);
4504 /* Add parent size to real size */
4505 native_size += parent_size;
4506 info->native_size = parent_size;
4509 for (j = i = 0; i < klass->field.count; ++i) {
4512 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
4515 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL)
4516 mono_metadata_field_info (klass->image, klass->field.first + i,
4517 NULL, NULL, &info->fields [j].mspec);
4519 info->fields [j].field = &klass->fields [i];
4521 if ((klass->field.count == 1) && (klass->instance_size == sizeof (MonoObject)) &&
4522 (strcmp (klass->fields [i].name, "$PRIVATE$") == 0)) {
4523 /* This field is a hack inserted by MCS to empty structures */
4528 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
4529 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
4530 size = mono_marshal_type_size (klass->fields [i].type, info->fields [j].mspec,
4531 &align, TRUE, klass->unicode);
4532 align = klass->packing_size ? MIN (klass->packing_size, align): align;
4533 info->fields [j].offset = info->native_size;
4534 info->fields [j].offset += align - 1;
4535 info->fields [j].offset &= ~(align - 1);
4536 info->native_size = info->fields [j].offset + size;
4538 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
4540 info->fields [j].offset = klass->fields [i].offset - sizeof (MonoObject);
4541 info->native_size = klass->instance_size - sizeof (MonoObject);
4547 if(layout != TYPE_ATTRIBUTE_AUTO_LAYOUT) {
4548 info->native_size = MAX (native_size, info->native_size);
4551 if (info->native_size & (klass->min_align - 1)) {
4552 info->native_size += klass->min_align - 1;
4553 info->native_size &= ~(klass->min_align - 1);
4556 return klass->marshal_info;
4560 * mono_class_native_size:
4563 * Returns: the native size of an object instance (when marshaled
4564 * to unmanaged code)
4567 mono_class_native_size (MonoClass *klass, guint32 *align)
4570 if (!klass->marshal_info)
4571 mono_marshal_load_type_info (klass);
4574 *align = klass->min_align;
4576 return klass->marshal_info->native_size;
4580 * mono_type_native_stack_size:
4581 * @t: the type to return the size it uses on the stack
4583 * Returns: the number of bytes required to hold an instance of this
4584 * type on the native stack
4587 mono_type_native_stack_size (MonoType *t, gint *align)
4591 g_assert (t != NULL);
4602 case MONO_TYPE_BOOLEAN:
4603 case MONO_TYPE_CHAR:
4612 case MONO_TYPE_STRING:
4613 case MONO_TYPE_OBJECT:
4614 case MONO_TYPE_CLASS:
4615 case MONO_TYPE_SZARRAY:
4617 case MONO_TYPE_FNPTR:
4618 case MONO_TYPE_ARRAY:
4619 case MONO_TYPE_TYPEDBYREF:
4630 case MONO_TYPE_VALUETYPE: {
4633 if (t->data.klass->enumtype)
4634 return mono_type_native_stack_size (t->data.klass->enum_basetype, align);
4636 size = mono_class_native_size (t->data.klass, align);
4637 *align = *align + 3;
4647 g_error ("type 0x%02x unknown", t->type);
4652 /* __alignof__ returns the preferred alignment of values not the actual alignment used by
4653 the compiler so is wrong e.g. for Linux where doubles are aligned on a 4 byte boundary
4654 but __alignof__ returns 8 - using G_STRUCT_OFFSET works better */
4655 #define ALIGNMENT(type) G_STRUCT_OFFSET(struct { char c; type x; }, x)
4658 mono_marshal_type_size (MonoType *type, MonoMarshalSpec *mspec, gint32 *align,
4659 gboolean as_field, gboolean unicode)
4661 MonoMarshalNative native_type = mono_type_to_unmanaged (type, mspec, as_field, unicode, NULL);
4664 switch (native_type) {
4665 case MONO_NATIVE_BOOLEAN:
4668 case MONO_NATIVE_I1:
4669 case MONO_NATIVE_U1:
4672 case MONO_NATIVE_I2:
4673 case MONO_NATIVE_U2:
4674 case MONO_NATIVE_VARIANTBOOL:
4677 case MONO_NATIVE_I4:
4678 case MONO_NATIVE_U4:
4679 case MONO_NATIVE_ERROR:
4682 case MONO_NATIVE_I8:
4683 case MONO_NATIVE_U8:
4684 *align = ALIGNMENT(guint64);
4686 case MONO_NATIVE_R4:
4689 case MONO_NATIVE_R8:
4690 *align = ALIGNMENT(double);
4692 case MONO_NATIVE_INT:
4693 case MONO_NATIVE_UINT:
4694 case MONO_NATIVE_LPSTR:
4695 case MONO_NATIVE_LPWSTR:
4696 case MONO_NATIVE_LPTSTR:
4697 case MONO_NATIVE_BSTR:
4698 case MONO_NATIVE_ANSIBSTR:
4699 case MONO_NATIVE_TBSTR:
4700 case MONO_NATIVE_LPARRAY:
4701 case MONO_NATIVE_SAFEARRAY:
4702 case MONO_NATIVE_IUNKNOWN:
4703 case MONO_NATIVE_IDISPATCH:
4704 case MONO_NATIVE_INTERFACE:
4705 case MONO_NATIVE_ASANY:
4706 case MONO_NATIVE_FUNC:
4707 case MONO_NATIVE_LPSTRUCT:
4708 *align = ALIGNMENT(gpointer);
4709 return sizeof (gpointer);
4710 case MONO_NATIVE_STRUCT:
4711 klass = mono_class_from_mono_type (type);
4712 return mono_class_native_size (klass, align);
4713 case MONO_NATIVE_BYVALTSTR: {
4714 int esize = unicode ? 2: 1;
4717 return mspec->data.array_data.num_elem * esize;
4719 case MONO_NATIVE_BYVALARRAY: {
4721 klass = mono_class_from_mono_type (type);
4722 esize = mono_class_native_size (klass->element_class, align);
4724 return mspec->data.array_data.num_elem * esize;
4726 case MONO_NATIVE_CUSTOM:
4727 g_assert_not_reached ();
4729 case MONO_NATIVE_CURRENCY:
4730 case MONO_NATIVE_VBBYREFSTR:
4732 g_error ("native type %02x not implemented", native_type);
4735 g_assert_not_reached ();