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)
1177 if (wrapper->wrapper_type == MONO_WRAPPER_NONE)
1180 EnterCriticalSection (&marshal_mutex);
1181 res = mono_g_hash_table_lookup (wrapper_hash, wrapper);
1182 LeaveCriticalSection (&marshal_mutex);
1184 if (wrapper->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)
1185 /* See mono_marshal_get_remoting_invoke_with_check */
1186 return (MonoMethod*)((char*)res - 1);
1192 mono_marshal_get_delegate_begin_invoke (MonoMethod *method)
1194 MonoMethodSignature *sig;
1195 static MonoMethodSignature *csig = NULL;
1196 MonoMethodBuilder *mb;
1202 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1203 !strcmp (method->name, "BeginInvoke"));
1205 sig = method->signature;
1207 cache = method->klass->image->delegate_begin_invoke_cache;
1208 if ((res = mono_marshal_find_in_cache (cache, sig)))
1211 g_assert (sig->hasthis);
1214 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1215 csig = g_malloc0 (sigsize);
1217 /* MonoAsyncResult * begin_invoke (MonoDelegate *delegate, gpointer params[]) */
1218 csig->param_count = 2;
1219 csig->ret = &mono_defaults.object_class->byval_arg;
1220 csig->params [0] = &mono_defaults.object_class->byval_arg;
1221 csig->params [1] = &mono_defaults.int_class->byval_arg;
1224 name = mono_signature_to_name (sig, "begin_invoke");
1225 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_BEGIN_INVOKE);
1228 mb->method->save_lmf = 1;
1230 params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1232 mono_mb_emit_ldarg (mb, 0);
1233 mono_mb_emit_ldloc (mb, params_var);
1234 mono_mb_emit_native_call (mb, csig, mono_delegate_begin_invoke);
1235 mono_mb_emit_byte (mb, CEE_RET);
1237 res = mono_mb_create_and_cache (cache, sig, mb, sig, sig->param_count + 16);
1243 mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params)
1245 MonoDomain *domain = mono_domain_get ();
1246 MonoAsyncResult *ares;
1247 MonoMethod *method = NULL;
1248 MonoMethodSignature *sig;
1249 MonoMethodMessage *msg;
1250 MonoObject *res, *exc;
1251 MonoArray *out_args;
1255 g_assert (delegate);
1257 if (!delegate->method_info || !delegate->method_info->method)
1258 g_assert_not_reached ();
1260 klass = delegate->object.vtable->klass;
1262 for (i = 0; i < klass->method.count; ++i) {
1263 if (klass->methods [i]->name[0] == 'E' &&
1264 !strcmp ("EndInvoke", klass->methods [i]->name)) {
1265 method = klass->methods [i];
1270 g_assert (method != NULL);
1272 sig = method->signature;
1274 msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1276 ares = mono_array_get (msg->args, gpointer, sig->param_count - 1);
1279 if (delegate->target && mono_object_class (delegate->target) == mono_defaults.transparent_proxy_class) {
1280 MonoTransparentProxy* tp = (MonoTransparentProxy *)delegate->target;
1281 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
1282 mono_message_init (domain, msg, delegate->method_info, NULL);
1283 msg->call_type = CallType_EndInvoke;
1284 msg->async_result = ares;
1285 res = mono_remoting_invoke ((MonoObject *)tp->rp, msg, &exc, &out_args);
1288 res = mono_thread_pool_finish (ares, &out_args, &exc);
1291 char *strace = mono_string_to_utf8 (((MonoException*)exc)->stack_trace);
1293 tmp = g_strdup_printf ("%s\nException Rethrown at:\n", strace);
1295 ((MonoException*)exc)->stack_trace = mono_string_new (domain, tmp);
1297 mono_raise_exception ((MonoException*)exc);
1300 mono_method_return_message_restore (method, params, out_args);
1305 mono_mb_emit_restore_result (MonoMethodBuilder *mb, MonoType *return_type)
1307 if (return_type->byref)
1308 return_type = &mono_defaults.int_class->byval_arg;
1309 else if (return_type->type == MONO_TYPE_VALUETYPE && return_type->data.klass->enumtype)
1310 return_type = return_type->data.klass->enum_basetype;
1312 switch (return_type->type) {
1313 case MONO_TYPE_VOID:
1314 g_assert_not_reached ();
1317 case MONO_TYPE_STRING:
1318 case MONO_TYPE_CLASS:
1319 case MONO_TYPE_OBJECT:
1320 case MONO_TYPE_ARRAY:
1321 case MONO_TYPE_SZARRAY:
1325 case MONO_TYPE_BOOLEAN:
1326 mono_mb_emit_byte (mb, CEE_UNBOX);
1327 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1328 mono_mb_emit_byte (mb, CEE_LDIND_U1);
1331 mono_mb_emit_byte (mb, CEE_UNBOX);
1332 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1333 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1336 case MONO_TYPE_CHAR:
1337 mono_mb_emit_byte (mb, CEE_UNBOX);
1338 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1339 mono_mb_emit_byte (mb, CEE_LDIND_U2);
1342 mono_mb_emit_byte (mb, CEE_UNBOX);
1343 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1344 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1348 mono_mb_emit_byte (mb, CEE_UNBOX);
1349 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1350 mono_mb_emit_byte (mb, CEE_LDIND_I);
1353 mono_mb_emit_byte (mb, CEE_UNBOX);
1354 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1355 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1358 mono_mb_emit_byte (mb, CEE_UNBOX);
1359 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1360 mono_mb_emit_byte (mb, CEE_LDIND_U4);
1364 mono_mb_emit_byte (mb, CEE_UNBOX);
1365 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1366 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1369 mono_mb_emit_byte (mb, CEE_UNBOX);
1370 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1371 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1374 mono_mb_emit_byte (mb, CEE_UNBOX);
1375 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1376 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1378 case MONO_TYPE_VALUETYPE: {
1380 mono_mb_emit_byte (mb, CEE_UNBOX);
1381 class = mono_mb_add_data (mb, mono_class_from_mono_type (return_type));
1382 mono_mb_emit_i4 (mb, class);
1383 mono_mb_emit_byte (mb, CEE_LDOBJ);
1384 mono_mb_emit_i4 (mb, class);
1388 g_warning ("type 0x%x not handled", return_type->type);
1389 g_assert_not_reached ();
1392 mono_mb_emit_byte (mb, CEE_RET);
1396 mono_marshal_get_delegate_end_invoke (MonoMethod *method)
1398 MonoMethodSignature *sig;
1399 static MonoMethodSignature *csig = NULL;
1400 MonoMethodBuilder *mb;
1406 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1407 !strcmp (method->name, "EndInvoke"));
1409 sig = method->signature;
1411 cache = method->klass->image->delegate_end_invoke_cache;
1412 if ((res = mono_marshal_find_in_cache (cache, sig)))
1415 g_assert (sig->hasthis);
1418 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1419 csig = g_malloc0 (sigsize);
1421 /* MonoObject *end_invoke (MonoDelegate *delegate, gpointer params[]) */
1422 csig->param_count = 2;
1423 csig->ret = &mono_defaults.object_class->byval_arg;
1424 csig->params [0] = &mono_defaults.object_class->byval_arg;
1425 csig->params [1] = &mono_defaults.int_class->byval_arg;
1428 name = mono_signature_to_name (sig, "end_invoke");
1429 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_END_INVOKE);
1432 mb->method->save_lmf = 1;
1434 params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1436 mono_mb_emit_ldarg (mb, 0);
1437 mono_mb_emit_ldloc (mb, params_var);
1438 mono_mb_emit_native_call (mb, csig, mono_delegate_end_invoke);
1440 if (sig->ret->type == MONO_TYPE_VOID) {
1441 mono_mb_emit_byte (mb, CEE_POP);
1442 mono_mb_emit_byte (mb, CEE_RET);
1444 mono_mb_emit_restore_result (mb, sig->ret);
1446 res = mono_mb_create_and_cache (cache, sig,
1447 mb, sig, sig->param_count + 16);
1454 mono_remoting_wrapper (MonoMethod *method, gpointer *params)
1456 MonoMethodMessage *msg;
1457 MonoTransparentProxy *this;
1458 MonoObject *res, *exc;
1459 MonoArray *out_args;
1461 this = *((MonoTransparentProxy **)params [0]);
1464 g_assert (((MonoObject *)this)->vtable->klass == mono_defaults.transparent_proxy_class);
1466 /* skip the this pointer */
1469 if (this->klass->contextbound && this->rp->context == (MonoObject *) mono_context_get ())
1472 MonoMethodSignature *sig = method->signature;
1473 int count = sig->param_count;
1474 gpointer* mparams = (gpointer*) alloca(count*sizeof(gpointer));
1476 for (i=0; i<count; i++) {
1477 MonoClass *class = mono_class_from_mono_type (sig->params [i]);
1478 if (class->valuetype) {
1479 if (sig->params [i]->byref)
1480 mparams[i] = *((gpointer *)params [i]);
1482 mparams[i] = params [i];
1484 mparams[i] = *((gpointer**)params [i]);
1488 return mono_runtime_invoke (method, this->rp->unwrapped_server, mparams, NULL);
1491 msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1493 res = mono_remoting_invoke ((MonoObject *)this->rp, msg, &exc, &out_args);
1496 mono_raise_exception ((MonoException *)exc);
1498 mono_method_return_message_restore (method, params, out_args);
1504 mono_marshal_get_remoting_invoke (MonoMethod *method)
1506 MonoMethodSignature *sig;
1507 static MonoMethodSignature *csig = NULL;
1508 MonoMethodBuilder *mb;
1515 if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE)
1518 sig = method->signature;
1520 /* we cant remote methods without this pointer */
1524 cache = method->klass->image->remoting_invoke_cache;
1525 if ((res = mono_marshal_find_in_cache (cache, method)))
1529 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
1530 csig->params [0] = &mono_defaults.int_class->byval_arg;
1531 csig->params [1] = &mono_defaults.int_class->byval_arg;
1532 csig->ret = &mono_defaults.object_class->byval_arg;
1536 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE);
1537 mb->method->save_lmf = 1;
1539 params_var = mono_mb_emit_save_args (mb, sig, TRUE);
1541 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1542 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1543 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
1544 mono_mb_emit_ldloc (mb, params_var);
1545 mono_mb_emit_native_call (mb, csig, mono_remoting_wrapper);
1547 if (sig->ret->type == MONO_TYPE_VOID) {
1548 mono_mb_emit_byte (mb, CEE_POP);
1549 mono_mb_emit_byte (mb, CEE_RET);
1551 mono_mb_emit_restore_result (mb, sig->ret);
1554 res = mono_mb_create_and_cache (cache, method, mb, sig, sig->param_count + 16);
1561 mono_marshal_get_remoting_invoke_with_check (MonoMethod *method)
1563 MonoMethodSignature *sig;
1564 MonoMethodBuilder *mb;
1565 MonoMethod *res, *native;
1571 if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)
1574 sig = method->signature;
1576 /* we cant remote methods without this pointer */
1577 g_assert (sig->hasthis);
1579 cache = method->klass->image->remoting_invoke_cache;
1580 if ((res = mono_marshal_find_in_cache (cache, (char *)method + 1)))
1583 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK);
1585 mono_mb_emit_ldarg (mb, 0);
1586 pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
1588 native = mono_marshal_get_remoting_invoke (method);
1590 for (i = 0; i <= sig->param_count; i++)
1591 mono_mb_emit_ldarg (mb, i);
1593 mono_mb_emit_managed_call (mb, native, native->signature);
1594 mono_mb_emit_byte (mb, CEE_RET);
1596 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1598 for (i = 0; i <= sig->param_count; i++)
1599 mono_mb_emit_ldarg (mb, i);
1601 mono_mb_emit_managed_call (mb, method, method->signature);
1602 mono_mb_emit_byte (mb, CEE_RET);
1604 res = mono_mb_create_and_cache (cache, (char*)method + 1,
1605 mb, sig, sig->param_count + 16);
1612 * the returned method invokes all methods in a multicast delegate
1615 mono_marshal_get_delegate_invoke (MonoMethod *method)
1617 MonoMethodSignature *sig, *static_sig;
1619 MonoMethodBuilder *mb;
1625 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1626 !strcmp (method->name, "Invoke"));
1628 sig = method->signature;
1630 cache = method->klass->image->delegate_invoke_cache;
1631 if ((res = mono_marshal_find_in_cache (cache, sig)))
1634 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1635 static_sig = g_memdup (sig, sigsize);
1636 static_sig->hasthis = 0;
1638 name = mono_signature_to_name (sig, "invoke");
1639 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_INVOKE);
1642 /* allocate local 0 (object) */
1643 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1645 g_assert (sig->hasthis);
1649 * prev.Invoke( args .. );
1650 * return this.<target>( args .. );
1653 /* get this->prev */
1654 mono_mb_emit_ldarg (mb, 0);
1655 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoMulticastDelegate, prev));
1656 mono_mb_emit_byte (mb, CEE_LDIND_I );
1657 mono_mb_emit_stloc (mb, 0);
1659 /* if prev != null */
1660 mono_mb_emit_ldloc (mb, 0);
1661 mono_mb_emit_byte (mb, CEE_BRFALSE);
1664 mono_mb_emit_i4 (mb, 0);
1667 mono_mb_emit_ldloc (mb, 0);
1668 for (i = 0; i < sig->param_count; i++)
1669 mono_mb_emit_ldarg (mb, i + 1);
1670 mono_mb_emit_managed_call (mb, method, method->signature);
1671 if (sig->ret->type != MONO_TYPE_VOID)
1672 mono_mb_emit_byte (mb, CEE_POP);
1674 /* continued or prev == null */
1675 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1677 /* get this->target */
1678 mono_mb_emit_ldarg (mb, 0);
1679 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, target));
1680 mono_mb_emit_byte (mb, CEE_LDIND_I );
1681 mono_mb_emit_stloc (mb, 0);
1683 /* if target != null */
1684 mono_mb_emit_ldloc (mb, 0);
1685 mono_mb_emit_byte (mb, CEE_BRFALSE);
1687 mono_mb_emit_i4 (mb, 0);
1689 /* then call this->method_ptr nonstatic */
1690 mono_mb_emit_ldloc (mb, 0);
1691 for (i = 0; i < sig->param_count; ++i)
1692 mono_mb_emit_ldarg (mb, i + 1);
1693 mono_mb_emit_ldarg (mb, 0);
1694 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1695 mono_mb_emit_byte (mb, CEE_LDIND_I );
1696 mono_mb_emit_byte (mb, CEE_CALLI);
1697 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
1699 mono_mb_emit_byte (mb, CEE_BR);
1701 mono_mb_emit_i4 (mb, 0);
1703 /* else [target == null] call this->method_ptr static */
1704 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1706 for (i = 0; i < sig->param_count; ++i)
1707 mono_mb_emit_ldarg (mb, i + 1);
1708 mono_mb_emit_ldarg (mb, 0);
1709 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1710 mono_mb_emit_byte (mb, CEE_LDIND_I );
1711 mono_mb_emit_byte (mb, CEE_CALLI);
1712 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, static_sig));
1715 mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
1716 mono_mb_emit_byte (mb, CEE_RET);
1718 res = mono_mb_create_and_cache (cache, sig,
1719 mb, sig, sig->param_count + 16);
1726 * generates IL code for the runtime invoke function
1727 * MonoObject *runtime_invoke (MonoObject *this, void **params, MonoObject **exc)
1729 * we also catch exceptions if exc != null
1732 mono_marshal_get_runtime_invoke (MonoMethod *method)
1734 MonoMethodSignature *sig, *csig;
1735 MonoExceptionClause *clause;
1736 MonoMethodHeader *header;
1737 MonoMethodBuilder *mb;
1740 static MonoString *string_dummy = NULL;
1741 int i, pos, sigsize;
1745 cache = method->klass->image->runtime_invoke_cache;
1746 if ((res = mono_marshal_find_in_cache (cache, method)))
1749 /* to make it work with our special string constructors */
1751 string_dummy = mono_string_new_wrapper ("dummy");
1753 sig = method->signature;
1755 sigsize = sizeof (MonoMethodSignature) + 3 * sizeof (MonoType *);
1756 csig = g_malloc0 (sigsize);
1758 csig->param_count = 3;
1759 csig->ret = &mono_defaults.object_class->byval_arg;
1760 csig->params [0] = &mono_defaults.object_class->byval_arg;
1761 csig->params [1] = &mono_defaults.int_class->byval_arg;
1762 csig->params [2] = &mono_defaults.int_class->byval_arg;
1764 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_RUNTIME_INVOKE);
1766 /* allocate local 0 (object) tmp */
1767 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1768 /* allocate local 1 (object) exc */
1769 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1771 /* cond set *exc to null */
1772 mono_mb_emit_byte (mb, CEE_LDARG_2);
1773 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
1774 mono_mb_emit_byte (mb, 3);
1775 mono_mb_emit_byte (mb, CEE_LDARG_2);
1776 mono_mb_emit_byte (mb, CEE_LDNULL);
1777 mono_mb_emit_byte (mb, CEE_STIND_I);
1780 if (method->string_ctor) {
1781 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1782 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1783 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, string_dummy));
1785 mono_mb_emit_ldarg (mb, 0);
1786 if (method->klass->valuetype) {
1787 mono_mb_emit_byte (mb, CEE_UNBOX);
1788 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method->klass));
1793 for (i = 0; i < sig->param_count; i++) {
1794 MonoType *t = sig->params [i];
1797 mono_mb_emit_ldarg (mb, 1);
1799 mono_mb_emit_icon (mb, sizeof (gpointer) * i);
1800 mono_mb_emit_byte (mb, CEE_ADD);
1802 mono_mb_emit_byte (mb, CEE_LDIND_I);
1807 type = sig->params [i]->type;
1811 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1813 case MONO_TYPE_BOOLEAN:
1815 mono_mb_emit_byte (mb, CEE_LDIND_U1);
1818 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1821 case MONO_TYPE_CHAR:
1822 mono_mb_emit_byte (mb, CEE_LDIND_U2);
1826 mono_mb_emit_byte (mb, CEE_LDIND_I);
1829 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1832 mono_mb_emit_byte (mb, CEE_LDIND_U4);
1835 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1838 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1842 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1844 case MONO_TYPE_STRING:
1845 case MONO_TYPE_CLASS:
1846 case MONO_TYPE_ARRAY:
1848 case MONO_TYPE_SZARRAY:
1849 case MONO_TYPE_OBJECT:
1852 case MONO_TYPE_VALUETYPE:
1853 if (t->data.klass->enumtype) {
1854 type = t->data.klass->enum_basetype->type;
1857 mono_mb_emit_byte (mb, CEE_LDOBJ);
1858 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, t->data.klass));
1861 g_assert_not_reached ();
1865 if (method->string_ctor) {
1866 MonoMethodSignature *strsig;
1868 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1869 strsig = g_memdup (sig, sigsize);
1870 strsig->ret = &mono_defaults.string_class->byval_arg;
1872 mono_mb_emit_managed_call (mb, method, strsig);
1874 mono_mb_emit_managed_call (mb, method, NULL);
1876 if (sig->ret->byref) {
1878 g_assert_not_reached ();
1882 switch (sig->ret->type) {
1883 case MONO_TYPE_VOID:
1884 if (!method->string_ctor)
1885 mono_mb_emit_byte (mb, CEE_LDNULL);
1887 case MONO_TYPE_BOOLEAN:
1888 case MONO_TYPE_CHAR:
1901 case MONO_TYPE_VALUETYPE:
1902 /* box value types */
1903 mono_mb_emit_byte (mb, CEE_BOX);
1904 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (sig->ret)));
1906 case MONO_TYPE_STRING:
1907 case MONO_TYPE_CLASS:
1908 case MONO_TYPE_ARRAY:
1909 case MONO_TYPE_SZARRAY:
1910 case MONO_TYPE_OBJECT:
1915 g_assert_not_reached ();
1918 mono_mb_emit_stloc (mb, 0);
1920 mono_mb_emit_byte (mb, CEE_LEAVE);
1922 mono_mb_emit_i4 (mb, 0);
1924 clause = g_new0 (MonoExceptionClause, 1);
1925 clause->flags = MONO_EXCEPTION_CLAUSE_FILTER;
1926 clause->try_len = mb->pos;
1929 clause->token_or_filter = mb->pos;
1931 mono_mb_emit_byte (mb, CEE_POP);
1932 mono_mb_emit_byte (mb, CEE_LDARG_2);
1933 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
1934 mono_mb_emit_byte (mb, CEE_PREFIX1);
1935 mono_mb_emit_byte (mb, CEE_CGT_UN);
1936 mono_mb_emit_byte (mb, CEE_PREFIX1);
1937 mono_mb_emit_byte (mb, CEE_ENDFILTER);
1939 clause->handler_offset = mb->pos;
1942 /* store exception */
1943 mono_mb_emit_stloc (mb, 1);
1945 mono_mb_emit_byte (mb, CEE_LDARG_2);
1946 mono_mb_emit_ldloc (mb, 1);
1947 mono_mb_emit_byte (mb, CEE_STIND_I);
1949 mono_mb_emit_byte (mb, CEE_LEAVE);
1950 mono_mb_emit_i4 (mb, 0);
1952 clause->handler_len = mb->pos - clause->handler_offset;
1955 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1956 mono_mb_emit_ldloc (mb, 0);
1957 mono_mb_emit_byte (mb, CEE_RET);
1959 res = mono_mb_create_and_cache (cache, method,
1960 mb, csig, sig->param_count + 16);
1963 header = ((MonoMethodNormal *)res)->header;
1964 header->num_clauses = 1;
1965 header->clauses = clause;
1971 * generates IL code to call managed methods from unmanaged code
1974 mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this, MonoMarshalSpec **mspecs)
1976 MonoMethodSignature *sig, *csig;
1977 MonoMethodBuilder *mb;
1981 int i, pos, sigsize, *tmp_locals;
1982 static MonoMethodSignature *alloc_sig = NULL;
1985 g_assert (method != NULL);
1986 g_assert (!method->signature->pinvoke);
1988 cache = method->klass->image->managed_wrapper_cache;
1989 if (!this && (res = mono_marshal_find_in_cache (cache, method)))
1992 /* Under MS, the allocation should be done using CoTaskMemAlloc */
1994 alloc_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
1995 alloc_sig->params [0] = &mono_defaults.int_class->byval_arg;
1996 alloc_sig->ret = &mono_defaults.int_class->byval_arg;
1997 alloc_sig->pinvoke = 1;
2001 /* fime: howto free that memory ? */
2004 sig = method->signature;
2006 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_NATIVE_TO_MANAGED);
2008 /* allocate local 0 (pointer) src_ptr */
2009 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2010 /* allocate local 1 (pointer) dst_ptr */
2011 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2012 /* allocate local 2 (boolean) delete_old */
2013 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2015 if (!MONO_TYPE_IS_VOID(sig->ret)) {
2016 /* allocate local 3 to store the return value */
2017 mono_mb_add_local (mb, sig->ret);
2020 mono_mb_emit_byte (mb, CEE_LDNULL);
2021 mono_mb_emit_byte (mb, CEE_STLOC_2);
2023 /* we copy the signature, so that we can modify it */
2024 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
2025 csig = g_memdup (sig, sigsize);
2029 #ifdef PLATFORM_WIN32
2031 * Under windows, delegates passed to native code must use the STDCALL
2032 * calling convention.
2034 csig->call_convention = MONO_CALL_STDCALL;
2037 /* fixme: howto handle this ? */
2041 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2042 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
2043 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, this));
2048 g_assert_not_reached ();
2053 /* we first do all conversions */
2054 tmp_locals = alloca (sizeof (int) * sig->param_count);
2055 for (i = 0; i < sig->param_count; i ++) {
2056 MonoType *t = sig->params [i];
2057 MonoMarshalSpec *spec = mspecs [i + 1];
2061 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
2064 MonoMethod *marshal_native_to_managed;
2065 MonoMethod *get_instance;
2067 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
2068 g_assert (mtype != NULL);
2069 mklass = mono_class_from_mono_type (mtype);
2070 g_assert (mklass != NULL);
2072 marshal_native_to_managed = mono_find_method_by_name (mklass, "MarshalNativeToManaged", 1);
2073 g_assert (marshal_native_to_managed);
2074 get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
2075 g_assert (get_instance);
2078 case MONO_TYPE_CLASS:
2079 case MONO_TYPE_OBJECT:
2080 case MONO_TYPE_STRING:
2081 case MONO_TYPE_ARRAY:
2082 case MONO_TYPE_SZARRAY:
2086 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2088 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
2090 mono_mb_emit_byte (mb, CEE_CALL);
2091 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
2093 mono_mb_emit_ldarg (mb, i);
2095 mono_mb_emit_byte (mb, CEE_CALLVIRT);
2096 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_native_to_managed));
2098 mono_mb_emit_stloc (mb, tmp_locals [i]);
2101 g_warning ("custom marshalling of type %x is currently not supported", t->type);
2102 g_assert_not_reached ();
2109 case MONO_TYPE_CLASS: {
2110 klass = t->data.klass;
2112 /* FIXME: Raise a MarshalDirectiveException here */
2113 g_assert ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT);
2115 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2117 if (t->attrs & PARAM_ATTRIBUTE_OUT) {
2118 mono_mb_emit_byte (mb, CEE_LDNULL);
2119 mono_mb_emit_stloc (mb, tmp_locals [i]);
2124 mono_mb_emit_ldarg (mb, i);
2128 /* Check for NULL and raise an exception */
2129 mono_mb_emit_byte (mb, CEE_BRTRUE);
2131 mono_mb_emit_i4 (mb, 0);
2133 mono_mb_emit_exception (mb, "ArgumentNullException");
2135 mono_mb_patch_addr (mb, pos2, mb->pos - (pos2 + 4));
2136 mono_mb_emit_ldarg (mb, i);
2137 mono_mb_emit_byte (mb, CEE_LDIND_I);
2140 mono_mb_emit_byte (mb, CEE_STLOC_0);
2142 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
2143 mono_mb_emit_stloc (mb, tmp_locals [i]);
2145 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2146 mono_mb_emit_byte (mb, CEE_BRFALSE);
2148 mono_mb_emit_i4 (mb, 0);
2150 /* Create and set dst */
2151 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2152 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
2153 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2154 mono_mb_emit_stloc (mb, tmp_locals [i]);
2155 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2156 mono_mb_emit_icon (mb, sizeof (MonoObject));
2157 mono_mb_emit_byte (mb, CEE_ADD);
2158 mono_mb_emit_byte (mb, CEE_STLOC_1);
2160 /* emit valuetype conversion code */
2161 emit_struct_conv (mb, klass, TRUE);
2163 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2166 case MONO_TYPE_VALUETYPE:
2168 klass = sig->params [i]->data.klass;
2169 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2170 klass->blittable || klass->enumtype)
2173 tmp_locals [i] = mono_mb_add_local (mb, &klass->byval_arg);
2176 mono_mb_emit_ldarg (mb, i);
2178 mono_mb_emit_ldarg_addr (mb, i);
2179 mono_mb_emit_byte (mb, CEE_STLOC_0);
2182 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2183 mono_mb_emit_byte (mb, CEE_BRFALSE);
2185 mono_mb_emit_i4 (mb, 0);
2188 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2189 mono_mb_emit_byte (mb, CEE_STLOC_1);
2191 /* emit valuetype convnversion code code */
2192 emit_struct_conv (mb, klass, TRUE);
2195 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2197 case MONO_TYPE_STRING:
2201 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2202 csig->params [i] = &mono_defaults.int_class->byval_arg;
2204 mono_mb_emit_ldarg (mb, i);
2205 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2206 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2207 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
2208 mono_mb_emit_stloc (mb, tmp_locals [i]);
2210 case MONO_TYPE_ARRAY:
2211 case MONO_TYPE_SZARRAY:
2215 klass = mono_class_from_mono_type (t);
2217 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2218 csig->params [i] = &mono_defaults.int_class->byval_arg;
2220 g_warning ("array marshaling not implemented");
2221 g_assert_not_reached ();
2226 for (i = 0; i < sig->param_count; i++) {
2227 MonoType *t = sig->params [i];
2230 case MONO_TYPE_BOOLEAN:
2244 mono_mb_emit_ldarg (mb, i);
2246 case MONO_TYPE_STRING:
2248 mono_mb_emit_ldarg (mb, i);
2250 g_assert (tmp_locals [i]);
2251 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2254 case MONO_TYPE_CLASS:
2256 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2258 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2260 case MONO_TYPE_ARRAY:
2261 case MONO_TYPE_SZARRAY:
2262 case MONO_TYPE_OBJECT:
2264 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2266 mono_mb_emit_ldarg (mb, i);
2268 case MONO_TYPE_VALUETYPE:
2269 klass = sig->params [i]->data.klass;
2270 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2271 klass->blittable || klass->enumtype) {
2272 mono_mb_emit_ldarg (mb, i);
2276 g_assert (tmp_locals [i]);
2278 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2280 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2283 g_warning ("type 0x%02x unknown", t->type);
2284 g_assert_not_reached ();
2288 mono_mb_emit_managed_call (mb, method, NULL);
2290 if (!sig->ret->byref) {
2291 switch (sig->ret->type) {
2292 case MONO_TYPE_VOID:
2294 case MONO_TYPE_BOOLEAN:
2308 case MONO_TYPE_OBJECT:
2309 mono_mb_emit_byte (mb, CEE_STLOC_3);
2311 case MONO_TYPE_STRING:
2312 csig->ret = &mono_defaults.int_class->byval_arg;
2314 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2315 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2316 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
2317 mono_mb_emit_byte (mb, CEE_STLOC_3);
2319 case MONO_TYPE_VALUETYPE:
2320 klass = sig->ret->data.klass;
2321 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2322 klass->blittable || klass->enumtype)
2325 /* load pointer to returned value type */
2326 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2327 mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
2329 /* store the address of the source into local variable 0 */
2330 mono_mb_emit_byte (mb, CEE_STLOC_0);
2331 /* allocate space for the native struct and
2332 * store the address into dst_ptr */
2333 retobj_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2334 g_assert (retobj_var);
2335 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2336 mono_mb_emit_native_call (mb, alloc_sig, mono_marshal_alloc);
2337 mono_mb_emit_byte (mb, CEE_STLOC_1);
2338 mono_mb_emit_byte (mb, CEE_LDLOC_1);
2339 mono_mb_emit_stloc (mb, retobj_var);
2341 /* emit valuetype conversion code */
2342 emit_struct_conv (mb, klass, FALSE);
2344 case MONO_TYPE_CLASS: {
2347 klass = sig->ret->data.klass;
2349 /* FIXME: Raise a MarshalDirectiveException here */
2350 g_assert ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT);
2352 mono_mb_emit_byte (mb, CEE_STLOC_0);
2353 /* Check for null */
2354 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2355 pos = mono_mb_emit_branch (mb, CEE_BRTRUE);
2356 mono_mb_emit_byte (mb, CEE_LDNULL);
2357 mono_mb_emit_byte (mb, CEE_STLOC_3);
2358 pos2 = mono_mb_emit_branch (mb, CEE_BR);
2360 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2363 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2364 mono_mb_emit_icon (mb, sizeof (MonoObject));
2365 mono_mb_emit_byte (mb, CEE_ADD);
2366 mono_mb_emit_byte (mb, CEE_STLOC_0);
2368 /* Allocate and set dest */
2369 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2370 mono_mb_emit_native_call (mb, alloc_sig, mono_marshal_alloc);
2371 mono_mb_emit_byte (mb, CEE_DUP);
2372 mono_mb_emit_byte (mb, CEE_STLOC_1);
2373 mono_mb_emit_byte (mb, CEE_STLOC_3);
2375 emit_struct_conv (mb, klass, FALSE);
2377 mono_mb_patch_addr (mb, pos2, mb->pos - (pos2 + 4));
2381 g_warning ("return type 0x%02x unknown", sig->ret->type);
2382 g_assert_not_reached ();
2385 mono_mb_emit_byte (mb, CEE_STLOC_3);
2388 /* Convert byref arguments back */
2389 for (i = 0; i < sig->param_count; i ++) {
2390 MonoType *t = sig->params [i];
2396 case MONO_TYPE_CLASS: {
2399 klass = t->data.klass;
2401 /* Check for null */
2402 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2403 pos = mono_mb_emit_branch (mb, CEE_BRTRUE);
2404 mono_mb_emit_ldarg (mb, i);
2405 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
2406 mono_mb_emit_byte (mb, CEE_STIND_I);
2407 pos2 = mono_mb_emit_branch (mb, CEE_BR);
2409 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2412 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2413 mono_mb_emit_icon (mb, sizeof (MonoObject));
2414 mono_mb_emit_byte (mb, CEE_ADD);
2415 mono_mb_emit_byte (mb, CEE_STLOC_0);
2417 /* Allocate and set dest */
2418 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2419 mono_mb_emit_native_call (mb, alloc_sig, mono_marshal_alloc);
2420 mono_mb_emit_byte (mb, CEE_STLOC_1);
2422 /* Update argument pointer */
2423 mono_mb_emit_ldarg (mb, i);
2424 mono_mb_emit_byte (mb, CEE_LDLOC_1);
2425 mono_mb_emit_byte (mb, CEE_STIND_I);
2427 /* emit valuetype conversion code */
2428 emit_struct_conv (mb, klass, FALSE);
2430 mono_mb_patch_addr (mb, pos2, mb->pos - (pos2 + 4));
2437 mono_mb_emit_ldloc (mb, retobj_var);
2438 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2439 mono_mb_emit_byte (mb, CEE_MONO_RETOBJ);
2440 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2443 if (!MONO_TYPE_IS_VOID(sig->ret))
2444 mono_mb_emit_byte (mb, CEE_LDLOC_3);
2445 mono_mb_emit_byte (mb, CEE_RET);
2449 res = mono_mb_create_and_cache (cache, method,
2450 mb, csig, sig->param_count + 16);
2452 res = mono_mb_create_method (mb, csig, sig->param_count + 16);
2455 //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));
2461 * mono_marshal_get_ldfld_wrapper:
2462 * @type: the type of the field
2464 * This method generates a function which can be use to load a field with type
2465 * @type from an object. The generated function has the following signature:
2466 * <@type> ldfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset)
2469 mono_marshal_get_ldfld_wrapper (MonoType *type)
2471 MonoMethodSignature *sig, *csig;
2472 MonoMethodBuilder *mb;
2475 static GHashTable *ldfld_hash = NULL;
2482 if (type->type == MONO_TYPE_SZARRAY) {
2483 klass = mono_defaults.array_class;
2484 } else if (type->type == MONO_TYPE_VALUETYPE) {
2485 klass = type->data.klass;
2486 if (klass->enumtype) {
2487 t = klass->enum_basetype->type;
2488 klass = mono_class_from_mono_type (klass->enum_basetype);
2490 } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
2491 t == MONO_TYPE_CLASS) {
2492 klass = mono_defaults.object_class;
2493 } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
2494 klass = mono_defaults.int_class;
2496 klass = mono_class_from_mono_type (type);
2499 klass = mono_defaults.int_class;
2502 EnterCriticalSection (&marshal_mutex);
2504 ldfld_hash = g_hash_table_new (NULL, NULL);
2505 res = g_hash_table_lookup (ldfld_hash, klass);
2506 LeaveCriticalSection (&marshal_mutex);
2510 name = g_strdup_printf ("__ldfld_wrapper_%s.%s", klass->name_space, klass->name);
2511 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_LDFLD);
2514 mb->method->save_lmf = 1;
2516 sig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
2517 sig->params [0] = &mono_defaults.object_class->byval_arg;
2518 sig->params [1] = &mono_defaults.int_class->byval_arg;
2519 sig->params [2] = &mono_defaults.int_class->byval_arg;
2520 sig->params [3] = &mono_defaults.int_class->byval_arg;
2521 sig->ret = &klass->byval_arg;
2523 mono_mb_emit_ldarg (mb, 0);
2524 pos0 = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
2526 mono_mb_emit_ldarg (mb, 0);
2527 mono_mb_emit_ldarg (mb, 1);
2528 mono_mb_emit_ldarg (mb, 2);
2530 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
2531 csig->params [0] = &mono_defaults.object_class->byval_arg;
2532 csig->params [1] = &mono_defaults.int_class->byval_arg;
2533 csig->params [2] = &mono_defaults.int_class->byval_arg;
2534 csig->ret = &klass->this_arg;
2537 mono_mb_emit_native_call (mb, csig, mono_load_remote_field_new);
2539 if (klass->valuetype) {
2540 mono_mb_emit_byte (mb, CEE_UNBOX);
2541 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2542 mono_mb_emit_byte (mb, CEE_BR);
2544 mono_mb_emit_i4 (mb, 0);
2546 mono_mb_emit_byte (mb, CEE_RET);
2550 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
2552 mono_mb_emit_ldarg (mb, 0);
2553 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2554 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2555 mono_mb_emit_ldarg (mb, 3);
2556 mono_mb_emit_byte (mb, CEE_ADD);
2558 if (klass->valuetype)
2559 mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
2564 case MONO_TYPE_BOOLEAN:
2565 mono_mb_emit_byte (mb, CEE_LDIND_I1);
2567 case MONO_TYPE_CHAR:
2570 mono_mb_emit_byte (mb, CEE_LDIND_I2);
2574 mono_mb_emit_byte (mb, CEE_LDIND_I4);
2578 mono_mb_emit_byte (mb, CEE_LDIND_I8);
2581 mono_mb_emit_byte (mb, CEE_LDIND_R4);
2584 mono_mb_emit_byte (mb, CEE_LDIND_R8);
2586 case MONO_TYPE_ARRAY:
2588 case MONO_TYPE_FNPTR:
2589 case MONO_TYPE_SZARRAY:
2590 case MONO_TYPE_OBJECT:
2591 case MONO_TYPE_CLASS:
2592 case MONO_TYPE_STRING:
2595 mono_mb_emit_byte (mb, CEE_LDIND_I);
2597 case MONO_TYPE_VALUETYPE:
2598 g_assert (!klass->enumtype);
2599 mono_mb_emit_byte (mb, CEE_LDOBJ);
2600 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2603 g_warning ("type %x not implemented", type->type);
2604 g_assert_not_reached ();
2607 mono_mb_emit_byte (mb, CEE_RET);
2609 res = mono_mb_create_and_cache (ldfld_hash, klass,
2610 mb, sig, sig->param_count + 16);
2617 * mono_marshal_get_stfld_wrapper:
2618 * @type: the type of the field
2620 * This method generates a function which can be use to store a field with type
2621 * @type. The generated function has the following signature:
2622 * void stfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset, <@type> val)
2625 mono_marshal_get_stfld_wrapper (MonoType *type)
2627 MonoMethodSignature *sig, *csig;
2628 MonoMethodBuilder *mb;
2631 static GHashTable *stfld_hash = NULL;
2638 if (type->type == MONO_TYPE_SZARRAY) {
2639 klass = mono_defaults.array_class;
2640 } else if (type->type == MONO_TYPE_VALUETYPE) {
2641 klass = type->data.klass;
2642 if (klass->enumtype) {
2643 t = klass->enum_basetype->type;
2644 klass = mono_class_from_mono_type (klass->enum_basetype);
2646 } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
2647 t == MONO_TYPE_CLASS) {
2648 klass = mono_defaults.object_class;
2649 } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
2650 klass = mono_defaults.int_class;
2652 klass = mono_class_from_mono_type (type);
2655 klass = mono_defaults.int_class;
2658 EnterCriticalSection (&marshal_mutex);
2660 stfld_hash = g_hash_table_new (NULL, NULL);
2661 res = g_hash_table_lookup (stfld_hash, klass);
2662 LeaveCriticalSection (&marshal_mutex);
2666 name = g_strdup_printf ("__stfld_wrapper_%s.%s", klass->name_space, klass->name);
2667 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_STFLD);
2670 mb->method->save_lmf = 1;
2672 sig = mono_metadata_signature_alloc (mono_defaults.corlib, 5);
2673 sig->params [0] = &mono_defaults.object_class->byval_arg;
2674 sig->params [1] = &mono_defaults.int_class->byval_arg;
2675 sig->params [2] = &mono_defaults.int_class->byval_arg;
2676 sig->params [3] = &mono_defaults.int_class->byval_arg;
2677 sig->params [4] = &klass->byval_arg;
2678 sig->ret = &mono_defaults.void_class->byval_arg;
2680 mono_mb_emit_ldarg (mb, 0);
2681 pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
2683 mono_mb_emit_ldarg (mb, 0);
2684 mono_mb_emit_ldarg (mb, 1);
2685 mono_mb_emit_ldarg (mb, 2);
2686 mono_mb_emit_ldarg (mb, 4);
2688 if (klass->valuetype) {
2689 mono_mb_emit_byte (mb, CEE_BOX);
2690 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2693 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
2694 csig->params [0] = &mono_defaults.object_class->byval_arg;
2695 csig->params [1] = &mono_defaults.int_class->byval_arg;
2696 csig->params [2] = &mono_defaults.int_class->byval_arg;
2697 csig->params [3] = &klass->this_arg;
2698 csig->ret = &mono_defaults.void_class->byval_arg;
2701 mono_mb_emit_native_call (mb, csig, mono_store_remote_field_new);
2703 mono_mb_emit_byte (mb, CEE_RET);
2705 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2707 mono_mb_emit_ldarg (mb, 0);
2708 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2709 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2710 mono_mb_emit_ldarg (mb, 3);
2711 mono_mb_emit_byte (mb, CEE_ADD);
2712 mono_mb_emit_ldarg (mb, 4);
2717 case MONO_TYPE_BOOLEAN:
2718 mono_mb_emit_byte (mb, CEE_STIND_I1);
2720 case MONO_TYPE_CHAR:
2723 mono_mb_emit_byte (mb, CEE_STIND_I2);
2727 mono_mb_emit_byte (mb, CEE_STIND_I4);
2731 mono_mb_emit_byte (mb, CEE_STIND_I8);
2734 mono_mb_emit_byte (mb, CEE_STIND_R4);
2737 mono_mb_emit_byte (mb, CEE_STIND_R8);
2739 case MONO_TYPE_ARRAY:
2741 case MONO_TYPE_FNPTR:
2742 case MONO_TYPE_SZARRAY:
2743 case MONO_TYPE_OBJECT:
2744 case MONO_TYPE_CLASS:
2745 case MONO_TYPE_STRING:
2748 mono_mb_emit_byte (mb, CEE_STIND_I);
2750 case MONO_TYPE_VALUETYPE:
2751 g_assert (!klass->enumtype);
2752 mono_mb_emit_byte (mb, CEE_STOBJ);
2753 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2756 g_warning ("type %x not implemented", type->type);
2757 g_assert_not_reached ();
2760 mono_mb_emit_byte (mb, CEE_RET);
2762 res = mono_mb_create_and_cache (stfld_hash, klass,
2763 mb, sig, sig->param_count + 16);
2770 * generates IL code for the icall wrapper (the generated method
2771 * calls the unmanaged code in func)
2774 mono_marshal_get_icall_wrapper (MonoMethodSignature *sig, const char *name, gconstpointer func)
2776 MonoMethodSignature *csig;
2777 MonoMethodBuilder *mb;
2781 g_assert (sig->pinvoke);
2783 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_MANAGED_TO_NATIVE);
2785 mb->method->save_lmf = 1;
2787 /* we copy the signature, so that we can modify it */
2788 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
2791 mono_mb_emit_byte (mb, CEE_LDARG_0);
2793 for (i = 0; i < sig->param_count; i++)
2794 mono_mb_emit_ldarg (mb, i + sig->hasthis);
2796 mono_mb_emit_native_call (mb, sig, (gpointer) func);
2798 mono_mb_emit_byte (mb, CEE_RET);
2800 csig = g_memdup (sig, sigsize);
2803 res = mono_mb_create_method (mb, csig, csig->param_count + 16);
2810 * generates IL code for the pinvoke wrapper (the generated method
2811 * calls the unmanaged code in method->addr)
2814 mono_marshal_get_native_wrapper (MonoMethod *method)
2816 MonoMethodSignature *sig, *csig;
2817 MonoMethodPInvoke *piinfo;
2818 MonoMethodBuilder *mb;
2819 MonoMarshalSpec **mspecs;
2823 gboolean pinvoke = FALSE;
2824 int i, pos, argnum, *tmp_locals;
2827 g_assert (method != NULL);
2828 g_assert (method->signature->pinvoke);
2830 cache = method->klass->image->native_wrapper_cache;
2831 if ((res = mono_marshal_find_in_cache (cache, method)))
2834 sig = method->signature;
2835 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
2837 if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
2838 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2841 if (!method->addr) {
2843 mono_lookup_pinvoke_call (method);
2845 method->addr = mono_lookup_internal_call (method);
2848 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_MANAGED_TO_NATIVE);
2850 mb->method->save_lmf = 1;
2852 piinfo = (MonoMethodPInvoke *)method;
2854 if (!method->addr) {
2855 mono_mb_emit_exception (mb, "MissingMethodException");
2856 csig = g_memdup (sig, sigsize);
2858 res = mono_mb_create_and_cache (cache, method,
2859 mb, csig, csig->param_count + 16);
2864 /* internal calls: we simply push all arguments and call the method (no conversions) */
2865 if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
2867 /* hack - string constructors returns a value */
2868 if (method->string_ctor) {
2869 csig = g_memdup (sig, sigsize);
2870 csig->ret = &mono_defaults.string_class->byval_arg;
2875 mono_mb_emit_byte (mb, CEE_LDARG_0);
2877 for (i = 0; i < sig->param_count; i++)
2878 mono_mb_emit_ldarg (mb, i + sig->hasthis);
2880 g_assert (method->addr);
2881 mono_mb_emit_native_call (mb, csig, method->addr);
2883 mono_mb_emit_byte (mb, CEE_RET);
2885 csig = g_memdup (csig, sigsize);
2887 res = mono_mb_create_and_cache (cache, method,
2888 mb, csig, csig->param_count + 16);
2895 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
2896 mono_method_get_marshal_info (method, mspecs);
2898 /* pinvoke: we need to convert the arguments if necessary */
2900 /* we copy the signature, so that we can set pinvoke to 0 */
2901 csig = g_memdup (sig, sigsize);
2904 /* we allocate local for use with emit_struct_conv() */
2905 /* allocate local 0 (pointer) src_ptr */
2906 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2907 /* allocate local 1 (pointer) dst_ptr */
2908 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2909 /* allocate local 2 (boolean) delete_old */
2910 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2912 /* delete_old = FALSE */
2913 mono_mb_emit_icon (mb, 0);
2914 mono_mb_emit_byte (mb, CEE_STLOC_2);
2916 if (!MONO_TYPE_IS_VOID(sig->ret)) {
2917 /* allocate local 3 to store the return value */
2918 mono_mb_add_local (mb, sig->ret);
2921 /* we first do all conversions */
2922 tmp_locals = alloca (sizeof (int) * sig->param_count);
2924 for (i = 0; i < sig->param_count; i ++) {
2925 MonoType *t = sig->params [i];
2926 MonoMarshalSpec *spec = mspecs [i + 1];
2928 argnum = i + sig->hasthis;
2931 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
2934 MonoMethod *marshal_managed_to_native;
2935 MonoMethod *get_instance;
2937 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
2938 g_assert (mtype != NULL);
2939 mklass = mono_class_from_mono_type (mtype);
2940 g_assert (mklass != NULL);
2942 marshal_managed_to_native = mono_find_method_by_name (mklass, "MarshalManagedToNative", 1);
2943 g_assert (marshal_managed_to_native);
2944 get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
2945 g_assert (get_instance);
2948 case MONO_TYPE_CLASS:
2949 case MONO_TYPE_OBJECT:
2950 case MONO_TYPE_STRING:
2951 case MONO_TYPE_ARRAY:
2952 case MONO_TYPE_SZARRAY:
2956 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2958 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
2960 mono_mb_emit_byte (mb, CEE_CALL);
2961 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
2963 mono_mb_emit_ldarg (mb, argnum);
2965 mono_mb_emit_byte (mb, CEE_CALLVIRT);
2966 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_managed_to_native));
2968 mono_mb_emit_stloc (mb, tmp_locals [i]);
2971 g_warning ("custom marshalling of type %x is currently not supported", t->type);
2972 g_assert_not_reached ();
2980 case MONO_TYPE_VALUETYPE:
2981 klass = t->data.klass;
2983 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2984 klass->blittable || klass->enumtype)
2987 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2989 /* store the address of the source into local variable 0 */
2991 mono_mb_emit_ldarg (mb, argnum);
2993 mono_mb_emit_ldarg_addr (mb, argnum);
2995 mono_mb_emit_byte (mb, CEE_STLOC_0);
2997 /* allocate space for the native struct and
2998 * store the address into local variable 1 (dest) */
2999 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
3000 mono_mb_emit_byte (mb, CEE_PREFIX1);
3001 mono_mb_emit_byte (mb, CEE_LOCALLOC);
3002 mono_mb_emit_stloc (mb, tmp_locals [i]);
3005 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3006 mono_mb_emit_byte (mb, CEE_BRFALSE);
3008 mono_mb_emit_i4 (mb, 0);
3012 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3013 mono_mb_emit_byte (mb, CEE_STLOC_1);
3015 /* emit valuetype conversion code */
3016 emit_struct_conv (mb, klass, FALSE);
3019 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3021 case MONO_TYPE_STRING:
3022 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3023 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3026 if (t->attrs & PARAM_ATTRIBUTE_OUT)
3029 mono_mb_emit_ldarg (mb, argnum);
3030 mono_mb_emit_byte (mb, CEE_LDIND_I);
3032 mono_mb_emit_ldarg (mb, argnum);
3035 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3036 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3039 switch (spec->native) {
3040 case MONO_NATIVE_LPWSTR:
3041 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPWSTR);
3043 case MONO_NATIVE_LPSTR:
3044 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
3047 g_warning ("marshalling conversion %d not implemented", spec->native);
3048 g_assert_not_reached ();
3051 switch (piinfo->piflags & PINVOKE_ATTRIBUTE_CHAR_SET_MASK) {
3052 case PINVOKE_ATTRIBUTE_CHAR_SET_ANSI:
3053 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
3055 case PINVOKE_ATTRIBUTE_CHAR_SET_UNICODE:
3056 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPWSTR);
3058 case PINVOKE_ATTRIBUTE_CHAR_SET_AUTO:
3059 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPTSTR);
3062 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
3067 mono_mb_emit_stloc (mb, tmp_locals [i]);
3069 case MONO_TYPE_CLASS:
3070 case MONO_TYPE_OBJECT:
3071 klass = t->data.klass;
3073 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3074 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3076 if (klass->delegate) {
3077 g_assert (!t->byref);
3078 mono_mb_emit_ldarg (mb, argnum);
3079 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3080 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3081 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_DEL_FTN);
3082 mono_mb_emit_stloc (mb, tmp_locals [i]);
3083 } else if (klass == mono_defaults.stringbuilder_class) {
3084 g_assert (!t->byref);
3085 mono_mb_emit_ldarg (mb, argnum);
3086 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3087 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3088 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_SB_LPSTR);
3089 mono_mb_emit_stloc (mb, tmp_locals [i]);
3091 mono_mb_emit_byte (mb, CEE_LDNULL);
3092 mono_mb_emit_stloc (mb, tmp_locals [i]);
3095 /* we dont need any conversions for out parameters */
3096 if (t->attrs & PARAM_ATTRIBUTE_OUT)
3099 mono_mb_emit_ldarg (mb, argnum);
3100 mono_mb_emit_byte (mb, CEE_LDIND_I);
3103 mono_mb_emit_ldarg (mb, argnum);
3104 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3105 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
3108 /* store the address of the source into local variable 0 */
3109 mono_mb_emit_byte (mb, CEE_STLOC_0);
3110 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3111 mono_mb_emit_byte (mb, CEE_BRFALSE);
3113 mono_mb_emit_i4 (mb, 0);
3115 /* allocate space for the native struct and store the address */
3116 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
3117 mono_mb_emit_byte (mb, CEE_PREFIX1);
3118 mono_mb_emit_byte (mb, CEE_LOCALLOC);
3119 mono_mb_emit_stloc (mb, tmp_locals [i]);
3121 /* set the src_ptr */
3122 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3123 mono_mb_emit_icon (mb, sizeof (MonoObject));
3124 mono_mb_emit_byte (mb, CEE_ADD);
3125 mono_mb_emit_byte (mb, CEE_STLOC_0);
3128 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3129 mono_mb_emit_byte (mb, CEE_STLOC_1);
3131 /* emit valuetype conversion code */
3132 emit_struct_conv (mb, klass, FALSE);
3134 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3138 case MONO_TYPE_ARRAY:
3139 case MONO_TYPE_SZARRAY:
3143 klass = mono_class_from_mono_type (t);
3145 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3146 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3148 if (klass->element_class == mono_defaults.string_class) {
3149 mono_mb_emit_ldarg (mb, argnum);
3150 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3151 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3153 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STRARRAY_STRLPARRAY);
3154 mono_mb_emit_stloc (mb, tmp_locals [i]);
3156 else if (klass->element_class->blittable) {
3157 mono_mb_emit_ldarg (mb, argnum);
3158 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3159 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3161 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_ARRAY_LPARRAY);
3162 mono_mb_emit_stloc (mb, tmp_locals [i]);
3166 guint32 label1, label2, label3;
3167 int index_var, dest_ptr;
3169 dest_ptr = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3172 mono_mb_emit_ldarg (mb, argnum);
3173 mono_mb_emit_stloc (mb, tmp_locals [i]);
3174 mono_mb_emit_ldarg (mb, argnum);
3175 mono_mb_emit_byte (mb, CEE_BRFALSE);
3177 mono_mb_emit_i4 (mb, 0);
3179 /* allocate space for the native struct and store the address */
3180 eklass = klass->element_class;
3181 mono_mb_emit_icon (mb, mono_class_native_size (eklass, NULL));
3182 mono_mb_emit_ldarg (mb, argnum);
3183 mono_mb_emit_byte (mb, CEE_LDLEN);
3184 mono_mb_emit_byte (mb, CEE_MUL);
3185 mono_mb_emit_byte (mb, CEE_PREFIX1);
3186 mono_mb_emit_byte (mb, CEE_LOCALLOC);
3187 mono_mb_emit_stloc (mb, tmp_locals [i]);
3189 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3190 mono_mb_emit_stloc (mb, dest_ptr);
3192 /* Emit marshalling loop */
3193 index_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3194 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
3195 mono_mb_emit_stloc (mb, index_var);
3197 mono_mb_emit_ldloc (mb, index_var);
3198 mono_mb_emit_ldarg (mb, argnum);
3199 mono_mb_emit_byte (mb, CEE_LDLEN);
3200 mono_mb_emit_byte (mb, CEE_BGE);
3202 mono_mb_emit_i4 (mb, 0);
3204 /* Emit marshalling code */
3206 /* set the src_ptr */
3207 mono_mb_emit_ldarg (mb, argnum);
3208 mono_mb_emit_ldloc (mb, index_var);
3209 mono_mb_emit_byte (mb, CEE_LDELEMA);
3210 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eklass));
3211 mono_mb_emit_byte (mb, CEE_STLOC_0);
3214 mono_mb_emit_ldloc (mb, dest_ptr);
3215 mono_mb_emit_byte (mb, CEE_STLOC_1);
3217 /* emit valuetype conversion code */
3218 emit_struct_conv (mb, eklass, FALSE);
3220 mono_mb_emit_add_to_local (mb, index_var, 1);
3221 mono_mb_emit_add_to_local (mb, dest_ptr, mono_class_native_size (eklass, NULL));
3223 mono_mb_emit_byte (mb, CEE_BR);
3224 mono_mb_emit_i4 (mb, label2 - (mb->pos + 4));
3226 mono_mb_patch_addr (mb, label1, mb->pos - (label1 + 4));
3227 mono_mb_patch_addr (mb, label3, mb->pos - (label3 + 4));
3231 case MONO_TYPE_BOOLEAN: {
3232 MonoType *local_type;
3233 int variant_bool = 0;
3237 local_type = &mono_defaults.int32_class->byval_arg;
3239 switch (spec->native) {
3240 case MONO_NATIVE_I1:
3241 local_type = &mono_defaults.byte_class->byval_arg;
3243 case MONO_NATIVE_VARIANTBOOL:
3244 local_type = &mono_defaults.int16_class->byval_arg;
3248 g_warning ("marshalling bool as native type %x is currently not supported", spec->native);
3252 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3253 tmp_locals [i] = mono_mb_add_local (mb, local_type);
3254 mono_mb_emit_ldarg (mb, argnum);
3255 mono_mb_emit_byte (mb, CEE_LDIND_I1);
3257 mono_mb_emit_byte (mb, CEE_NEG);
3258 mono_mb_emit_stloc (mb, tmp_locals [i]);
3264 /* push all arguments */
3267 mono_mb_emit_byte (mb, CEE_LDARG_0);
3269 for (i = 0; i < sig->param_count; i++) {
3270 MonoType *t = sig->params [i];
3272 argnum = i + sig->hasthis;
3275 case MONO_TYPE_BOOLEAN:
3277 g_assert (tmp_locals [i]);
3278 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
3280 mono_mb_emit_ldarg (mb, argnum);
3295 mono_mb_emit_ldarg (mb, argnum);
3297 case MONO_TYPE_VALUETYPE:
3298 klass = sig->params [i]->data.klass;
3299 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3300 klass->blittable || klass->enumtype) {
3301 mono_mb_emit_ldarg (mb, argnum);
3304 g_assert (tmp_locals [i]);
3305 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3307 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3308 mono_mb_emit_byte (mb, CEE_MONO_LDNATIVEOBJ);
3309 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3312 case MONO_TYPE_STRING:
3313 case MONO_TYPE_CLASS:
3314 case MONO_TYPE_OBJECT:
3315 g_assert (tmp_locals [i]);
3317 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
3319 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3321 case MONO_TYPE_CHAR:
3322 /* fixme: dont know how to marshal that. We cant simply
3323 * convert it to a one byte UTF8 character, because an
3324 * unicode character may need more that one byte in UTF8 */
3325 mono_mb_emit_ldarg (mb, argnum);
3327 case MONO_TYPE_ARRAY:
3328 case MONO_TYPE_SZARRAY:
3330 mono_mb_emit_ldarg (mb, argnum);
3332 g_assert (tmp_locals [i]);
3333 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3336 case MONO_TYPE_TYPEDBYREF:
3337 case MONO_TYPE_FNPTR:
3339 g_warning ("type 0x%02x unknown", t->type);
3340 g_assert_not_reached ();
3344 /* call the native method */
3345 mono_mb_emit_native_call (mb, csig, method->addr);
3347 /* Set LastError if needed */
3348 if (piinfo->piflags & PINVOKE_ATTRIBUTE_SUPPORTS_LAST_ERROR) {
3349 MonoMethodSignature *lasterr_sig;
3351 lasterr_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
3352 lasterr_sig->ret = &mono_defaults.void_class->byval_arg;
3353 lasterr_sig->pinvoke = 1;
3355 mono_mb_emit_native_call (mb, lasterr_sig, mono_marshal_set_last_error);
3358 /* convert the result */
3359 if (!sig->ret->byref) {
3360 MonoMarshalSpec *spec = mspecs [0];
3361 type = sig->ret->type;
3363 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
3366 MonoMethod *marshal_native_to_managed;
3367 MonoMethod *get_instance;
3369 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
3370 g_assert (mtype != NULL);
3371 mklass = mono_class_from_mono_type (mtype);
3372 g_assert (mklass != NULL);
3374 marshal_native_to_managed = mono_find_method_by_name (mklass, "MarshalNativeToManaged", 1);
3375 g_assert (marshal_native_to_managed);
3376 get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
3377 g_assert (get_instance);
3380 case MONO_TYPE_CLASS:
3381 case MONO_TYPE_OBJECT:
3382 case MONO_TYPE_STRING:
3383 case MONO_TYPE_ARRAY:
3384 case MONO_TYPE_SZARRAY:
3385 mono_mb_emit_byte (mb, CEE_STLOC_3);
3387 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
3389 mono_mb_emit_byte (mb, CEE_CALL);
3390 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
3392 mono_mb_emit_byte (mb, CEE_LDLOC_3);
3394 mono_mb_emit_byte (mb, CEE_CALLVIRT);
3395 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_native_to_managed));
3397 mono_mb_emit_byte (mb, CEE_STLOC_3);
3400 g_warning ("custom marshalling of type %x is currently not supported", type);
3401 g_assert_not_reached ();
3408 case MONO_TYPE_VOID:
3423 /* no conversions necessary */
3424 mono_mb_emit_byte (mb, CEE_STLOC_3);
3426 case MONO_TYPE_BOOLEAN:
3427 /* maybe we need to make sure that it fits within 8 bits */
3428 mono_mb_emit_byte (mb, CEE_STLOC_3);
3430 case MONO_TYPE_VALUETYPE:
3431 klass = sig->ret->data.klass;
3432 if (klass->enumtype) {
3433 type = sig->ret->data.klass->enum_basetype->type;
3437 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3439 mono_mb_emit_byte (mb, CEE_STLOC_3);
3442 /* load pointer to returned value type */
3443 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3444 mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
3445 /* store the address of the source into local variable 0 */
3446 mono_mb_emit_byte (mb, CEE_STLOC_0);
3448 mono_mb_emit_ldloc_addr (mb, 3);
3449 mono_mb_emit_byte (mb, CEE_STLOC_1);
3451 /* emit valuetype conversion code */
3452 emit_struct_conv (mb, sig->ret->data.klass, TRUE);
3454 case MONO_TYPE_STRING:
3455 #ifdef GTK_SHARP_FIXED
3456 mono_mb_emit_byte (mb, CEE_STLOC_0);
3457 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3460 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3461 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3463 switch (spec->native) {
3464 case MONO_NATIVE_LPWSTR:
3465 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPWSTR_STR);
3468 g_warning ("marshalling conversion not implemented");
3469 g_assert_not_reached ();
3472 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
3474 mono_mb_emit_byte (mb, CEE_STLOC_3);
3476 #ifdef GTK_SHARP_FIXED
3477 /* free the string */
3478 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3479 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3480 mono_mb_emit_byte (mb, CEE_MONO_FREE);
3483 case MONO_TYPE_CLASS:
3484 case MONO_TYPE_OBJECT:
3485 klass = sig->ret->data.klass;
3488 mono_mb_emit_byte (mb, CEE_STLOC_0);
3490 mono_mb_emit_byte (mb, CEE_LDNULL);
3491 mono_mb_emit_byte (mb, CEE_STLOC_3);
3494 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3495 mono_mb_emit_byte (mb, CEE_BRFALSE);
3497 mono_mb_emit_i4 (mb, 0);
3499 /* allocate result object */
3501 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3502 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
3503 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3504 mono_mb_emit_byte (mb, CEE_STLOC_3);
3508 mono_mb_emit_byte (mb, CEE_LDLOC_3);
3509 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3510 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
3511 mono_mb_emit_icon (mb, sizeof (MonoObject));
3512 mono_mb_emit_byte (mb, CEE_ADD);
3513 mono_mb_emit_byte (mb, CEE_STLOC_1);
3515 /* emit conversion code */
3516 emit_struct_conv (mb, klass, TRUE);
3518 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3520 case MONO_TYPE_ARRAY:
3521 case MONO_TYPE_SZARRAY:
3522 /* fixme: we need conversions here */
3523 mono_mb_emit_byte (mb, CEE_STLOC_3);
3525 case MONO_TYPE_CHAR:
3526 /* fixme: we need conversions here */
3527 mono_mb_emit_byte (mb, CEE_STLOC_3);
3529 case MONO_TYPE_TYPEDBYREF:
3530 case MONO_TYPE_FNPTR:
3532 g_warning ("return type 0x%02x unknown", sig->ret->type);
3533 g_assert_not_reached ();
3537 mono_mb_emit_byte (mb, CEE_STLOC_3);
3540 /* we need to convert byref arguments back and free string arrays */
3541 for (i = 0; i < sig->param_count; i++) {
3542 MonoType *t = sig->params [i];
3544 argnum = i + sig->hasthis;
3547 case MONO_TYPE_STRING:
3548 if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT)) {
3549 mono_mb_emit_ldarg (mb, argnum);
3550 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3551 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3552 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3553 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
3554 mono_mb_emit_byte (mb, CEE_STIND_I);
3556 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3557 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3558 mono_mb_emit_byte (mb, CEE_MONO_FREE);
3561 case MONO_TYPE_CLASS:
3562 case MONO_TYPE_OBJECT:
3563 if (t->data.klass == mono_defaults.stringbuilder_class) {
3564 g_assert (!t->byref);
3565 mono_mb_emit_ldarg (mb, argnum);
3566 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3567 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3568 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
3569 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_SB);
3570 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3571 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3572 mono_mb_emit_byte (mb, CEE_MONO_FREE);
3576 if (!(t->byref || (t->attrs & PARAM_ATTRIBUTE_OUT)))
3579 if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT)) {
3580 /* allocate a new object new object */
3581 mono_mb_emit_ldarg (mb, argnum);
3582 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3583 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
3584 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3585 mono_mb_emit_byte (mb, CEE_STIND_I);
3588 /* dst = *argument */
3589 mono_mb_emit_ldarg (mb, argnum);
3592 mono_mb_emit_byte (mb, CEE_LDIND_I);
3594 mono_mb_emit_byte (mb, CEE_STLOC_1);
3596 mono_mb_emit_byte (mb, CEE_LDLOC_1);
3597 mono_mb_emit_byte (mb, CEE_BRFALSE);
3599 mono_mb_emit_i4 (mb, 0);
3601 mono_mb_emit_byte (mb, CEE_LDLOC_1);
3602 mono_mb_emit_icon (mb, sizeof (MonoObject));
3603 mono_mb_emit_byte (mb, CEE_ADD);
3604 mono_mb_emit_byte (mb, CEE_STLOC_1);
3606 /* src = tmp_locals [i] */
3607 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3608 mono_mb_emit_byte (mb, CEE_STLOC_0);
3610 /* emit valuetype conversion code */
3611 emit_struct_conv (mb, klass, TRUE);
3613 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3615 case MONO_TYPE_VALUETYPE:
3619 klass = t->data.klass;
3620 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3621 klass->blittable || klass->enumtype)
3624 /* dst = argument */
3625 mono_mb_emit_ldarg (mb, argnum);
3626 mono_mb_emit_byte (mb, CEE_STLOC_1);
3628 mono_mb_emit_byte (mb, CEE_LDLOC_1);
3629 mono_mb_emit_byte (mb, CEE_BRFALSE);
3631 mono_mb_emit_i4 (mb, 0);
3633 /* src = tmp_locals [i] */
3634 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3635 mono_mb_emit_byte (mb, CEE_STLOC_0);
3637 /* emit valuetype conversion code */
3638 emit_struct_conv (mb, klass, TRUE);
3640 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3642 case MONO_TYPE_SZARRAY:
3646 klass = mono_class_from_mono_type (t);
3648 if (klass->element_class == mono_defaults.string_class) {
3649 g_assert (tmp_locals [i]);
3651 mono_mb_emit_ldarg (mb, argnum);
3652 mono_mb_emit_byte (mb, CEE_BRFALSE);
3654 mono_mb_emit_i4 (mb, 0);
3656 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3657 mono_mb_emit_ldarg (mb, argnum);
3658 mono_mb_emit_byte (mb, CEE_LDLEN);
3659 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3660 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
3661 mono_mb_emit_byte (mb, MONO_MARSHAL_FREE_ARRAY);
3663 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3666 if (t->attrs & PARAM_ATTRIBUTE_OUT) {
3667 /* FIXME: Optimize blittable case */
3669 guint32 label1, label2, label3;
3670 int index_var, src_ptr;
3672 eklass = klass->element_class;
3673 src_ptr = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3676 mono_mb_emit_ldarg (mb, argnum);
3677 mono_mb_emit_byte (mb, CEE_BRFALSE);
3679 mono_mb_emit_i4 (mb, 0);
3681 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3682 mono_mb_emit_stloc (mb, src_ptr);
3684 /* Emit marshalling loop */
3685 index_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3686 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
3687 mono_mb_emit_stloc (mb, index_var);
3689 mono_mb_emit_ldloc (mb, index_var);
3690 mono_mb_emit_ldarg (mb, argnum);
3691 mono_mb_emit_byte (mb, CEE_LDLEN);
3692 mono_mb_emit_byte (mb, CEE_BGE);
3694 mono_mb_emit_i4 (mb, 0);
3696 /* Emit marshalling code */
3698 /* set the src_ptr */
3699 mono_mb_emit_ldloc (mb, src_ptr);
3700 mono_mb_emit_byte (mb, CEE_STLOC_0);
3703 mono_mb_emit_ldarg (mb, argnum);
3704 mono_mb_emit_ldloc (mb, index_var);
3705 mono_mb_emit_byte (mb, CEE_LDELEMA);
3706 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eklass));
3707 mono_mb_emit_byte (mb, CEE_STLOC_1);
3709 /* emit valuetype conversion code */
3710 emit_struct_conv (mb, eklass, TRUE);
3712 mono_mb_emit_add_to_local (mb, index_var, 1);
3713 mono_mb_emit_add_to_local (mb, src_ptr, mono_class_native_size (eklass, NULL));
3715 mono_mb_emit_byte (mb, CEE_BR);
3716 mono_mb_emit_i4 (mb, label2 - (mb->pos + 4));
3718 mono_mb_patch_addr (mb, label1, mb->pos - (label1 + 4));
3719 mono_mb_patch_addr (mb, label3, mb->pos - (label3 + 4));
3722 case MONO_TYPE_BOOLEAN:
3725 mono_mb_emit_ldarg (mb, argnum);
3726 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3727 if (mspecs [i + 1] != NULL && mspecs [i + 1]->native == MONO_NATIVE_VARIANTBOOL)
3728 mono_mb_emit_byte (mb, CEE_NEG);
3729 mono_mb_emit_byte (mb, CEE_STIND_I1);
3733 if (!MONO_TYPE_IS_VOID(sig->ret))
3734 mono_mb_emit_byte (mb, CEE_LDLOC_3);
3736 mono_mb_emit_byte (mb, CEE_RET);
3738 csig = g_memdup (sig, sigsize);
3740 res = mono_mb_create_and_cache (cache, method,
3741 mb, csig, csig->param_count + 16);
3744 for (i = sig->param_count; i >= 0; i--)
3745 g_free (mspecs [i]);
3748 //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));
3754 * generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld)
3757 mono_marshal_get_struct_to_ptr (MonoClass *klass)
3759 MonoMethodBuilder *mb;
3760 static MonoMethod *stoptr = NULL;
3763 g_assert (klass != NULL);
3765 if (klass->str_to_ptr)
3766 return klass->str_to_ptr;
3769 stoptr = mono_find_method_by_name (mono_defaults.marshal_class, "StructureToPtr", 3);
3772 mb = mono_mb_new (klass, stoptr->name, MONO_WRAPPER_UNKNOWN);
3774 if (klass->blittable) {
3775 mono_mb_emit_byte (mb, CEE_LDARG_1);
3776 mono_mb_emit_byte (mb, CEE_LDARG_0);
3777 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3778 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
3779 mono_mb_emit_byte (mb, CEE_PREFIX1);
3780 mono_mb_emit_byte (mb, CEE_CPBLK);
3783 /* allocate local 0 (pointer) src_ptr */
3784 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3785 /* allocate local 1 (pointer) dst_ptr */
3786 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3787 /* allocate local 2 (boolean) delete_old */
3788 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
3789 mono_mb_emit_byte (mb, CEE_LDARG_2);
3790 mono_mb_emit_byte (mb, CEE_STLOC_2);
3792 /* initialize src_ptr to point to the start of object data */
3793 mono_mb_emit_byte (mb, CEE_LDARG_0);
3794 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3795 mono_mb_emit_byte (mb, CEE_STLOC_0);
3797 /* initialize dst_ptr */
3798 mono_mb_emit_byte (mb, CEE_LDARG_1);
3799 mono_mb_emit_byte (mb, CEE_STLOC_1);
3801 emit_struct_conv (mb, klass, FALSE);
3804 mono_mb_emit_byte (mb, CEE_RET);
3806 res = mono_mb_create_method (mb, stoptr->signature, 0);
3809 klass->str_to_ptr = res;
3814 * generates IL code for PtrToStructure (IntPtr src, object structure)
3817 mono_marshal_get_ptr_to_struct (MonoClass *klass)
3819 MonoMethodBuilder *mb;
3820 static MonoMethod *ptostr = NULL;
3823 g_assert (klass != NULL);
3825 if (klass->ptr_to_str)
3826 return klass->ptr_to_str;
3829 ptostr = mono_find_method_by_name (mono_defaults.marshal_class, "PtrToStructure", 2);
3832 mb = mono_mb_new (klass, ptostr->name, MONO_WRAPPER_UNKNOWN);
3834 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable) {
3835 mono_mb_emit_byte (mb, CEE_LDARG_1);
3836 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3837 mono_mb_emit_byte (mb, CEE_LDARG_0);
3838 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
3839 mono_mb_emit_byte (mb, CEE_PREFIX1);
3840 mono_mb_emit_byte (mb, CEE_CPBLK);
3843 /* allocate local 0 (pointer) src_ptr */
3844 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3845 /* allocate local 1 (pointer) dst_ptr */
3846 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3848 /* initialize src_ptr to point to the start of object data */
3849 mono_mb_emit_byte (mb, CEE_LDARG_0);
3850 mono_mb_emit_byte (mb, CEE_STLOC_0);
3852 /* initialize dst_ptr */
3853 mono_mb_emit_byte (mb, CEE_LDARG_1);
3854 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3855 mono_mb_emit_byte (mb, CEE_STLOC_1);
3857 emit_struct_conv (mb, klass, TRUE);
3860 mono_mb_emit_byte (mb, CEE_RET);
3862 res = mono_mb_create_method (mb, ptostr->signature, 0);
3865 klass->ptr_to_str = res;
3869 static MonoReflectionType *
3870 type_from_handle (MonoType *handle)
3872 MonoDomain *domain = mono_domain_get ();
3873 MonoClass *klass = mono_class_from_mono_type (handle);
3875 MONO_ARCH_SAVE_REGS;
3877 mono_class_init (klass);
3878 return mono_type_get_object (domain, handle);
3882 * generates IL code for the synchronized wrapper: the generated method
3883 * calls METHOD while locking 'this' or the parent type.
3886 mono_marshal_get_synchronized_wrapper (MonoMethod *method)
3888 static MonoMethodSignature *from_handle_sig = NULL;
3889 static MonoMethod *enter_method, *exit_method;
3890 MonoMethodSignature *sig;
3891 MonoExceptionClause *clause;
3892 MonoMethodHeader *header;
3893 MonoMethodBuilder *mb;
3896 int i, pos, this_local, ret_local;
3900 if (method->wrapper_type == MONO_WRAPPER_SYNCHRONIZED)
3903 cache = method->klass->image->synchronized_cache;
3904 if ((res = mono_marshal_find_in_cache (cache, method)))
3907 sig = method->signature;
3909 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_SYNCHRONIZED);
3912 if (!MONO_TYPE_IS_VOID (sig->ret))
3913 ret_local = mono_mb_add_local (mb, sig->ret);
3916 this_local = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
3918 clause = g_new0 (MonoExceptionClause, 1);
3919 clause->flags = MONO_EXCEPTION_CLAUSE_FINALLY;
3921 if (!enter_method) {
3922 MonoMethodDesc *desc;
3924 desc = mono_method_desc_new ("Monitor:Enter", FALSE);
3925 enter_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
3926 g_assert (enter_method);
3927 mono_method_desc_free (desc);
3928 desc = mono_method_desc_new ("Monitor:Exit", FALSE);
3929 exit_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
3930 g_assert (exit_method);
3931 mono_method_desc_free (desc);
3934 * GetTypeFromHandle isn't called as a managed method because it has
3935 * a funky calling sequence, e.g. ldtoken+GetTypeFromHandle gets
3936 * transformed into something else by the JIT.
3938 from_handle_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
3939 from_handle_sig->params [0] = &mono_defaults.object_class->byval_arg;
3940 from_handle_sig->ret = &mono_defaults.object_class->byval_arg;
3943 /* Push this or the type object */
3944 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3945 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3946 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
3947 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, &method->klass->byval_arg));
3948 mono_mb_emit_native_call (mb, from_handle_sig, type_from_handle);
3951 mono_mb_emit_ldarg (mb, 0);
3952 mono_mb_emit_stloc (mb, this_local);
3954 /* Call Monitor::Enter() */
3955 mono_mb_emit_ldloc (mb, this_local);
3956 mono_mb_emit_managed_call (mb, enter_method, NULL);
3958 clause->try_offset = mb->pos;
3960 /* Call the method */
3962 mono_mb_emit_ldarg (mb, 0);
3963 for (i = 0; i < sig->param_count; i++)
3964 mono_mb_emit_ldarg (mb, i + (sig->hasthis == TRUE));
3965 mono_mb_emit_managed_call (mb, method, method->signature);
3966 if (!MONO_TYPE_IS_VOID (sig->ret))
3967 mono_mb_emit_stloc (mb, ret_local);
3969 mono_mb_emit_byte (mb, CEE_LEAVE);
3971 mono_mb_emit_i4 (mb, 0);
3973 clause->try_len = mb->pos - clause->try_offset;
3974 clause->handler_offset = mb->pos;
3976 /* Call Monitor::Exit() */
3977 mono_mb_emit_ldloc (mb, this_local);
3978 // mono_mb_emit_native_call (mb, exit_sig, mono_monitor_exit);
3979 mono_mb_emit_managed_call (mb, exit_method, NULL);
3980 mono_mb_emit_byte (mb, CEE_ENDFINALLY);
3982 clause->handler_len = mb->pos - clause->handler_offset;
3984 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3985 if (!MONO_TYPE_IS_VOID (sig->ret))
3986 mono_mb_emit_ldloc (mb, ret_local);
3987 mono_mb_emit_byte (mb, CEE_RET);
3989 res = mono_mb_create_and_cache (cache, method,
3990 mb, sig, sig->param_count + 16);
3993 header = ((MonoMethodNormal *)res)->header;
3994 header->num_clauses = 1;
3995 header->clauses = clause;
4000 /* FIXME: on win32 we should probably use GlobalAlloc(). */
4002 mono_marshal_alloc (gpointer size)
4004 MONO_ARCH_SAVE_REGS;
4006 return g_try_malloc ((gulong)size);
4010 mono_marshal_free (gpointer ptr)
4012 MONO_ARCH_SAVE_REGS;
4018 mono_marshal_free_array (gpointer *ptr, int size)
4025 for (i = 0; i < size; i++)
4031 mono_marshal_realloc (gpointer ptr, gpointer size)
4033 MONO_ARCH_SAVE_REGS;
4035 return g_try_realloc (ptr, (gulong)size);
4039 mono_marshal_string_array (MonoArray *array)
4047 len = mono_array_length (array);
4049 result = g_malloc (sizeof (char *) * (len + 1));
4050 for (i = 0; i < len; ++i) {
4051 MonoString *s = (MonoString *)mono_array_get (array, gpointer, i);
4052 result [i] = s ? mono_string_to_utf8 (s): NULL;
4054 /* null terminate the array */
4061 mono_marshal_set_last_error (void)
4064 TlsSetValue (last_error_tls_id, (gpointer)GetLastError ());
4066 TlsSetValue (last_error_tls_id, (gpointer)errno);
4071 ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArray *src, gint32 start_index,
4072 gpointer dest, gint32 length)
4077 MONO_ARCH_SAVE_REGS;
4079 MONO_CHECK_ARG_NULL (src);
4080 MONO_CHECK_ARG_NULL (dest);
4082 g_assert (src->obj.vtable->klass->rank == 1);
4083 g_assert (start_index >= 0);
4084 g_assert (length >= 0);
4085 g_assert (start_index + length <= mono_array_length (src));
4087 element_size = mono_array_element_size (src->obj.vtable->klass);
4089 source_addr = mono_array_addr_with_size (src, element_size, start_index);
4091 memcpy (dest, source_addr, length * element_size);
4095 ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer src, gint32 start_index,
4096 MonoArray *dest, gint32 length)
4101 MONO_ARCH_SAVE_REGS;
4103 MONO_CHECK_ARG_NULL (src);
4104 MONO_CHECK_ARG_NULL (dest);
4106 g_assert (dest->obj.vtable->klass->rank == 1);
4107 g_assert (start_index >= 0);
4108 g_assert (length >= 0);
4109 g_assert (start_index + length <= mono_array_length (dest));
4111 element_size = mono_array_element_size (dest->obj.vtable->klass);
4113 dest_addr = mono_array_addr_with_size (dest, element_size, start_index);
4115 memcpy (dest_addr, src, length * element_size);
4119 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr, gint32 offset)
4123 MONO_ARCH_SAVE_REGS;
4125 return *(gpointer*)(p + offset);
4129 ves_icall_System_Runtime_InteropServices_Marshal_ReadByte (gpointer ptr, gint32 offset)
4133 MONO_ARCH_SAVE_REGS;
4135 return *(unsigned char*)(p + offset);
4139 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt16 (gpointer ptr, gint32 offset)
4143 MONO_ARCH_SAVE_REGS;
4145 return *(gint16*)(p + offset);
4149 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt32 (gpointer ptr, gint32 offset)
4153 MONO_ARCH_SAVE_REGS;
4155 return *(gint32*)(p + offset);
4159 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt64 (gpointer ptr, gint32 offset)
4163 MONO_ARCH_SAVE_REGS;
4165 return *(gint64*)(p + offset);
4169 ves_icall_System_Runtime_InteropServices_Marshal_WriteByte (gpointer ptr, gint32 offset, unsigned char val)
4173 MONO_ARCH_SAVE_REGS;
4175 *(unsigned char*)(p + offset) = val;
4179 ves_icall_System_Runtime_InteropServices_Marshal_WriteIntPtr (gpointer ptr, gint32 offset, gpointer val)
4183 MONO_ARCH_SAVE_REGS;
4185 *(gpointer*)(p + offset) = val;
4189 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt16 (gpointer ptr, gint32 offset, gint16 val)
4193 MONO_ARCH_SAVE_REGS;
4195 *(gint16*)(p + offset) = val;
4199 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt32 (gpointer ptr, gint32 offset, gint32 val)
4203 MONO_ARCH_SAVE_REGS;
4205 *(gint32*)(p + offset) = val;
4209 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt64 (gpointer ptr, gint32 offset, gint64 val)
4213 MONO_ARCH_SAVE_REGS;
4215 *(gint64*)(p + offset) = val;
4219 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (char *ptr)
4221 MONO_ARCH_SAVE_REGS;
4223 return mono_string_new (mono_domain_get (), ptr);
4227 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len (char *ptr, gint32 len)
4229 MONO_ARCH_SAVE_REGS;
4231 return mono_string_new_len (mono_domain_get (), ptr, len);
4235 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni (guint16 *ptr)
4237 MonoDomain *domain = mono_domain_get ();
4241 MONO_ARCH_SAVE_REGS;
4246 return mono_string_new_utf16 (domain, ptr, len);
4250 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len (guint16 *ptr, gint32 len)
4252 MonoDomain *domain = mono_domain_get ();
4254 MONO_ARCH_SAVE_REGS;
4256 return mono_string_new_utf16 (domain, ptr, len);
4260 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR (gpointer ptr)
4262 MONO_ARCH_SAVE_REGS;
4264 g_warning ("PtrToStringBSTR not implemented");
4265 g_assert_not_reached ();
4271 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
4273 MONO_ARCH_SAVE_REGS;
4275 return ((guint32)TlsGetValue (last_error_tls_id));
4279 ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype)
4283 MONO_ARCH_SAVE_REGS;
4285 MONO_CHECK_ARG_NULL (rtype);
4287 klass = mono_class_from_mono_type (rtype->type);
4289 return mono_class_native_size (klass, NULL);
4293 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old)
4298 MONO_ARCH_SAVE_REGS;
4300 MONO_CHECK_ARG_NULL (obj);
4301 MONO_CHECK_ARG_NULL (dst);
4303 method = mono_marshal_get_struct_to_ptr (obj->vtable->klass);
4307 pa [2] = &delete_old;
4309 mono_runtime_invoke (method, NULL, pa, NULL);
4313 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, MonoObject *dst)
4318 MONO_ARCH_SAVE_REGS;
4320 MONO_CHECK_ARG_NULL (src);
4321 MONO_CHECK_ARG_NULL (dst);
4323 method = mono_marshal_get_ptr_to_struct (dst->vtable->klass);
4328 mono_runtime_invoke (method, NULL, pa, NULL);
4332 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer src, MonoReflectionType *type)
4334 MonoDomain *domain = mono_domain_get ();
4337 MONO_ARCH_SAVE_REGS;
4339 MONO_CHECK_ARG_NULL (src);
4340 MONO_CHECK_ARG_NULL (type);
4342 res = mono_object_new (domain, mono_class_from_mono_type (type->type));
4344 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (src, res);
4350 ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *type, MonoString *field_name)
4352 MonoMarshalType *info;
4355 int i, match_index = -1;
4357 MONO_ARCH_SAVE_REGS;
4359 MONO_CHECK_ARG_NULL (type);
4360 MONO_CHECK_ARG_NULL (field_name);
4362 fname = mono_string_to_utf8 (field_name);
4363 klass = mono_class_from_mono_type (type->type);
4365 while(klass && match_index == -1) {
4366 for (i = 0; i < klass->field.count; ++i) {
4367 if (*fname == *klass->fields [i].name && strcmp (fname, klass->fields [i].name) == 0) {
4373 if(match_index == -1)
4374 klass = klass->parent;
4379 if(match_index == -1) {
4383 /* Get back original class instance */
4384 klass = mono_class_from_mono_type (type->type);
4386 tmp = g_strdup_printf ("Field passed in is not a marshaled member of the type %s", klass->name);
4387 exc = mono_get_exception_argument ("fieldName", tmp);
4390 mono_raise_exception ((MonoException*)exc);
4393 info = mono_marshal_load_type_info (klass);
4394 return info->fields [match_index].offset;
4398 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString *string)
4400 MONO_ARCH_SAVE_REGS;
4402 return mono_string_to_utf8 (string);
4406 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni (MonoString *string)
4408 MONO_ARCH_SAVE_REGS;
4410 return g_memdup (mono_string_chars (string), mono_string_length (string)*2);
4414 mono_struct_delete_old (MonoClass *klass, char *ptr)
4416 MonoMarshalType *info;
4419 info = mono_marshal_load_type_info (klass);
4421 for (i = 0; i < info->num_fields; i++) {
4422 MonoMarshalNative ntype;
4423 MonoMarshalConv conv;
4424 MonoType *ftype = info->fields [i].field->type;
4427 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
4430 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE,
4431 klass->unicode, &conv);
4433 cpos = ptr + info->fields [i].offset;
4436 case MONO_MARSHAL_CONV_NONE:
4437 if (MONO_TYPE_ISSTRUCT (ftype)) {
4438 mono_struct_delete_old (ftype->data.klass, cpos);
4442 case MONO_MARSHAL_CONV_STR_LPWSTR:
4443 case MONO_MARSHAL_CONV_STR_LPSTR:
4444 case MONO_MARSHAL_CONV_STR_LPTSTR:
4445 case MONO_MARSHAL_CONV_STR_BSTR:
4446 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
4447 case MONO_MARSHAL_CONV_STR_TBSTR:
4448 g_free (*(gpointer *)cpos);
4457 ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure (gpointer src, MonoReflectionType *type)
4461 MONO_ARCH_SAVE_REGS;
4463 MONO_CHECK_ARG_NULL (src);
4464 MONO_CHECK_ARG_NULL (type);
4466 klass = mono_class_from_mono_type (type->type);
4468 mono_struct_delete_old (klass, (char *)src);
4472 mono_marshal_load_type_info (MonoClass* klass)
4474 int i, j, count = 0, native_size = 0;
4475 MonoMarshalType *info;
4478 g_assert (klass != NULL);
4480 if (klass->marshal_info)
4481 return klass->marshal_info;
4484 mono_class_init (klass);
4486 for (i = 0; i < klass->field.count; ++i) {
4487 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
4489 if (mono_field_is_deleted (&klass->fields [i]))
4494 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
4496 klass->marshal_info = info = g_malloc0 (sizeof (MonoMarshalType) + sizeof (MonoMarshalField) * count);
4497 info->num_fields = count;
4499 /* Try to find a size for this type in metadata */
4500 mono_metadata_packing_from_typedef (klass->image, klass->type_token, NULL, &native_size);
4502 if (klass->parent) {
4503 int parent_size = mono_class_native_size (klass->parent, NULL);
4505 /* Add parent size to real size */
4506 native_size += parent_size;
4507 info->native_size = parent_size;
4510 for (j = i = 0; i < klass->field.count; ++i) {
4513 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
4516 if (mono_field_is_deleted (&klass->fields [i]))
4518 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL)
4519 mono_metadata_field_info (klass->image, klass->field.first + i,
4520 NULL, NULL, &info->fields [j].mspec);
4522 info->fields [j].field = &klass->fields [i];
4524 if ((klass->field.count == 1) && (klass->instance_size == sizeof (MonoObject)) &&
4525 (strcmp (klass->fields [i].name, "$PRIVATE$") == 0)) {
4526 /* This field is a hack inserted by MCS to empty structures */
4531 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
4532 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
4533 size = mono_marshal_type_size (klass->fields [i].type, info->fields [j].mspec,
4534 &align, TRUE, klass->unicode);
4535 align = klass->packing_size ? MIN (klass->packing_size, align): align;
4536 info->fields [j].offset = info->native_size;
4537 info->fields [j].offset += align - 1;
4538 info->fields [j].offset &= ~(align - 1);
4539 info->native_size = info->fields [j].offset + size;
4541 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
4543 info->fields [j].offset = klass->fields [i].offset - sizeof (MonoObject);
4544 info->native_size = klass->instance_size - sizeof (MonoObject);
4550 if(layout != TYPE_ATTRIBUTE_AUTO_LAYOUT) {
4551 info->native_size = MAX (native_size, info->native_size);
4554 if (info->native_size & (klass->min_align - 1)) {
4555 info->native_size += klass->min_align - 1;
4556 info->native_size &= ~(klass->min_align - 1);
4559 return klass->marshal_info;
4563 * mono_class_native_size:
4566 * Returns: the native size of an object instance (when marshaled
4567 * to unmanaged code)
4570 mono_class_native_size (MonoClass *klass, guint32 *align)
4573 if (!klass->marshal_info)
4574 mono_marshal_load_type_info (klass);
4577 *align = klass->min_align;
4579 return klass->marshal_info->native_size;
4583 * mono_type_native_stack_size:
4584 * @t: the type to return the size it uses on the stack
4586 * Returns: the number of bytes required to hold an instance of this
4587 * type on the native stack
4590 mono_type_native_stack_size (MonoType *t, gint *align)
4594 g_assert (t != NULL);
4605 case MONO_TYPE_BOOLEAN:
4606 case MONO_TYPE_CHAR:
4615 case MONO_TYPE_STRING:
4616 case MONO_TYPE_OBJECT:
4617 case MONO_TYPE_CLASS:
4618 case MONO_TYPE_SZARRAY:
4620 case MONO_TYPE_FNPTR:
4621 case MONO_TYPE_ARRAY:
4622 case MONO_TYPE_TYPEDBYREF:
4633 case MONO_TYPE_VALUETYPE: {
4636 if (t->data.klass->enumtype)
4637 return mono_type_native_stack_size (t->data.klass->enum_basetype, align);
4639 size = mono_class_native_size (t->data.klass, align);
4640 *align = *align + 3;
4650 g_error ("type 0x%02x unknown", t->type);
4655 /* __alignof__ returns the preferred alignment of values not the actual alignment used by
4656 the compiler so is wrong e.g. for Linux where doubles are aligned on a 4 byte boundary
4657 but __alignof__ returns 8 - using G_STRUCT_OFFSET works better */
4658 #define ALIGNMENT(type) G_STRUCT_OFFSET(struct { char c; type x; }, x)
4661 mono_marshal_type_size (MonoType *type, MonoMarshalSpec *mspec, gint32 *align,
4662 gboolean as_field, gboolean unicode)
4664 MonoMarshalNative native_type = mono_type_to_unmanaged (type, mspec, as_field, unicode, NULL);
4667 switch (native_type) {
4668 case MONO_NATIVE_BOOLEAN:
4671 case MONO_NATIVE_I1:
4672 case MONO_NATIVE_U1:
4675 case MONO_NATIVE_I2:
4676 case MONO_NATIVE_U2:
4677 case MONO_NATIVE_VARIANTBOOL:
4680 case MONO_NATIVE_I4:
4681 case MONO_NATIVE_U4:
4682 case MONO_NATIVE_ERROR:
4685 case MONO_NATIVE_I8:
4686 case MONO_NATIVE_U8:
4687 *align = ALIGNMENT(guint64);
4689 case MONO_NATIVE_R4:
4692 case MONO_NATIVE_R8:
4693 *align = ALIGNMENT(double);
4695 case MONO_NATIVE_INT:
4696 case MONO_NATIVE_UINT:
4697 case MONO_NATIVE_LPSTR:
4698 case MONO_NATIVE_LPWSTR:
4699 case MONO_NATIVE_LPTSTR:
4700 case MONO_NATIVE_BSTR:
4701 case MONO_NATIVE_ANSIBSTR:
4702 case MONO_NATIVE_TBSTR:
4703 case MONO_NATIVE_LPARRAY:
4704 case MONO_NATIVE_SAFEARRAY:
4705 case MONO_NATIVE_IUNKNOWN:
4706 case MONO_NATIVE_IDISPATCH:
4707 case MONO_NATIVE_INTERFACE:
4708 case MONO_NATIVE_ASANY:
4709 case MONO_NATIVE_FUNC:
4710 case MONO_NATIVE_LPSTRUCT:
4711 *align = ALIGNMENT(gpointer);
4712 return sizeof (gpointer);
4713 case MONO_NATIVE_STRUCT:
4714 klass = mono_class_from_mono_type (type);
4715 return mono_class_native_size (klass, align);
4716 case MONO_NATIVE_BYVALTSTR: {
4717 int esize = unicode ? 2: 1;
4720 return mspec->data.array_data.num_elem * esize;
4722 case MONO_NATIVE_BYVALARRAY: {
4724 klass = mono_class_from_mono_type (type);
4725 esize = mono_class_native_size (klass->element_class, align);
4727 return mspec->data.array_data.num_elem * esize;
4729 case MONO_NATIVE_CUSTOM:
4730 g_assert_not_reached ();
4732 case MONO_NATIVE_CURRENCY:
4733 case MONO_NATIVE_VBBYREFSTR:
4735 g_error ("native type %02x not implemented", native_type);
4738 g_assert_not_reached ();