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 > mono_stringbuilder_capacity (sb))
172 items_written = mono_stringbuilder_capacity (sb);
175 memcpy (mono_string_chars (sb->str), ut, items_written * 2);
176 sb->length = items_written;
178 g_error_free (error);
184 mono_string_builder_to_utf8 (MonoStringBuilder *sb)
186 GError *error = NULL;
192 res = g_malloc0 (mono_stringbuilder_capacity (sb) + 1);
194 g_utf16_to_utf8 (mono_string_chars (sb->str), sb->length, NULL, res, &error);
196 g_error_free (error);
197 mono_raise_exception (mono_get_exception_execution_engine ("Failed to convert StringBuilder from utf16 to utf8"));
204 mono_string_to_ansibstr (MonoString *string_obj)
206 g_error ("implement me");
211 mono_string_to_bstr (MonoString *string_obj)
213 g_error ("implement me");
218 mono_string_to_byvalstr (gpointer dst, MonoString *src, int size)
223 g_assert (dst != NULL);
226 memset (dst, 0, size);
231 s = mono_string_to_utf8 (src);
232 len = MIN (size, strlen (s));
233 memcpy (dst, s, len);
236 *((char *)dst + size - 1) = 0;
240 mono_string_to_byvalwstr (gpointer dst, MonoString *src, int size)
244 g_assert (dst != NULL);
248 memset (dst, 0, size);
252 len = MIN (size, (mono_string_length (src) * 2));
253 memcpy (dst, mono_string_chars (src), len);
255 *((char *)dst + size - 1) = 0;
256 *((char *)dst + size - 2) = 0;
260 mono_mb_free (MonoMethodBuilder *mb)
262 g_list_free (mb->locals_list);
267 mono_mb_new (MonoClass *klass, const char *name, MonoWrapperType type)
269 MonoMethodBuilder *mb;
272 g_assert (klass != NULL);
273 g_assert (name != NULL);
275 mb = g_new0 (MonoMethodBuilder, 1);
277 mb->method = m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
280 m->name = g_strdup (name);
282 m->inline_count = -1;
283 m->wrapper_type = type;
286 mb->code = g_malloc (mb->code_size);
292 mono_mb_add_local (MonoMethodBuilder *mb, MonoType *type)
294 int res = mb->locals;
296 g_assert (mb != NULL);
297 g_assert (type != NULL);
299 mb->locals_list = g_list_append (mb->locals_list, type);
306 mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack)
308 MonoMethodHeader *header;
312 g_assert (mb != NULL);
314 ((MonoMethodNormal *)mb->method)->header = header = (MonoMethodHeader *)
315 g_malloc0 (sizeof (MonoMethodHeader) + mb->locals * sizeof (MonoType *));
320 header->max_stack = max_stack;
322 for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
323 header->locals [i] = (MonoType *)l->data;
326 mb->method->signature = signature;
327 header->code = mb->code;
328 header->code_size = mb->pos;
329 header->num_locals = mb->locals;
331 #ifdef DEBUG_RUNTIME_CODE
332 printf ("RUNTIME CODE FOR %s\n", mono_method_full_name (mb->method, TRUE));
333 printf ("%s\n", mono_disasm_code (&marshal_dh, mb->method, mb->code, mb->code + mb->pos));
340 mono_mb_add_data (MonoMethodBuilder *mb, gpointer data)
342 MonoMethodWrapper *mw;
344 g_assert (mb != NULL);
346 mw = (MonoMethodWrapper *)mb->method;
348 mw->data = g_list_append (mw->data, data);
350 return g_list_length (mw->data);
354 mono_mb_patch_addr (MonoMethodBuilder *mb, int pos, int value)
356 mb->code [pos] = value & 0xff;
357 mb->code [pos + 1] = (value >> 8) & 0xff;
358 mb->code [pos + 2] = (value >> 16) & 0xff;
359 mb->code [pos + 3] = (value >> 24) & 0xff;
363 mono_mb_patch_addr_s (MonoMethodBuilder *mb, int pos, gint8 value)
365 *((gint8 *)(&mb->code [pos])) = value;
369 mono_mb_emit_byte (MonoMethodBuilder *mb, guint8 op)
371 if (mb->pos >= mb->code_size) {
373 mb->code = g_realloc (mb->code, mb->code_size);
376 mb->code [mb->pos++] = op;
380 mono_mb_emit_ldflda (MonoMethodBuilder *mb, gint32 offset)
382 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
383 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
386 mono_mb_emit_icon (mb, offset);
387 mono_mb_emit_byte (mb, CEE_ADD);
392 mono_mb_emit_proxy_check (MonoMethodBuilder *mb, int branch_code)
395 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoObject, vtable));
396 mono_mb_emit_byte (mb, CEE_LDIND_I);
397 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoVTable, klass));
398 mono_mb_emit_byte (mb, CEE_ADD);
399 mono_mb_emit_byte (mb, CEE_LDIND_I);
400 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
401 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
402 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_defaults.transparent_proxy_class));
403 mono_mb_emit_byte (mb, branch_code);
405 mono_mb_emit_i4 (mb, 0);
410 mono_mb_emit_i4 (MonoMethodBuilder *mb, gint32 data)
412 if ((mb->pos + 4) >= mb->code_size) {
414 mb->code = g_realloc (mb->code, mb->code_size);
417 mono_mb_patch_addr (mb, mb->pos, data);
422 mono_mb_emit_i2 (MonoMethodBuilder *mb, gint16 data)
424 if ((mb->pos + 2) >= mb->code_size) {
426 mb->code = g_realloc (mb->code, mb->code_size);
429 mb->code [mb->pos] = data & 0xff;
430 mb->code [mb->pos + 1] = (data >> 8) & 0xff;
435 mono_mb_emit_ldstr (MonoMethodBuilder *mb, char *str)
437 mono_mb_emit_byte (mb, CEE_LDSTR);
438 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, str));
443 mono_mb_emit_ldarg (MonoMethodBuilder *mb, guint argnum)
446 mono_mb_emit_byte (mb, CEE_LDARG_0 + argnum);
447 } else if (argnum < 256) {
448 mono_mb_emit_byte (mb, CEE_LDARG_S);
449 mono_mb_emit_byte (mb, argnum);
451 mono_mb_emit_byte (mb, CEE_PREFIX1);
452 mono_mb_emit_byte (mb, CEE_LDARG);
453 mono_mb_emit_i2 (mb, argnum);
458 mono_mb_emit_ldarg_addr (MonoMethodBuilder *mb, guint argnum)
461 mono_mb_emit_byte (mb, CEE_LDARGA_S);
462 mono_mb_emit_byte (mb, argnum);
464 mono_mb_emit_byte (mb, CEE_PREFIX1);
465 mono_mb_emit_byte (mb, CEE_LDARGA);
466 mono_mb_emit_i2 (mb, argnum);
471 mono_mb_emit_ldloc_addr (MonoMethodBuilder *mb, guint locnum)
474 mono_mb_emit_byte (mb, CEE_LDLOCA_S);
475 mono_mb_emit_byte (mb, locnum);
477 mono_mb_emit_byte (mb, CEE_PREFIX1);
478 mono_mb_emit_byte (mb, CEE_LDLOCA);
479 mono_mb_emit_i2 (mb, locnum);
484 mono_mb_emit_ldloc (MonoMethodBuilder *mb, guint num)
487 mono_mb_emit_byte (mb, CEE_LDLOC_0 + num);
488 } else if (num < 256) {
489 mono_mb_emit_byte (mb, CEE_LDLOC_S);
490 mono_mb_emit_byte (mb, num);
492 mono_mb_emit_byte (mb, CEE_PREFIX1);
493 mono_mb_emit_byte (mb, CEE_LDLOC);
494 mono_mb_emit_i2 (mb, num);
499 mono_mb_emit_stloc (MonoMethodBuilder *mb, guint num)
502 mono_mb_emit_byte (mb, CEE_STLOC_0 + num);
503 } else if (num < 256) {
504 mono_mb_emit_byte (mb, CEE_STLOC_S);
505 mono_mb_emit_byte (mb, num);
507 mono_mb_emit_byte (mb, CEE_PREFIX1);
508 mono_mb_emit_byte (mb, CEE_STLOC);
509 mono_mb_emit_i2 (mb, num);
514 mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value)
516 if (value >= -1 && value < 8) {
517 mono_mb_emit_byte (mb, CEE_LDC_I4_0 + value);
518 } else if (value >= -128 && value <= 127) {
519 mono_mb_emit_byte (mb, CEE_LDC_I4_S);
520 mono_mb_emit_byte (mb, value);
522 mono_mb_emit_byte (mb, CEE_LDC_I4);
523 mono_mb_emit_i4 (mb, value);
528 mono_mb_emit_branch (MonoMethodBuilder *mb, guint8 op)
531 mono_mb_emit_byte (mb, op);
533 mono_mb_emit_i4 (mb, 0);
538 mono_mb_emit_managed_call (MonoMethodBuilder *mb, MonoMethod *method, MonoMethodSignature *opt_sig)
541 opt_sig = method->signature;
542 mono_mb_emit_byte (mb, CEE_PREFIX1);
543 mono_mb_emit_byte (mb, CEE_LDFTN);
544 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
545 mono_mb_emit_byte (mb, CEE_CALLI);
546 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, opt_sig));
550 mono_mb_emit_native_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, gpointer func)
552 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
553 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
554 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, func));
555 mono_mb_emit_byte (mb, CEE_CALLI);
556 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
560 mono_mb_emit_exception (MonoMethodBuilder *mb, const char *exc_name, const char *msg)
562 /* fixme: we need a better way to throw exception,
563 * supporting several exception types and messages */
564 MonoMethod *ctor = NULL;
566 MonoClass *mme = mono_class_from_name (mono_defaults.corlib, "System", exc_name);
568 mono_class_init (mme);
569 for (i = 0; i < mme->method.count; ++i) {
570 if (strcmp (mme->methods [i]->name, ".ctor") == 0 && mme->methods [i]->signature->param_count == 0) {
571 ctor = mme->methods [i];
576 mono_mb_emit_byte (mb, CEE_NEWOBJ);
577 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, ctor));
579 mono_mb_emit_byte (mb, CEE_DUP);
580 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoException, message));
581 mono_mb_emit_ldstr (mb, msg);
582 mono_mb_emit_byte (mb, CEE_STIND_I);
584 mono_mb_emit_byte (mb, CEE_THROW);
588 mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint16 local, gint32 incr)
590 mono_mb_emit_ldloc (mb, local);
591 mono_mb_emit_icon (mb, incr);
592 mono_mb_emit_byte (mb, CEE_ADD);
593 mono_mb_emit_stloc (mb, local);
597 emit_ptr_to_str_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv,
598 int usize, int msize, MonoMarshalSpec *mspec)
601 case MONO_MARSHAL_CONV_BOOL_I4:
602 mono_mb_emit_byte (mb, CEE_LDLOC_1);
603 mono_mb_emit_byte (mb, CEE_LDLOC_0);
604 mono_mb_emit_byte (mb, CEE_LDIND_I4);
605 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
606 mono_mb_emit_byte (mb, 3);
607 mono_mb_emit_byte (mb, CEE_LDC_I4_1);
608 mono_mb_emit_byte (mb, CEE_BR_S);
609 mono_mb_emit_byte (mb, 1);
610 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
611 mono_mb_emit_byte (mb, CEE_STIND_I1);
613 case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
614 mono_mb_emit_byte (mb, CEE_LDLOC_1);
615 mono_mb_emit_byte (mb, CEE_LDLOC_0);
616 mono_mb_emit_byte (mb, CEE_LDIND_I2);
617 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
618 mono_mb_emit_byte (mb, 3);
619 mono_mb_emit_byte (mb, CEE_LDC_I4_1);
620 mono_mb_emit_byte (mb, CEE_BR_S);
621 mono_mb_emit_byte (mb, 1);
622 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
623 mono_mb_emit_byte (mb, CEE_STIND_I1);
625 case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
629 if (type->type == MONO_TYPE_SZARRAY) {
630 eclass = type->data.klass;
632 g_assert_not_reached ();
635 if (eclass->valuetype)
636 esize = mono_class_instance_size (eclass) - sizeof (MonoObject);
638 esize = sizeof (gpointer);
640 /* create a new array */
641 mono_mb_emit_byte (mb, CEE_LDLOC_1);
642 mono_mb_emit_icon (mb, mspec->data.array_data.num_elem);
643 mono_mb_emit_byte (mb, CEE_NEWARR);
644 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eclass));
645 mono_mb_emit_byte (mb, CEE_STIND_I);
647 /* copy the elements */
648 mono_mb_emit_byte (mb, CEE_LDLOC_1);
649 mono_mb_emit_byte (mb, CEE_LDIND_I);
650 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
651 mono_mb_emit_byte (mb, CEE_ADD);
652 mono_mb_emit_byte (mb, CEE_LDLOC_0);
653 mono_mb_emit_icon (mb, mspec->data.array_data.num_elem * esize);
654 mono_mb_emit_byte (mb, CEE_PREFIX1);
655 mono_mb_emit_byte (mb, CEE_CPBLK);
659 case MONO_MARSHAL_CONV_STR_BYVALSTR:
660 mono_mb_emit_byte (mb, CEE_LDLOC_1);
661 mono_mb_emit_byte (mb, CEE_LDLOC_0);
662 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
663 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
664 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
665 mono_mb_emit_byte (mb, CEE_STIND_I);
667 case MONO_MARSHAL_CONV_STR_LPTSTR:
668 case MONO_MARSHAL_CONV_STR_LPSTR:
669 mono_mb_emit_byte (mb, CEE_LDLOC_1);
670 mono_mb_emit_byte (mb, CEE_LDLOC_0);
671 mono_mb_emit_byte (mb, CEE_LDIND_I);
672 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
673 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
674 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
675 mono_mb_emit_byte (mb, CEE_STIND_I);
677 case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
678 MonoClass *klass = mono_class_from_mono_type (type);
679 int src_var, dst_var;
681 src_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
682 dst_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
684 /* *dst = new object */
685 mono_mb_emit_byte (mb, CEE_LDLOC_1);
686 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
687 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
688 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
689 mono_mb_emit_byte (mb, CEE_STIND_I);
691 /* save the old src pointer */
692 mono_mb_emit_byte (mb, CEE_LDLOC_0);
693 mono_mb_emit_stloc (mb, src_var);
694 /* save the old dst pointer */
695 mono_mb_emit_byte (mb, CEE_LDLOC_1);
696 mono_mb_emit_stloc (mb, dst_var);
698 /* dst = pointer to newly created object data */
699 mono_mb_emit_byte (mb, CEE_LDLOC_1);
700 mono_mb_emit_byte (mb, CEE_LDIND_I);
701 mono_mb_emit_icon (mb, sizeof (MonoObject));
702 mono_mb_emit_byte (mb, CEE_ADD);
703 mono_mb_emit_byte (mb, CEE_STLOC_1);
705 emit_struct_conv (mb, klass, TRUE);
707 /* restore the old src pointer */
708 mono_mb_emit_ldloc (mb, src_var);
709 mono_mb_emit_byte (mb, CEE_STLOC_0);
710 /* restore the old dst pointer */
711 mono_mb_emit_ldloc (mb, dst_var);
712 mono_mb_emit_byte (mb, CEE_STLOC_1);
715 case MONO_MARSHAL_CONV_DEL_FTN: {
716 // fixme: we never convert functions back to delegates, dont
717 // know if thats the correct behaviour
720 case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
721 g_error ("Structure field of type %s can't be marshalled as LPArray", mono_class_from_mono_type (type)->name);
723 case MONO_MARSHAL_CONV_STR_LPWSTR:
724 case MONO_MARSHAL_CONV_STR_BSTR:
725 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
726 case MONO_MARSHAL_CONV_STR_TBSTR:
727 case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
728 case MONO_MARSHAL_CONV_STR_BYVALWSTR:
730 g_warning ("marshaling conversion %d not implemented", conv);
731 g_assert_not_reached ();
736 emit_str_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, int usize, int msize,
737 MonoMarshalSpec *mspec)
742 case MONO_MARSHAL_CONV_BOOL_I4:
743 mono_mb_emit_byte (mb, CEE_LDLOC_1);
744 mono_mb_emit_byte (mb, CEE_LDLOC_0);
745 mono_mb_emit_byte (mb, CEE_LDIND_U1);
746 mono_mb_emit_byte (mb, CEE_STIND_I4);
748 case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
749 mono_mb_emit_byte (mb, CEE_LDLOC_1);
750 mono_mb_emit_byte (mb, CEE_LDLOC_0);
751 mono_mb_emit_byte (mb, CEE_LDIND_U1);
752 mono_mb_emit_byte (mb, CEE_NEG);
753 mono_mb_emit_byte (mb, CEE_STIND_I2);
755 case MONO_MARSHAL_CONV_STR_LPWSTR:
756 case MONO_MARSHAL_CONV_STR_LPSTR:
757 case MONO_MARSHAL_CONV_STR_LPTSTR:
758 case MONO_MARSHAL_CONV_STR_BSTR:
759 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
760 case MONO_MARSHAL_CONV_STR_TBSTR:
761 /* free space if free == true */
762 mono_mb_emit_byte (mb, CEE_LDLOC_2);
763 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
764 mono_mb_emit_byte (mb, 4);
765 mono_mb_emit_byte (mb, CEE_LDLOC_1);
766 mono_mb_emit_byte (mb, CEE_LDIND_I);
767 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
768 mono_mb_emit_byte (mb, CEE_MONO_FREE);
770 mono_mb_emit_byte (mb, CEE_LDLOC_1);
771 mono_mb_emit_byte (mb, CEE_LDLOC_0);
772 mono_mb_emit_byte (mb, CEE_LDIND_I);
773 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
774 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
775 mono_mb_emit_byte (mb, conv);
776 mono_mb_emit_byte (mb, CEE_STIND_I);
778 case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
779 case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
780 case MONO_MARSHAL_CONV_DEL_FTN:
781 mono_mb_emit_byte (mb, CEE_LDLOC_1);
782 mono_mb_emit_byte (mb, CEE_LDLOC_0);
783 mono_mb_emit_byte (mb, CEE_LDIND_I);
784 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
785 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
786 mono_mb_emit_byte (mb, conv);
787 mono_mb_emit_byte (mb, CEE_STIND_I);
789 case MONO_MARSHAL_CONV_STR_BYVALSTR:
790 case MONO_MARSHAL_CONV_STR_BYVALWSTR: {
794 mono_mb_emit_byte (mb, CEE_LDLOC_1); /* dst */
795 mono_mb_emit_byte (mb, CEE_LDLOC_0);
796 mono_mb_emit_byte (mb, CEE_LDIND_I); /* src String */
797 mono_mb_emit_icon (mb, usize);
798 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
799 mono_mb_emit_byte (mb, CEE_MONO_PROC3);
800 mono_mb_emit_byte (mb, conv);
803 case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
807 if (type->type == MONO_TYPE_SZARRAY) {
808 eclass = type->data.klass;
810 g_assert_not_reached ();
813 if (eclass->valuetype)
814 esize = mono_class_native_size (eclass, NULL);
816 esize = sizeof (gpointer);
821 mono_mb_emit_byte (mb, CEE_LDLOC_0);
822 mono_mb_emit_byte (mb, CEE_LDIND_I);
823 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
825 mono_mb_emit_byte (mb, 0);
827 mono_mb_emit_byte (mb, CEE_LDLOC_1);
828 mono_mb_emit_byte (mb, CEE_LDLOC_0);
829 mono_mb_emit_byte (mb, CEE_LDIND_I);
830 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
831 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
832 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
833 mono_mb_emit_byte (mb, CEE_ADD);
834 mono_mb_emit_icon (mb, mspec->data.array_data.num_elem * esize);
835 mono_mb_emit_byte (mb, CEE_PREFIX1);
836 mono_mb_emit_byte (mb, CEE_CPBLK);
837 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
840 case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
841 int src_var, dst_var;
843 src_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
844 dst_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
846 mono_mb_emit_byte (mb, CEE_LDLOC_0);
847 mono_mb_emit_byte (mb, CEE_LDIND_I);
848 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
850 mono_mb_emit_byte (mb, 0);
852 /* save the old src pointer */
853 mono_mb_emit_byte (mb, CEE_LDLOC_0);
854 mono_mb_emit_stloc (mb, src_var);
855 /* save the old dst pointer */
856 mono_mb_emit_byte (mb, CEE_LDLOC_1);
857 mono_mb_emit_stloc (mb, dst_var);
859 /* src = pointer to object data */
860 mono_mb_emit_byte (mb, CEE_LDLOC_0);
861 mono_mb_emit_byte (mb, CEE_LDIND_I);
862 mono_mb_emit_icon (mb, sizeof (MonoObject));
863 mono_mb_emit_byte (mb, CEE_ADD);
864 mono_mb_emit_byte (mb, CEE_STLOC_0);
866 emit_struct_conv (mb, mono_class_from_mono_type (type), FALSE);
868 /* restore the old src pointer */
869 mono_mb_emit_ldloc (mb, src_var);
870 mono_mb_emit_byte (mb, CEE_STLOC_0);
871 /* restore the old dst pointer */
872 mono_mb_emit_ldloc (mb, dst_var);
873 mono_mb_emit_byte (mb, CEE_STLOC_1);
875 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
879 char *msg = g_strdup_printf ("marshalling conversion %d not implemented", conv);
880 MonoException *exc = mono_get_exception_not_implemented (msg);
883 mono_raise_exception (exc);
889 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
891 MonoMarshalType *info;
895 emit_struct_conv(mb, klass->parent, to_object);
897 info = mono_marshal_load_type_info (klass);
899 if (info->native_size == 0)
902 if (klass->blittable) {
903 mono_mb_emit_byte (mb, CEE_LDLOC_1);
904 mono_mb_emit_byte (mb, CEE_LDLOC_0);
905 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
906 mono_mb_emit_byte (mb, CEE_PREFIX1);
907 mono_mb_emit_byte (mb, CEE_CPBLK);
911 for (i = 0; i < info->num_fields; i++) {
912 MonoMarshalNative ntype;
913 MonoMarshalConv conv;
914 MonoType *ftype = info->fields [i].field->type;
917 gboolean last_field = i < (info->num_fields -1) ? 0 : 1;
919 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
922 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, klass->unicode, &conv);
925 msize = klass->instance_size - info->fields [i].field->offset;
926 usize = info->native_size - info->fields [i].offset;
928 msize = info->fields [i + 1].field->offset - info->fields [i].field->offset;
929 usize = info->fields [i + 1].offset - info->fields [i].offset;
931 g_assert ((msize >= 0) && (usize >= 0));
934 case MONO_MARSHAL_CONV_NONE: {
937 if (ftype->byref || ftype->type == MONO_TYPE_I ||
938 ftype->type == MONO_TYPE_U) {
939 mono_mb_emit_byte (mb, CEE_LDLOC_1);
940 mono_mb_emit_byte (mb, CEE_LDLOC_0);
941 mono_mb_emit_byte (mb, CEE_LDIND_I);
942 mono_mb_emit_byte (mb, CEE_STIND_I);
951 #if SIZEOF_VOID_P == 4
954 mono_mb_emit_byte (mb, CEE_LDLOC_1);
955 mono_mb_emit_byte (mb, CEE_LDLOC_0);
956 mono_mb_emit_byte (mb, CEE_LDIND_I4);
957 mono_mb_emit_byte (mb, CEE_STIND_I4);
961 case MONO_TYPE_BOOLEAN:
962 mono_mb_emit_byte (mb, CEE_LDLOC_1);
963 mono_mb_emit_byte (mb, CEE_LDLOC_0);
964 mono_mb_emit_byte (mb, CEE_LDIND_I1);
965 mono_mb_emit_byte (mb, CEE_STIND_I1);
970 mono_mb_emit_byte (mb, CEE_LDLOC_1);
971 mono_mb_emit_byte (mb, CEE_LDLOC_0);
972 mono_mb_emit_byte (mb, CEE_LDIND_I2);
973 mono_mb_emit_byte (mb, CEE_STIND_I2);
977 #if SIZEOF_VOID_P == 8
980 mono_mb_emit_byte (mb, CEE_LDLOC_1);
981 mono_mb_emit_byte (mb, CEE_LDLOC_0);
982 mono_mb_emit_byte (mb, CEE_LDIND_I8);
983 mono_mb_emit_byte (mb, CEE_STIND_I8);
986 mono_mb_emit_byte (mb, CEE_LDLOC_1);
987 mono_mb_emit_byte (mb, CEE_LDLOC_0);
988 mono_mb_emit_byte (mb, CEE_LDIND_R4);
989 mono_mb_emit_byte (mb, CEE_STIND_R4);
992 mono_mb_emit_byte (mb, CEE_LDLOC_1);
993 mono_mb_emit_byte (mb, CEE_LDLOC_0);
994 mono_mb_emit_byte (mb, CEE_LDIND_R8);
995 mono_mb_emit_byte (mb, CEE_STIND_R8);
997 case MONO_TYPE_VALUETYPE:
998 if (ftype->data.klass->enumtype) {
999 t = ftype->data.klass->enum_basetype->type;
1002 emit_struct_conv (mb, ftype->data.klass, to_object);
1005 g_warning ("marshaling type %02x not implemented", ftype->type);
1006 g_assert_not_reached ();
1012 emit_ptr_to_str_conv (mb, ftype, conv, usize, msize, info->fields [i].mspec);
1014 emit_str_to_ptr_conv (mb, ftype, conv, usize, msize, info->fields [i].mspec);
1018 mono_mb_emit_add_to_local (mb, 0, usize);
1019 mono_mb_emit_add_to_local (mb, 1, msize);
1021 mono_mb_emit_add_to_local (mb, 0, msize);
1022 mono_mb_emit_add_to_local (mb, 1, usize);
1027 static MonoAsyncResult *
1028 mono_delegate_begin_invoke (MonoDelegate *delegate, gpointer *params)
1030 MonoMethodMessage *msg;
1031 MonoDelegate *async_callback;
1035 MonoMethod *method = NULL;
1038 g_assert (delegate);
1040 if (delegate->target && mono_object_class (delegate->target) == mono_defaults.transparent_proxy_class) {
1042 MonoTransparentProxy* tp = (MonoTransparentProxy *)delegate->target;
1043 if (!tp->klass->contextbound || tp->rp->context != (MonoObject *) mono_context_get ()) {
1045 // If the target is a proxy, make a direct call. Is proxy's work
1046 // to make the call asynchronous.
1048 MonoAsyncResult *ares;
1050 MonoArray *out_args;
1052 method = delegate->method_info->method;
1054 msg = mono_method_call_message_new (method, params, NULL, &async_callback, &state);
1055 handle = CreateEvent (NULL, TRUE, FALSE, NULL);
1056 ares = mono_async_result_new (mono_domain_get (), handle, state, handle);
1057 ares->async_delegate = (MonoObject *)delegate;
1058 ares->async_callback = (MonoObject *)async_callback;
1059 msg->async_result = ares;
1060 msg->call_type = CallType_BeginInvoke;
1062 mono_remoting_invoke ((MonoObject *)tp->rp, msg, &exc, &out_args);
1067 klass = delegate->object.vtable->klass;
1069 method = mono_get_delegate_invoke (klass);
1070 for (i = 0; i < klass->method.count; ++i) {
1071 if (klass->methods [i]->name[0] == 'B' &&
1072 !strcmp ("BeginInvoke", klass->methods [i]->name)) {
1073 method = klass->methods [i];
1078 g_assert (method != NULL);
1080 im = mono_get_delegate_invoke (method->klass);
1081 msg = mono_method_call_message_new (method, params, im, &async_callback, &state);
1083 return mono_thread_pool_add ((MonoObject *)delegate, msg, async_callback, state);
1087 mono_mb_emit_save_args (MonoMethodBuilder *mb, MonoMethodSignature *sig, gboolean save_this)
1089 int i, params_var, tmp_var;
1091 /* allocate local (pointer) *params[] */
1092 params_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1093 /* allocate local (pointer) tmp */
1094 tmp_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1096 /* alloate space on stack to store an array of pointers to the arguments */
1097 mono_mb_emit_icon (mb, sizeof (gpointer) * (sig->param_count + 1));
1098 mono_mb_emit_byte (mb, CEE_PREFIX1);
1099 mono_mb_emit_byte (mb, CEE_LOCALLOC);
1100 mono_mb_emit_stloc (mb, params_var);
1103 mono_mb_emit_ldloc (mb, params_var);
1104 mono_mb_emit_stloc (mb, tmp_var);
1106 if (save_this && sig->hasthis) {
1107 mono_mb_emit_ldloc (mb, tmp_var);
1108 mono_mb_emit_ldarg_addr (mb, 0);
1109 mono_mb_emit_byte (mb, CEE_STIND_I);
1110 /* tmp = tmp + sizeof (gpointer) */
1111 if (sig->param_count)
1112 mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
1116 for (i = 0; i < sig->param_count; i++) {
1117 mono_mb_emit_ldloc (mb, tmp_var);
1118 mono_mb_emit_ldarg_addr (mb, i + sig->hasthis);
1119 mono_mb_emit_byte (mb, CEE_STIND_I);
1120 /* tmp = tmp + sizeof (gpointer) */
1121 if (i < (sig->param_count - 1))
1122 mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
1129 mono_signature_to_name (MonoMethodSignature *sig, const char *prefix)
1133 GString *res = g_string_new ("");
1136 g_string_append (res, prefix);
1137 g_string_append_c (res, '_');
1140 mono_type_get_desc (res, sig->ret, FALSE);
1142 for (i = 0; i < sig->param_count; ++i) {
1143 g_string_append_c (res, '_');
1144 mono_type_get_desc (res, sig->params [i], FALSE);
1147 g_string_free (res, FALSE);
1151 static inline MonoMethod*
1152 mono_marshal_find_in_cache (GHashTable *cache, gpointer key)
1156 EnterCriticalSection (&marshal_mutex);
1157 res = g_hash_table_lookup (cache, key);
1158 LeaveCriticalSection (&marshal_mutex);
1162 /* Create the method from the builder and place it in the cache */
1163 static inline MonoMethod*
1164 mono_mb_create_and_cache (GHashTable *cache, gpointer key,
1165 MonoMethodBuilder *mb, MonoMethodSignature *sig,
1170 EnterCriticalSection (&marshal_mutex);
1171 res = g_hash_table_lookup (cache, key);
1173 /* This does not acquire any locks */
1174 res = mono_mb_create_method (mb, sig, max_stack);
1175 g_hash_table_insert (cache, key, res);
1176 mono_g_hash_table_insert (wrapper_hash, res, key);
1179 /* Somebody created it before us */
1181 LeaveCriticalSection (&marshal_mutex);
1187 mono_marshal_method_from_wrapper (MonoMethod *wrapper)
1191 if (wrapper->wrapper_type == MONO_WRAPPER_NONE)
1194 EnterCriticalSection (&marshal_mutex);
1195 res = mono_g_hash_table_lookup (wrapper_hash, wrapper);
1196 LeaveCriticalSection (&marshal_mutex);
1198 if (res && wrapper->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)
1199 /* See mono_marshal_get_remoting_invoke_with_check */
1200 return (MonoMethod*)((char*)res - 1);
1206 mono_marshal_get_delegate_begin_invoke (MonoMethod *method)
1208 MonoMethodSignature *sig;
1209 static MonoMethodSignature *csig = NULL;
1210 MonoMethodBuilder *mb;
1216 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1217 !strcmp (method->name, "BeginInvoke"));
1219 sig = method->signature;
1221 cache = method->klass->image->delegate_begin_invoke_cache;
1222 if ((res = mono_marshal_find_in_cache (cache, sig)))
1225 g_assert (sig->hasthis);
1228 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1229 csig = g_malloc0 (sigsize);
1231 /* MonoAsyncResult * begin_invoke (MonoDelegate *delegate, gpointer params[]) */
1232 csig->param_count = 2;
1233 csig->ret = &mono_defaults.object_class->byval_arg;
1234 csig->params [0] = &mono_defaults.object_class->byval_arg;
1235 csig->params [1] = &mono_defaults.int_class->byval_arg;
1238 name = mono_signature_to_name (sig, "begin_invoke");
1239 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_BEGIN_INVOKE);
1242 mb->method->save_lmf = 1;
1244 params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1246 mono_mb_emit_ldarg (mb, 0);
1247 mono_mb_emit_ldloc (mb, params_var);
1248 mono_mb_emit_native_call (mb, csig, mono_delegate_begin_invoke);
1249 mono_mb_emit_byte (mb, CEE_RET);
1251 res = mono_mb_create_and_cache (cache, sig, mb, sig, sig->param_count + 16);
1257 mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params)
1259 MonoDomain *domain = mono_domain_get ();
1260 MonoAsyncResult *ares;
1261 MonoMethod *method = NULL;
1262 MonoMethodSignature *sig;
1263 MonoMethodMessage *msg;
1264 MonoObject *res, *exc;
1265 MonoArray *out_args;
1269 g_assert (delegate);
1271 if (!delegate->method_info || !delegate->method_info->method)
1272 g_assert_not_reached ();
1274 klass = delegate->object.vtable->klass;
1276 for (i = 0; i < klass->method.count; ++i) {
1277 if (klass->methods [i]->name[0] == 'E' &&
1278 !strcmp ("EndInvoke", klass->methods [i]->name)) {
1279 method = klass->methods [i];
1284 g_assert (method != NULL);
1286 sig = method->signature;
1288 msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1290 ares = mono_array_get (msg->args, gpointer, sig->param_count - 1);
1293 if (delegate->target && mono_object_class (delegate->target) == mono_defaults.transparent_proxy_class) {
1294 MonoTransparentProxy* tp = (MonoTransparentProxy *)delegate->target;
1295 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
1296 mono_message_init (domain, msg, delegate->method_info, NULL);
1297 msg->call_type = CallType_EndInvoke;
1298 msg->async_result = ares;
1299 res = mono_remoting_invoke ((MonoObject *)tp->rp, msg, &exc, &out_args);
1302 res = mono_thread_pool_finish (ares, &out_args, &exc);
1305 char *strace = mono_string_to_utf8 (((MonoException*)exc)->stack_trace);
1307 tmp = g_strdup_printf ("%s\nException Rethrown at:\n", strace);
1309 ((MonoException*)exc)->stack_trace = mono_string_new (domain, tmp);
1311 mono_raise_exception ((MonoException*)exc);
1314 mono_method_return_message_restore (method, params, out_args);
1319 mono_mb_emit_restore_result (MonoMethodBuilder *mb, MonoType *return_type)
1321 if (return_type->byref)
1322 return_type = &mono_defaults.int_class->byval_arg;
1323 else if (return_type->type == MONO_TYPE_VALUETYPE && return_type->data.klass->enumtype)
1324 return_type = return_type->data.klass->enum_basetype;
1326 switch (return_type->type) {
1327 case MONO_TYPE_VOID:
1328 g_assert_not_reached ();
1331 case MONO_TYPE_STRING:
1332 case MONO_TYPE_CLASS:
1333 case MONO_TYPE_OBJECT:
1334 case MONO_TYPE_ARRAY:
1335 case MONO_TYPE_SZARRAY:
1339 case MONO_TYPE_BOOLEAN:
1340 mono_mb_emit_byte (mb, CEE_UNBOX);
1341 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1342 mono_mb_emit_byte (mb, CEE_LDIND_U1);
1345 mono_mb_emit_byte (mb, CEE_UNBOX);
1346 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1347 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1350 case MONO_TYPE_CHAR:
1351 mono_mb_emit_byte (mb, CEE_UNBOX);
1352 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1353 mono_mb_emit_byte (mb, CEE_LDIND_U2);
1356 mono_mb_emit_byte (mb, CEE_UNBOX);
1357 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1358 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1362 mono_mb_emit_byte (mb, CEE_UNBOX);
1363 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1364 mono_mb_emit_byte (mb, CEE_LDIND_I);
1367 mono_mb_emit_byte (mb, CEE_UNBOX);
1368 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1369 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1372 mono_mb_emit_byte (mb, CEE_UNBOX);
1373 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1374 mono_mb_emit_byte (mb, CEE_LDIND_U4);
1378 mono_mb_emit_byte (mb, CEE_UNBOX);
1379 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1380 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1383 mono_mb_emit_byte (mb, CEE_UNBOX);
1384 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1385 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1388 mono_mb_emit_byte (mb, CEE_UNBOX);
1389 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1390 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1392 case MONO_TYPE_VALUETYPE: {
1394 mono_mb_emit_byte (mb, CEE_UNBOX);
1395 class = mono_mb_add_data (mb, mono_class_from_mono_type (return_type));
1396 mono_mb_emit_i4 (mb, class);
1397 mono_mb_emit_byte (mb, CEE_LDOBJ);
1398 mono_mb_emit_i4 (mb, class);
1402 g_warning ("type 0x%x not handled", return_type->type);
1403 g_assert_not_reached ();
1406 mono_mb_emit_byte (mb, CEE_RET);
1410 mono_marshal_get_delegate_end_invoke (MonoMethod *method)
1412 MonoMethodSignature *sig;
1413 static MonoMethodSignature *csig = NULL;
1414 MonoMethodBuilder *mb;
1420 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1421 !strcmp (method->name, "EndInvoke"));
1423 sig = method->signature;
1425 cache = method->klass->image->delegate_end_invoke_cache;
1426 if ((res = mono_marshal_find_in_cache (cache, sig)))
1429 g_assert (sig->hasthis);
1432 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1433 csig = g_malloc0 (sigsize);
1435 /* MonoObject *end_invoke (MonoDelegate *delegate, gpointer params[]) */
1436 csig->param_count = 2;
1437 csig->ret = &mono_defaults.object_class->byval_arg;
1438 csig->params [0] = &mono_defaults.object_class->byval_arg;
1439 csig->params [1] = &mono_defaults.int_class->byval_arg;
1442 name = mono_signature_to_name (sig, "end_invoke");
1443 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_END_INVOKE);
1446 mb->method->save_lmf = 1;
1448 params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1450 mono_mb_emit_ldarg (mb, 0);
1451 mono_mb_emit_ldloc (mb, params_var);
1452 mono_mb_emit_native_call (mb, csig, mono_delegate_end_invoke);
1454 if (sig->ret->type == MONO_TYPE_VOID) {
1455 mono_mb_emit_byte (mb, CEE_POP);
1456 mono_mb_emit_byte (mb, CEE_RET);
1458 mono_mb_emit_restore_result (mb, sig->ret);
1460 res = mono_mb_create_and_cache (cache, sig,
1461 mb, sig, sig->param_count + 16);
1468 mono_remoting_wrapper (MonoMethod *method, gpointer *params)
1470 MonoMethodMessage *msg;
1471 MonoTransparentProxy *this;
1472 MonoObject *res, *exc;
1473 MonoArray *out_args;
1475 this = *((MonoTransparentProxy **)params [0]);
1478 g_assert (((MonoObject *)this)->vtable->klass == mono_defaults.transparent_proxy_class);
1480 /* skip the this pointer */
1483 if (this->klass->contextbound && this->rp->context == (MonoObject *) mono_context_get ())
1486 MonoMethodSignature *sig = method->signature;
1487 int count = sig->param_count;
1488 gpointer* mparams = (gpointer*) alloca(count*sizeof(gpointer));
1490 for (i=0; i<count; i++) {
1491 MonoClass *class = mono_class_from_mono_type (sig->params [i]);
1492 if (class->valuetype) {
1493 if (sig->params [i]->byref)
1494 mparams[i] = *((gpointer *)params [i]);
1496 mparams[i] = params [i];
1498 mparams[i] = *((gpointer**)params [i]);
1502 return mono_runtime_invoke (method, this, mparams, NULL);
1505 msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1507 res = mono_remoting_invoke ((MonoObject *)this->rp, msg, &exc, &out_args);
1510 mono_raise_exception ((MonoException *)exc);
1512 mono_method_return_message_restore (method, params, out_args);
1518 mono_marshal_get_remoting_invoke (MonoMethod *method)
1520 MonoMethodSignature *sig;
1521 static MonoMethodSignature *csig = NULL;
1522 MonoMethodBuilder *mb;
1529 if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE)
1532 sig = method->signature;
1534 /* we cant remote methods without this pointer */
1538 cache = method->klass->image->remoting_invoke_cache;
1539 if ((res = mono_marshal_find_in_cache (cache, method)))
1543 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
1544 csig->params [0] = &mono_defaults.int_class->byval_arg;
1545 csig->params [1] = &mono_defaults.int_class->byval_arg;
1546 csig->ret = &mono_defaults.object_class->byval_arg;
1550 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE);
1551 mb->method->save_lmf = 1;
1553 params_var = mono_mb_emit_save_args (mb, sig, TRUE);
1555 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1556 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1557 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
1558 mono_mb_emit_ldloc (mb, params_var);
1559 mono_mb_emit_native_call (mb, csig, mono_remoting_wrapper);
1561 if (sig->ret->type == MONO_TYPE_VOID) {
1562 mono_mb_emit_byte (mb, CEE_POP);
1563 mono_mb_emit_byte (mb, CEE_RET);
1565 mono_mb_emit_restore_result (mb, sig->ret);
1568 res = mono_mb_create_and_cache (cache, method, mb, sig, sig->param_count + 16);
1575 mono_marshal_get_remoting_invoke_with_check (MonoMethod *method)
1577 MonoMethodSignature *sig;
1578 MonoMethodBuilder *mb;
1579 MonoMethod *res, *native;
1585 if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)
1588 sig = method->signature;
1590 /* we cant remote methods without this pointer */
1591 g_assert (sig->hasthis);
1593 cache = method->klass->image->remoting_invoke_cache;
1594 if ((res = mono_marshal_find_in_cache (cache, (char *)method + 1)))
1597 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK);
1599 mono_mb_emit_ldarg (mb, 0);
1600 pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
1602 native = mono_marshal_get_remoting_invoke (method);
1604 for (i = 0; i <= sig->param_count; i++)
1605 mono_mb_emit_ldarg (mb, i);
1607 mono_mb_emit_managed_call (mb, native, native->signature);
1608 mono_mb_emit_byte (mb, CEE_RET);
1610 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1612 for (i = 0; i <= sig->param_count; i++)
1613 mono_mb_emit_ldarg (mb, i);
1615 mono_mb_emit_managed_call (mb, method, method->signature);
1616 mono_mb_emit_byte (mb, CEE_RET);
1618 res = mono_mb_create_and_cache (cache, (char*)method + 1,
1619 mb, sig, sig->param_count + 16);
1626 * the returned method invokes all methods in a multicast delegate
1629 mono_marshal_get_delegate_invoke (MonoMethod *method)
1631 MonoMethodSignature *sig, *static_sig;
1633 MonoMethodBuilder *mb;
1639 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1640 !strcmp (method->name, "Invoke"));
1642 sig = method->signature;
1644 cache = method->klass->image->delegate_invoke_cache;
1645 if ((res = mono_marshal_find_in_cache (cache, sig)))
1648 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1649 static_sig = g_memdup (sig, sigsize);
1650 static_sig->hasthis = 0;
1652 name = mono_signature_to_name (sig, "invoke");
1653 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_INVOKE);
1656 /* allocate local 0 (object) */
1657 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1659 g_assert (sig->hasthis);
1663 * prev.Invoke( args .. );
1664 * return this.<target>( args .. );
1667 /* get this->prev */
1668 mono_mb_emit_ldarg (mb, 0);
1669 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoMulticastDelegate, prev));
1670 mono_mb_emit_byte (mb, CEE_LDIND_I );
1671 mono_mb_emit_stloc (mb, 0);
1673 /* if prev != null */
1674 mono_mb_emit_ldloc (mb, 0);
1675 mono_mb_emit_byte (mb, CEE_BRFALSE);
1678 mono_mb_emit_i4 (mb, 0);
1681 mono_mb_emit_ldloc (mb, 0);
1682 for (i = 0; i < sig->param_count; i++)
1683 mono_mb_emit_ldarg (mb, i + 1);
1684 mono_mb_emit_managed_call (mb, method, method->signature);
1685 if (sig->ret->type != MONO_TYPE_VOID)
1686 mono_mb_emit_byte (mb, CEE_POP);
1688 /* continued or prev == null */
1689 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1691 /* get this->target */
1692 mono_mb_emit_ldarg (mb, 0);
1693 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, target));
1694 mono_mb_emit_byte (mb, CEE_LDIND_I );
1695 mono_mb_emit_stloc (mb, 0);
1697 /* if target != null */
1698 mono_mb_emit_ldloc (mb, 0);
1699 mono_mb_emit_byte (mb, CEE_BRFALSE);
1701 mono_mb_emit_i4 (mb, 0);
1703 /* then call this->method_ptr nonstatic */
1704 mono_mb_emit_ldloc (mb, 0);
1705 for (i = 0; i < sig->param_count; ++i)
1706 mono_mb_emit_ldarg (mb, i + 1);
1707 mono_mb_emit_ldarg (mb, 0);
1708 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1709 mono_mb_emit_byte (mb, CEE_LDIND_I );
1710 mono_mb_emit_byte (mb, CEE_CALLI);
1711 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
1713 mono_mb_emit_byte (mb, CEE_BR);
1715 mono_mb_emit_i4 (mb, 0);
1717 /* else [target == null] call this->method_ptr static */
1718 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1720 for (i = 0; i < sig->param_count; ++i)
1721 mono_mb_emit_ldarg (mb, i + 1);
1722 mono_mb_emit_ldarg (mb, 0);
1723 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1724 mono_mb_emit_byte (mb, CEE_LDIND_I );
1725 mono_mb_emit_byte (mb, CEE_CALLI);
1726 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, static_sig));
1729 mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
1730 mono_mb_emit_byte (mb, CEE_RET);
1732 res = mono_mb_create_and_cache (cache, sig,
1733 mb, sig, sig->param_count + 16);
1740 * generates IL code for the runtime invoke function
1741 * MonoObject *runtime_invoke (MonoObject *this, void **params, MonoObject **exc)
1743 * we also catch exceptions if exc != null
1746 mono_marshal_get_runtime_invoke (MonoMethod *method)
1748 MonoMethodSignature *sig, *csig;
1749 MonoExceptionClause *clause;
1750 MonoMethodHeader *header;
1751 MonoMethodBuilder *mb;
1754 static MonoString *string_dummy = NULL;
1755 int i, pos, sigsize;
1759 cache = method->klass->image->runtime_invoke_cache;
1760 if ((res = mono_marshal_find_in_cache (cache, method)))
1763 /* to make it work with our special string constructors */
1765 string_dummy = mono_string_new_wrapper ("dummy");
1767 sig = method->signature;
1769 sigsize = sizeof (MonoMethodSignature) + 3 * sizeof (MonoType *);
1770 csig = g_malloc0 (sigsize);
1772 csig->param_count = 3;
1773 csig->ret = &mono_defaults.object_class->byval_arg;
1774 csig->params [0] = &mono_defaults.object_class->byval_arg;
1775 csig->params [1] = &mono_defaults.int_class->byval_arg;
1776 csig->params [2] = &mono_defaults.int_class->byval_arg;
1778 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_RUNTIME_INVOKE);
1780 /* allocate local 0 (object) tmp */
1781 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1782 /* allocate local 1 (object) exc */
1783 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1785 /* cond set *exc to null */
1786 mono_mb_emit_byte (mb, CEE_LDARG_2);
1787 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
1788 mono_mb_emit_byte (mb, 3);
1789 mono_mb_emit_byte (mb, CEE_LDARG_2);
1790 mono_mb_emit_byte (mb, CEE_LDNULL);
1791 mono_mb_emit_byte (mb, CEE_STIND_I);
1794 if (method->string_ctor) {
1795 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1796 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1797 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, string_dummy));
1799 mono_mb_emit_ldarg (mb, 0);
1800 if (method->klass->valuetype) {
1801 mono_mb_emit_byte (mb, CEE_UNBOX);
1802 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method->klass));
1807 for (i = 0; i < sig->param_count; i++) {
1808 MonoType *t = sig->params [i];
1811 mono_mb_emit_ldarg (mb, 1);
1813 mono_mb_emit_icon (mb, sizeof (gpointer) * i);
1814 mono_mb_emit_byte (mb, CEE_ADD);
1816 mono_mb_emit_byte (mb, CEE_LDIND_I);
1821 type = sig->params [i]->type;
1825 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1827 case MONO_TYPE_BOOLEAN:
1829 mono_mb_emit_byte (mb, CEE_LDIND_U1);
1832 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1835 case MONO_TYPE_CHAR:
1836 mono_mb_emit_byte (mb, CEE_LDIND_U2);
1840 mono_mb_emit_byte (mb, CEE_LDIND_I);
1843 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1846 mono_mb_emit_byte (mb, CEE_LDIND_U4);
1849 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1852 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1856 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1858 case MONO_TYPE_STRING:
1859 case MONO_TYPE_CLASS:
1860 case MONO_TYPE_ARRAY:
1862 case MONO_TYPE_SZARRAY:
1863 case MONO_TYPE_OBJECT:
1866 case MONO_TYPE_VALUETYPE:
1867 if (t->data.klass->enumtype) {
1868 type = t->data.klass->enum_basetype->type;
1871 mono_mb_emit_byte (mb, CEE_LDOBJ);
1872 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, t->data.klass));
1875 g_assert_not_reached ();
1879 if (method->string_ctor) {
1880 MonoMethodSignature *strsig;
1882 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1883 strsig = g_memdup (sig, sigsize);
1884 strsig->ret = &mono_defaults.string_class->byval_arg;
1886 mono_mb_emit_managed_call (mb, method, strsig);
1888 mono_mb_emit_managed_call (mb, method, NULL);
1890 if (sig->ret->byref) {
1892 g_assert_not_reached ();
1896 switch (sig->ret->type) {
1897 case MONO_TYPE_VOID:
1898 if (!method->string_ctor)
1899 mono_mb_emit_byte (mb, CEE_LDNULL);
1901 case MONO_TYPE_BOOLEAN:
1902 case MONO_TYPE_CHAR:
1915 case MONO_TYPE_VALUETYPE:
1916 /* box value types */
1917 mono_mb_emit_byte (mb, CEE_BOX);
1918 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (sig->ret)));
1920 case MONO_TYPE_STRING:
1921 case MONO_TYPE_CLASS:
1922 case MONO_TYPE_ARRAY:
1923 case MONO_TYPE_SZARRAY:
1924 case MONO_TYPE_OBJECT:
1929 g_assert_not_reached ();
1932 mono_mb_emit_stloc (mb, 0);
1934 mono_mb_emit_byte (mb, CEE_LEAVE);
1936 mono_mb_emit_i4 (mb, 0);
1938 clause = g_new0 (MonoExceptionClause, 1);
1939 clause->flags = MONO_EXCEPTION_CLAUSE_FILTER;
1940 clause->try_len = mb->pos;
1943 clause->token_or_filter = mb->pos;
1945 mono_mb_emit_byte (mb, CEE_POP);
1946 mono_mb_emit_byte (mb, CEE_LDARG_2);
1947 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
1948 mono_mb_emit_byte (mb, CEE_PREFIX1);
1949 mono_mb_emit_byte (mb, CEE_CGT_UN);
1950 mono_mb_emit_byte (mb, CEE_PREFIX1);
1951 mono_mb_emit_byte (mb, CEE_ENDFILTER);
1953 clause->handler_offset = mb->pos;
1956 /* store exception */
1957 mono_mb_emit_stloc (mb, 1);
1959 mono_mb_emit_byte (mb, CEE_LDARG_2);
1960 mono_mb_emit_ldloc (mb, 1);
1961 mono_mb_emit_byte (mb, CEE_STIND_I);
1963 mono_mb_emit_byte (mb, CEE_LEAVE);
1964 mono_mb_emit_i4 (mb, 0);
1966 clause->handler_len = mb->pos - clause->handler_offset;
1969 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1970 mono_mb_emit_ldloc (mb, 0);
1971 mono_mb_emit_byte (mb, CEE_RET);
1973 res = mono_mb_create_and_cache (cache, method,
1974 mb, csig, sig->param_count + 16);
1977 header = ((MonoMethodNormal *)res)->header;
1978 header->num_clauses = 1;
1979 header->clauses = clause;
1985 * generates IL code to call managed methods from unmanaged code
1988 mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this, MonoMarshalSpec **mspecs)
1990 MonoMethodSignature *sig, *csig;
1991 MonoMethodBuilder *mb;
1995 int i, pos, sigsize, *tmp_locals;
1996 static MonoMethodSignature *alloc_sig = NULL;
1999 g_assert (method != NULL);
2000 g_assert (!method->signature->pinvoke);
2002 cache = method->klass->image->managed_wrapper_cache;
2003 if (!this && (res = mono_marshal_find_in_cache (cache, method)))
2006 /* Under MS, the allocation should be done using CoTaskMemAlloc */
2008 alloc_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
2009 alloc_sig->params [0] = &mono_defaults.int_class->byval_arg;
2010 alloc_sig->ret = &mono_defaults.int_class->byval_arg;
2011 alloc_sig->pinvoke = 1;
2015 /* fime: howto free that memory ? */
2018 sig = method->signature;
2020 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_NATIVE_TO_MANAGED);
2022 /* allocate local 0 (pointer) src_ptr */
2023 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2024 /* allocate local 1 (pointer) dst_ptr */
2025 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2026 /* allocate local 2 (boolean) delete_old */
2027 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2029 if (!MONO_TYPE_IS_VOID(sig->ret)) {
2030 /* allocate local 3 to store the return value */
2031 mono_mb_add_local (mb, sig->ret);
2034 mono_mb_emit_byte (mb, CEE_LDNULL);
2035 mono_mb_emit_byte (mb, CEE_STLOC_2);
2037 /* we copy the signature, so that we can modify it */
2038 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
2039 csig = g_memdup (sig, sigsize);
2043 #ifdef PLATFORM_WIN32
2045 * Under windows, delegates passed to native code must use the STDCALL
2046 * calling convention.
2048 csig->call_convention = MONO_CALL_STDCALL;
2051 /* fixme: howto handle this ? */
2055 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2056 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
2057 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, this));
2062 g_assert_not_reached ();
2067 /* we first do all conversions */
2068 tmp_locals = alloca (sizeof (int) * sig->param_count);
2069 for (i = 0; i < sig->param_count; i ++) {
2070 MonoType *t = sig->params [i];
2071 MonoMarshalSpec *spec = mspecs [i + 1];
2075 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
2078 MonoMethod *marshal_native_to_managed;
2079 MonoMethod *get_instance;
2081 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
2082 g_assert (mtype != NULL);
2083 mklass = mono_class_from_mono_type (mtype);
2084 g_assert (mklass != NULL);
2086 marshal_native_to_managed = mono_find_method_by_name (mklass, "MarshalNativeToManaged", 1);
2087 g_assert (marshal_native_to_managed);
2088 get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
2089 g_assert (get_instance);
2092 case MONO_TYPE_CLASS:
2093 case MONO_TYPE_OBJECT:
2094 case MONO_TYPE_STRING:
2095 case MONO_TYPE_ARRAY:
2096 case MONO_TYPE_SZARRAY:
2100 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2102 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
2104 mono_mb_emit_byte (mb, CEE_CALL);
2105 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
2107 mono_mb_emit_ldarg (mb, i);
2109 mono_mb_emit_byte (mb, CEE_CALLVIRT);
2110 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_native_to_managed));
2112 mono_mb_emit_stloc (mb, tmp_locals [i]);
2115 g_warning ("custom marshalling of type %x is currently not supported", t->type);
2116 g_assert_not_reached ();
2123 case MONO_TYPE_CLASS: {
2124 klass = t->data.klass;
2126 /* FIXME: Raise a MarshalDirectiveException here */
2127 g_assert ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT);
2129 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2131 if (t->attrs & PARAM_ATTRIBUTE_OUT) {
2132 mono_mb_emit_byte (mb, CEE_LDNULL);
2133 mono_mb_emit_stloc (mb, tmp_locals [i]);
2138 mono_mb_emit_ldarg (mb, i);
2142 /* Check for NULL and raise an exception */
2143 mono_mb_emit_byte (mb, CEE_BRTRUE);
2145 mono_mb_emit_i4 (mb, 0);
2147 mono_mb_emit_exception (mb, "ArgumentNullException", NULL);
2149 mono_mb_patch_addr (mb, pos2, mb->pos - (pos2 + 4));
2150 mono_mb_emit_ldarg (mb, i);
2151 mono_mb_emit_byte (mb, CEE_LDIND_I);
2154 mono_mb_emit_byte (mb, CEE_STLOC_0);
2156 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
2157 mono_mb_emit_stloc (mb, tmp_locals [i]);
2159 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2160 mono_mb_emit_byte (mb, CEE_BRFALSE);
2162 mono_mb_emit_i4 (mb, 0);
2164 /* Create and set dst */
2165 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2166 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
2167 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2168 mono_mb_emit_stloc (mb, tmp_locals [i]);
2169 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2170 mono_mb_emit_icon (mb, sizeof (MonoObject));
2171 mono_mb_emit_byte (mb, CEE_ADD);
2172 mono_mb_emit_byte (mb, CEE_STLOC_1);
2174 /* emit valuetype conversion code */
2175 emit_struct_conv (mb, klass, TRUE);
2177 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2180 case MONO_TYPE_VALUETYPE:
2182 klass = sig->params [i]->data.klass;
2183 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2184 klass->blittable || klass->enumtype)
2187 tmp_locals [i] = mono_mb_add_local (mb, &klass->byval_arg);
2190 mono_mb_emit_ldarg (mb, i);
2192 mono_mb_emit_ldarg_addr (mb, i);
2193 mono_mb_emit_byte (mb, CEE_STLOC_0);
2196 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2197 mono_mb_emit_byte (mb, CEE_BRFALSE);
2199 mono_mb_emit_i4 (mb, 0);
2202 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2203 mono_mb_emit_byte (mb, CEE_STLOC_1);
2205 /* emit valuetype convnversion code code */
2206 emit_struct_conv (mb, klass, TRUE);
2209 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2211 case MONO_TYPE_STRING:
2215 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2216 csig->params [i] = &mono_defaults.int_class->byval_arg;
2218 mono_mb_emit_ldarg (mb, i);
2219 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2220 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2221 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
2222 mono_mb_emit_stloc (mb, tmp_locals [i]);
2224 case MONO_TYPE_ARRAY:
2225 case MONO_TYPE_SZARRAY:
2229 klass = mono_class_from_mono_type (t);
2231 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2232 csig->params [i] = &mono_defaults.int_class->byval_arg;
2234 g_warning ("array marshaling not implemented");
2235 g_assert_not_reached ();
2240 for (i = 0; i < sig->param_count; i++) {
2241 MonoType *t = sig->params [i];
2244 case MONO_TYPE_BOOLEAN:
2258 mono_mb_emit_ldarg (mb, i);
2260 case MONO_TYPE_STRING:
2262 mono_mb_emit_ldarg (mb, i);
2264 g_assert (tmp_locals [i]);
2265 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2268 case MONO_TYPE_CLASS:
2270 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2272 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2274 case MONO_TYPE_ARRAY:
2275 case MONO_TYPE_SZARRAY:
2276 case MONO_TYPE_OBJECT:
2278 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2280 mono_mb_emit_ldarg (mb, i);
2282 case MONO_TYPE_VALUETYPE:
2283 klass = sig->params [i]->data.klass;
2284 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2285 klass->blittable || klass->enumtype) {
2286 mono_mb_emit_ldarg (mb, i);
2290 g_assert (tmp_locals [i]);
2292 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2294 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2297 g_warning ("type 0x%02x unknown", t->type);
2298 g_assert_not_reached ();
2302 mono_mb_emit_managed_call (mb, method, NULL);
2304 if (!sig->ret->byref) {
2305 switch (sig->ret->type) {
2306 case MONO_TYPE_VOID:
2308 case MONO_TYPE_BOOLEAN:
2322 case MONO_TYPE_OBJECT:
2323 mono_mb_emit_byte (mb, CEE_STLOC_3);
2325 case MONO_TYPE_STRING:
2326 csig->ret = &mono_defaults.int_class->byval_arg;
2328 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2329 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2330 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
2331 mono_mb_emit_byte (mb, CEE_STLOC_3);
2333 case MONO_TYPE_VALUETYPE:
2334 klass = sig->ret->data.klass;
2335 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2336 klass->blittable || klass->enumtype)
2339 /* load pointer to returned value type */
2340 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2341 mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
2343 /* store the address of the source into local variable 0 */
2344 mono_mb_emit_byte (mb, CEE_STLOC_0);
2345 /* allocate space for the native struct and
2346 * store the address into dst_ptr */
2347 retobj_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2348 g_assert (retobj_var);
2349 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2350 mono_mb_emit_native_call (mb, alloc_sig, mono_marshal_alloc);
2351 mono_mb_emit_byte (mb, CEE_STLOC_1);
2352 mono_mb_emit_byte (mb, CEE_LDLOC_1);
2353 mono_mb_emit_stloc (mb, retobj_var);
2355 /* emit valuetype conversion code */
2356 emit_struct_conv (mb, klass, FALSE);
2358 case MONO_TYPE_CLASS: {
2361 klass = sig->ret->data.klass;
2363 /* FIXME: Raise a MarshalDirectiveException here */
2364 g_assert ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT);
2366 mono_mb_emit_byte (mb, CEE_STLOC_0);
2367 /* Check for null */
2368 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2369 pos = mono_mb_emit_branch (mb, CEE_BRTRUE);
2370 mono_mb_emit_byte (mb, CEE_LDNULL);
2371 mono_mb_emit_byte (mb, CEE_STLOC_3);
2372 pos2 = mono_mb_emit_branch (mb, CEE_BR);
2374 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2377 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2378 mono_mb_emit_icon (mb, sizeof (MonoObject));
2379 mono_mb_emit_byte (mb, CEE_ADD);
2380 mono_mb_emit_byte (mb, CEE_STLOC_0);
2382 /* Allocate and set dest */
2383 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2384 mono_mb_emit_native_call (mb, alloc_sig, mono_marshal_alloc);
2385 mono_mb_emit_byte (mb, CEE_DUP);
2386 mono_mb_emit_byte (mb, CEE_STLOC_1);
2387 mono_mb_emit_byte (mb, CEE_STLOC_3);
2389 emit_struct_conv (mb, klass, FALSE);
2391 mono_mb_patch_addr (mb, pos2, mb->pos - (pos2 + 4));
2395 g_warning ("return type 0x%02x unknown", sig->ret->type);
2396 g_assert_not_reached ();
2399 mono_mb_emit_byte (mb, CEE_STLOC_3);
2402 /* Convert byref arguments back */
2403 for (i = 0; i < sig->param_count; i ++) {
2404 MonoType *t = sig->params [i];
2410 case MONO_TYPE_CLASS: {
2413 klass = t->data.klass;
2415 /* Check for null */
2416 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2417 pos = mono_mb_emit_branch (mb, CEE_BRTRUE);
2418 mono_mb_emit_ldarg (mb, i);
2419 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
2420 mono_mb_emit_byte (mb, CEE_STIND_I);
2421 pos2 = mono_mb_emit_branch (mb, CEE_BR);
2423 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2426 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2427 mono_mb_emit_icon (mb, sizeof (MonoObject));
2428 mono_mb_emit_byte (mb, CEE_ADD);
2429 mono_mb_emit_byte (mb, CEE_STLOC_0);
2431 /* Allocate and set dest */
2432 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2433 mono_mb_emit_native_call (mb, alloc_sig, mono_marshal_alloc);
2434 mono_mb_emit_byte (mb, CEE_STLOC_1);
2436 /* Update argument pointer */
2437 mono_mb_emit_ldarg (mb, i);
2438 mono_mb_emit_byte (mb, CEE_LDLOC_1);
2439 mono_mb_emit_byte (mb, CEE_STIND_I);
2441 /* emit valuetype conversion code */
2442 emit_struct_conv (mb, klass, FALSE);
2444 mono_mb_patch_addr (mb, pos2, mb->pos - (pos2 + 4));
2451 mono_mb_emit_ldloc (mb, retobj_var);
2452 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2453 mono_mb_emit_byte (mb, CEE_MONO_RETOBJ);
2454 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2457 if (!MONO_TYPE_IS_VOID(sig->ret))
2458 mono_mb_emit_byte (mb, CEE_LDLOC_3);
2459 mono_mb_emit_byte (mb, CEE_RET);
2463 res = mono_mb_create_and_cache (cache, method,
2464 mb, csig, sig->param_count + 16);
2466 res = mono_mb_create_method (mb, csig, sig->param_count + 16);
2469 //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));
2475 * mono_marshal_get_ldfld_wrapper:
2476 * @type: the type of the field
2478 * This method generates a function which can be use to load a field with type
2479 * @type from an object. The generated function has the following signature:
2480 * <@type> ldfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset)
2483 mono_marshal_get_ldfld_wrapper (MonoType *type)
2485 MonoMethodSignature *sig, *csig;
2486 MonoMethodBuilder *mb;
2489 static GHashTable *ldfld_hash = NULL;
2496 if (type->type == MONO_TYPE_SZARRAY) {
2497 klass = mono_defaults.array_class;
2498 } else if (type->type == MONO_TYPE_VALUETYPE) {
2499 klass = type->data.klass;
2500 if (klass->enumtype) {
2501 t = klass->enum_basetype->type;
2502 klass = mono_class_from_mono_type (klass->enum_basetype);
2504 } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
2505 t == MONO_TYPE_CLASS) {
2506 klass = mono_defaults.object_class;
2507 } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
2508 klass = mono_defaults.int_class;
2510 klass = mono_class_from_mono_type (type);
2513 klass = mono_defaults.int_class;
2516 EnterCriticalSection (&marshal_mutex);
2518 ldfld_hash = g_hash_table_new (NULL, NULL);
2519 res = g_hash_table_lookup (ldfld_hash, klass);
2520 LeaveCriticalSection (&marshal_mutex);
2524 name = g_strdup_printf ("__ldfld_wrapper_%s.%s", klass->name_space, klass->name);
2525 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_LDFLD);
2528 mb->method->save_lmf = 1;
2530 sig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
2531 sig->params [0] = &mono_defaults.object_class->byval_arg;
2532 sig->params [1] = &mono_defaults.int_class->byval_arg;
2533 sig->params [2] = &mono_defaults.int_class->byval_arg;
2534 sig->params [3] = &mono_defaults.int_class->byval_arg;
2535 sig->ret = &klass->byval_arg;
2537 mono_mb_emit_ldarg (mb, 0);
2538 pos0 = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
2540 mono_mb_emit_ldarg (mb, 0);
2541 mono_mb_emit_ldarg (mb, 1);
2542 mono_mb_emit_ldarg (mb, 2);
2544 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
2545 csig->params [0] = &mono_defaults.object_class->byval_arg;
2546 csig->params [1] = &mono_defaults.int_class->byval_arg;
2547 csig->params [2] = &mono_defaults.int_class->byval_arg;
2548 csig->ret = &klass->this_arg;
2551 mono_mb_emit_native_call (mb, csig, mono_load_remote_field_new);
2553 if (klass->valuetype) {
2554 mono_mb_emit_byte (mb, CEE_UNBOX);
2555 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2556 mono_mb_emit_byte (mb, CEE_BR);
2558 mono_mb_emit_i4 (mb, 0);
2560 mono_mb_emit_byte (mb, CEE_RET);
2564 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
2566 mono_mb_emit_ldarg (mb, 0);
2567 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2568 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2569 mono_mb_emit_ldarg (mb, 3);
2570 mono_mb_emit_byte (mb, CEE_ADD);
2572 if (klass->valuetype)
2573 mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
2578 case MONO_TYPE_BOOLEAN:
2579 mono_mb_emit_byte (mb, CEE_LDIND_I1);
2581 case MONO_TYPE_CHAR:
2584 mono_mb_emit_byte (mb, CEE_LDIND_I2);
2588 mono_mb_emit_byte (mb, CEE_LDIND_I4);
2592 mono_mb_emit_byte (mb, CEE_LDIND_I8);
2595 mono_mb_emit_byte (mb, CEE_LDIND_R4);
2598 mono_mb_emit_byte (mb, CEE_LDIND_R8);
2600 case MONO_TYPE_ARRAY:
2602 case MONO_TYPE_FNPTR:
2603 case MONO_TYPE_SZARRAY:
2604 case MONO_TYPE_OBJECT:
2605 case MONO_TYPE_CLASS:
2606 case MONO_TYPE_STRING:
2609 mono_mb_emit_byte (mb, CEE_LDIND_I);
2611 case MONO_TYPE_VALUETYPE:
2612 g_assert (!klass->enumtype);
2613 mono_mb_emit_byte (mb, CEE_LDOBJ);
2614 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2617 g_warning ("type %x not implemented", type->type);
2618 g_assert_not_reached ();
2621 mono_mb_emit_byte (mb, CEE_RET);
2623 res = mono_mb_create_and_cache (ldfld_hash, klass,
2624 mb, sig, sig->param_count + 16);
2631 * mono_marshal_get_stfld_wrapper:
2632 * @type: the type of the field
2634 * This method generates a function which can be use to store a field with type
2635 * @type. The generated function has the following signature:
2636 * void stfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset, <@type> val)
2639 mono_marshal_get_stfld_wrapper (MonoType *type)
2641 MonoMethodSignature *sig, *csig;
2642 MonoMethodBuilder *mb;
2645 static GHashTable *stfld_hash = NULL;
2652 if (type->type == MONO_TYPE_SZARRAY) {
2653 klass = mono_defaults.array_class;
2654 } else if (type->type == MONO_TYPE_VALUETYPE) {
2655 klass = type->data.klass;
2656 if (klass->enumtype) {
2657 t = klass->enum_basetype->type;
2658 klass = mono_class_from_mono_type (klass->enum_basetype);
2660 } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
2661 t == MONO_TYPE_CLASS) {
2662 klass = mono_defaults.object_class;
2663 } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
2664 klass = mono_defaults.int_class;
2666 klass = mono_class_from_mono_type (type);
2669 klass = mono_defaults.int_class;
2672 EnterCriticalSection (&marshal_mutex);
2674 stfld_hash = g_hash_table_new (NULL, NULL);
2675 res = g_hash_table_lookup (stfld_hash, klass);
2676 LeaveCriticalSection (&marshal_mutex);
2680 name = g_strdup_printf ("__stfld_wrapper_%s.%s", klass->name_space, klass->name);
2681 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_STFLD);
2684 mb->method->save_lmf = 1;
2686 sig = mono_metadata_signature_alloc (mono_defaults.corlib, 5);
2687 sig->params [0] = &mono_defaults.object_class->byval_arg;
2688 sig->params [1] = &mono_defaults.int_class->byval_arg;
2689 sig->params [2] = &mono_defaults.int_class->byval_arg;
2690 sig->params [3] = &mono_defaults.int_class->byval_arg;
2691 sig->params [4] = &klass->byval_arg;
2692 sig->ret = &mono_defaults.void_class->byval_arg;
2694 mono_mb_emit_ldarg (mb, 0);
2695 pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
2697 mono_mb_emit_ldarg (mb, 0);
2698 mono_mb_emit_ldarg (mb, 1);
2699 mono_mb_emit_ldarg (mb, 2);
2700 mono_mb_emit_ldarg (mb, 4);
2702 if (klass->valuetype) {
2703 mono_mb_emit_byte (mb, CEE_BOX);
2704 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2707 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
2708 csig->params [0] = &mono_defaults.object_class->byval_arg;
2709 csig->params [1] = &mono_defaults.int_class->byval_arg;
2710 csig->params [2] = &mono_defaults.int_class->byval_arg;
2711 csig->params [3] = &klass->this_arg;
2712 csig->ret = &mono_defaults.void_class->byval_arg;
2715 mono_mb_emit_native_call (mb, csig, mono_store_remote_field_new);
2717 mono_mb_emit_byte (mb, CEE_RET);
2719 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2721 mono_mb_emit_ldarg (mb, 0);
2722 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2723 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2724 mono_mb_emit_ldarg (mb, 3);
2725 mono_mb_emit_byte (mb, CEE_ADD);
2726 mono_mb_emit_ldarg (mb, 4);
2731 case MONO_TYPE_BOOLEAN:
2732 mono_mb_emit_byte (mb, CEE_STIND_I1);
2734 case MONO_TYPE_CHAR:
2737 mono_mb_emit_byte (mb, CEE_STIND_I2);
2741 mono_mb_emit_byte (mb, CEE_STIND_I4);
2745 mono_mb_emit_byte (mb, CEE_STIND_I8);
2748 mono_mb_emit_byte (mb, CEE_STIND_R4);
2751 mono_mb_emit_byte (mb, CEE_STIND_R8);
2753 case MONO_TYPE_ARRAY:
2755 case MONO_TYPE_FNPTR:
2756 case MONO_TYPE_SZARRAY:
2757 case MONO_TYPE_OBJECT:
2758 case MONO_TYPE_CLASS:
2759 case MONO_TYPE_STRING:
2762 mono_mb_emit_byte (mb, CEE_STIND_I);
2764 case MONO_TYPE_VALUETYPE:
2765 g_assert (!klass->enumtype);
2766 mono_mb_emit_byte (mb, CEE_STOBJ);
2767 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2770 g_warning ("type %x not implemented", type->type);
2771 g_assert_not_reached ();
2774 mono_mb_emit_byte (mb, CEE_RET);
2776 res = mono_mb_create_and_cache (stfld_hash, klass,
2777 mb, sig, sig->param_count + 16);
2784 * generates IL code for the icall wrapper (the generated method
2785 * calls the unmanaged code in func)
2788 mono_marshal_get_icall_wrapper (MonoMethodSignature *sig, const char *name, gconstpointer func)
2790 MonoMethodSignature *csig;
2791 MonoMethodBuilder *mb;
2795 g_assert (sig->pinvoke);
2797 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_MANAGED_TO_NATIVE);
2799 mb->method->save_lmf = 1;
2801 /* we copy the signature, so that we can modify it */
2802 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
2805 mono_mb_emit_byte (mb, CEE_LDARG_0);
2807 for (i = 0; i < sig->param_count; i++)
2808 mono_mb_emit_ldarg (mb, i + sig->hasthis);
2810 mono_mb_emit_native_call (mb, sig, (gpointer) func);
2812 mono_mb_emit_byte (mb, CEE_RET);
2814 csig = g_memdup (sig, sigsize);
2817 res = mono_mb_create_method (mb, csig, csig->param_count + 16);
2824 * mono_marshal_get_native_wrapper:
2825 * @method: The MonoMethod to wrap.
2827 * generates IL code for the pinvoke wrapper (the generated method
2828 * calls the unmanaged code in method->addr)
2831 mono_marshal_get_native_wrapper (MonoMethod *method)
2833 MonoMethodSignature *sig, *csig;
2834 MonoMethodPInvoke *piinfo;
2835 MonoMethodBuilder *mb;
2836 MonoMarshalSpec **mspecs;
2840 gboolean pinvoke = FALSE;
2841 int i, pos, argnum, *tmp_locals;
2843 const char *exc_class = "MissingMethodException";
2844 const char *exc_arg = NULL;
2846 g_assert (method != NULL);
2847 g_assert (method->signature->pinvoke);
2849 cache = method->klass->image->native_wrapper_cache;
2850 if ((res = mono_marshal_find_in_cache (cache, method)))
2853 sig = method->signature;
2854 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
2856 if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
2857 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2860 if (!method->addr) {
2862 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
2864 method->addr = mono_lookup_internal_call (method);
2867 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_MANAGED_TO_NATIVE);
2869 mb->method->save_lmf = 1;
2871 piinfo = (MonoMethodPInvoke *)method;
2873 if (!method->addr) {
2874 mono_mb_emit_exception (mb, exc_class, exc_arg);
2875 csig = g_memdup (sig, sigsize);
2877 res = mono_mb_create_and_cache (cache, method,
2878 mb, csig, csig->param_count + 16);
2883 /* internal calls: we simply push all arguments and call the method (no conversions) */
2884 if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
2886 /* hack - string constructors returns a value */
2887 if (method->string_ctor) {
2888 csig = g_memdup (sig, sigsize);
2889 csig->ret = &mono_defaults.string_class->byval_arg;
2894 mono_mb_emit_byte (mb, CEE_LDARG_0);
2896 for (i = 0; i < sig->param_count; i++)
2897 mono_mb_emit_ldarg (mb, i + sig->hasthis);
2899 g_assert (method->addr);
2900 mono_mb_emit_native_call (mb, csig, method->addr);
2902 mono_mb_emit_byte (mb, CEE_RET);
2904 csig = g_memdup (csig, sigsize);
2906 res = mono_mb_create_and_cache (cache, method,
2907 mb, csig, csig->param_count + 16);
2914 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
2915 mono_method_get_marshal_info (method, mspecs);
2917 /* pinvoke: we need to convert the arguments if necessary */
2919 /* we copy the signature, so that we can set pinvoke to 0 */
2920 csig = g_memdup (sig, sigsize);
2923 /* we allocate local for use with emit_struct_conv() */
2924 /* allocate local 0 (pointer) src_ptr */
2925 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2926 /* allocate local 1 (pointer) dst_ptr */
2927 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2928 /* allocate local 2 (boolean) delete_old */
2929 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2931 /* delete_old = FALSE */
2932 mono_mb_emit_icon (mb, 0);
2933 mono_mb_emit_byte (mb, CEE_STLOC_2);
2935 if (!MONO_TYPE_IS_VOID(sig->ret)) {
2936 /* allocate local 3 to store the return value */
2937 mono_mb_add_local (mb, sig->ret);
2940 /* we first do all conversions */
2941 tmp_locals = alloca (sizeof (int) * sig->param_count);
2943 for (i = 0; i < sig->param_count; i ++) {
2944 MonoType *t = sig->params [i];
2945 MonoMarshalSpec *spec = mspecs [i + 1];
2947 argnum = i + sig->hasthis;
2950 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
2953 MonoMethod *marshal_managed_to_native;
2954 MonoMethod *get_instance;
2956 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
2957 g_assert (mtype != NULL);
2958 mklass = mono_class_from_mono_type (mtype);
2959 g_assert (mklass != NULL);
2961 marshal_managed_to_native = mono_find_method_by_name (mklass, "MarshalManagedToNative", 1);
2962 g_assert (marshal_managed_to_native);
2963 get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
2964 g_assert (get_instance);
2967 case MONO_TYPE_CLASS:
2968 case MONO_TYPE_OBJECT:
2969 case MONO_TYPE_STRING:
2970 case MONO_TYPE_ARRAY:
2971 case MONO_TYPE_SZARRAY:
2975 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2977 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
2979 mono_mb_emit_byte (mb, CEE_CALL);
2980 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
2982 mono_mb_emit_ldarg (mb, argnum);
2984 mono_mb_emit_byte (mb, CEE_CALLVIRT);
2985 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_managed_to_native));
2987 mono_mb_emit_stloc (mb, tmp_locals [i]);
2990 g_warning ("custom marshalling of type %x is currently not supported", t->type);
2991 g_assert_not_reached ();
2999 case MONO_TYPE_VALUETYPE:
3000 klass = t->data.klass;
3002 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3003 klass->blittable || klass->enumtype)
3006 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3008 /* store the address of the source into local variable 0 */
3010 mono_mb_emit_ldarg (mb, argnum);
3012 mono_mb_emit_ldarg_addr (mb, argnum);
3014 mono_mb_emit_byte (mb, CEE_STLOC_0);
3016 /* allocate space for the native struct and
3017 * store the address into local variable 1 (dest) */
3018 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
3019 mono_mb_emit_byte (mb, CEE_PREFIX1);
3020 mono_mb_emit_byte (mb, CEE_LOCALLOC);
3021 mono_mb_emit_stloc (mb, tmp_locals [i]);
3024 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3025 mono_mb_emit_byte (mb, CEE_BRFALSE);
3027 mono_mb_emit_i4 (mb, 0);
3031 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3032 mono_mb_emit_byte (mb, CEE_STLOC_1);
3034 /* emit valuetype conversion code */
3035 emit_struct_conv (mb, klass, FALSE);
3038 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3040 case MONO_TYPE_STRING:
3041 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3042 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3045 if (t->attrs & PARAM_ATTRIBUTE_OUT)
3048 mono_mb_emit_ldarg (mb, argnum);
3049 mono_mb_emit_byte (mb, CEE_LDIND_I);
3051 mono_mb_emit_ldarg (mb, argnum);
3054 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3055 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3058 switch (spec->native) {
3059 case MONO_NATIVE_LPWSTR:
3060 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPWSTR);
3062 case MONO_NATIVE_LPSTR:
3063 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
3066 char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", spec->native);
3067 MonoException *exc = mono_get_exception_not_implemented (msg);
3070 mono_raise_exception (exc);
3074 switch (piinfo->piflags & PINVOKE_ATTRIBUTE_CHAR_SET_MASK) {
3075 case PINVOKE_ATTRIBUTE_CHAR_SET_ANSI:
3076 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
3078 case PINVOKE_ATTRIBUTE_CHAR_SET_UNICODE:
3079 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPWSTR);
3081 case PINVOKE_ATTRIBUTE_CHAR_SET_AUTO:
3082 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPTSTR);
3085 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
3090 mono_mb_emit_stloc (mb, tmp_locals [i]);
3092 case MONO_TYPE_CLASS:
3093 case MONO_TYPE_OBJECT:
3094 klass = t->data.klass;
3096 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3097 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3099 if (klass->delegate) {
3100 g_assert (!t->byref);
3101 mono_mb_emit_ldarg (mb, argnum);
3102 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3103 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3104 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_DEL_FTN);
3105 mono_mb_emit_stloc (mb, tmp_locals [i]);
3106 } else if (klass == mono_defaults.stringbuilder_class) {
3107 g_assert (!t->byref);
3108 mono_mb_emit_ldarg (mb, argnum);
3109 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3110 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3111 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_SB_LPSTR);
3112 mono_mb_emit_stloc (mb, tmp_locals [i]);
3114 mono_mb_emit_byte (mb, CEE_LDNULL);
3115 mono_mb_emit_stloc (mb, tmp_locals [i]);
3118 /* we dont need any conversions for out parameters */
3119 if (t->attrs & PARAM_ATTRIBUTE_OUT)
3122 mono_mb_emit_ldarg (mb, argnum);
3123 mono_mb_emit_byte (mb, CEE_LDIND_I);
3126 mono_mb_emit_ldarg (mb, argnum);
3127 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3128 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
3131 /* store the address of the source into local variable 0 */
3132 mono_mb_emit_byte (mb, CEE_STLOC_0);
3133 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3134 mono_mb_emit_byte (mb, CEE_BRFALSE);
3136 mono_mb_emit_i4 (mb, 0);
3138 /* allocate space for the native struct and store the address */
3139 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
3140 mono_mb_emit_byte (mb, CEE_PREFIX1);
3141 mono_mb_emit_byte (mb, CEE_LOCALLOC);
3142 mono_mb_emit_stloc (mb, tmp_locals [i]);
3144 /* set the src_ptr */
3145 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3146 mono_mb_emit_icon (mb, sizeof (MonoObject));
3147 mono_mb_emit_byte (mb, CEE_ADD);
3148 mono_mb_emit_byte (mb, CEE_STLOC_0);
3151 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3152 mono_mb_emit_byte (mb, CEE_STLOC_1);
3154 /* emit valuetype conversion code */
3155 emit_struct_conv (mb, klass, FALSE);
3157 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3161 case MONO_TYPE_ARRAY:
3162 case MONO_TYPE_SZARRAY:
3166 klass = mono_class_from_mono_type (t);
3168 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3169 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3171 if (klass->element_class == mono_defaults.string_class) {
3172 mono_mb_emit_ldarg (mb, argnum);
3173 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3174 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3176 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STRARRAY_STRLPARRAY);
3177 mono_mb_emit_stloc (mb, tmp_locals [i]);
3179 else if (klass->element_class->blittable) {
3180 mono_mb_emit_ldarg (mb, argnum);
3181 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3182 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3184 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_ARRAY_LPARRAY);
3185 mono_mb_emit_stloc (mb, tmp_locals [i]);
3189 guint32 label1, label2, label3;
3190 int index_var, dest_ptr;
3192 dest_ptr = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3195 mono_mb_emit_ldarg (mb, argnum);
3196 mono_mb_emit_stloc (mb, tmp_locals [i]);
3197 mono_mb_emit_ldarg (mb, argnum);
3198 mono_mb_emit_byte (mb, CEE_BRFALSE);
3200 mono_mb_emit_i4 (mb, 0);
3202 /* allocate space for the native struct and store the address */
3203 eklass = klass->element_class;
3204 mono_mb_emit_icon (mb, mono_class_native_size (eklass, NULL));
3205 mono_mb_emit_ldarg (mb, argnum);
3206 mono_mb_emit_byte (mb, CEE_LDLEN);
3207 mono_mb_emit_byte (mb, CEE_MUL);
3208 mono_mb_emit_byte (mb, CEE_PREFIX1);
3209 mono_mb_emit_byte (mb, CEE_LOCALLOC);
3210 mono_mb_emit_stloc (mb, tmp_locals [i]);
3212 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3213 mono_mb_emit_stloc (mb, dest_ptr);
3215 /* Emit marshalling loop */
3216 index_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3217 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
3218 mono_mb_emit_stloc (mb, index_var);
3220 mono_mb_emit_ldloc (mb, index_var);
3221 mono_mb_emit_ldarg (mb, argnum);
3222 mono_mb_emit_byte (mb, CEE_LDLEN);
3223 mono_mb_emit_byte (mb, CEE_BGE);
3225 mono_mb_emit_i4 (mb, 0);
3227 /* Emit marshalling code */
3229 /* set the src_ptr */
3230 mono_mb_emit_ldarg (mb, argnum);
3231 mono_mb_emit_ldloc (mb, index_var);
3232 mono_mb_emit_byte (mb, CEE_LDELEMA);
3233 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eklass));
3234 mono_mb_emit_byte (mb, CEE_STLOC_0);
3237 mono_mb_emit_ldloc (mb, dest_ptr);
3238 mono_mb_emit_byte (mb, CEE_STLOC_1);
3240 /* emit valuetype conversion code */
3241 emit_struct_conv (mb, eklass, FALSE);
3243 mono_mb_emit_add_to_local (mb, index_var, 1);
3244 mono_mb_emit_add_to_local (mb, dest_ptr, mono_class_native_size (eklass, NULL));
3246 mono_mb_emit_byte (mb, CEE_BR);
3247 mono_mb_emit_i4 (mb, label2 - (mb->pos + 4));
3249 mono_mb_patch_addr (mb, label1, mb->pos - (label1 + 4));
3250 mono_mb_patch_addr (mb, label3, mb->pos - (label3 + 4));
3254 case MONO_TYPE_BOOLEAN: {
3255 MonoType *local_type;
3256 int variant_bool = 0;
3260 local_type = &mono_defaults.int32_class->byval_arg;
3262 switch (spec->native) {
3263 case MONO_NATIVE_I1:
3264 local_type = &mono_defaults.byte_class->byval_arg;
3266 case MONO_NATIVE_VARIANTBOOL:
3267 local_type = &mono_defaults.int16_class->byval_arg;
3271 g_warning ("marshalling bool as native type %x is currently not supported", spec->native);
3275 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3276 tmp_locals [i] = mono_mb_add_local (mb, local_type);
3277 mono_mb_emit_ldarg (mb, argnum);
3278 mono_mb_emit_byte (mb, CEE_LDIND_I1);
3280 mono_mb_emit_byte (mb, CEE_NEG);
3281 mono_mb_emit_stloc (mb, tmp_locals [i]);
3287 /* push all arguments */
3290 mono_mb_emit_byte (mb, CEE_LDARG_0);
3292 for (i = 0; i < sig->param_count; i++) {
3293 MonoType *t = sig->params [i];
3295 argnum = i + sig->hasthis;
3298 case MONO_TYPE_BOOLEAN:
3300 g_assert (tmp_locals [i]);
3301 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
3303 mono_mb_emit_ldarg (mb, argnum);
3318 mono_mb_emit_ldarg (mb, argnum);
3320 case MONO_TYPE_VALUETYPE:
3321 klass = sig->params [i]->data.klass;
3322 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3323 klass->blittable || klass->enumtype) {
3324 mono_mb_emit_ldarg (mb, argnum);
3327 g_assert (tmp_locals [i]);
3328 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3330 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3331 mono_mb_emit_byte (mb, CEE_MONO_LDNATIVEOBJ);
3332 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3335 case MONO_TYPE_STRING:
3336 case MONO_TYPE_CLASS:
3337 case MONO_TYPE_OBJECT:
3338 g_assert (tmp_locals [i]);
3340 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
3342 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3344 case MONO_TYPE_CHAR:
3345 /* fixme: dont know how to marshal that. We cant simply
3346 * convert it to a one byte UTF8 character, because an
3347 * unicode character may need more that one byte in UTF8 */
3348 mono_mb_emit_ldarg (mb, argnum);
3350 case MONO_TYPE_ARRAY:
3351 case MONO_TYPE_SZARRAY:
3353 mono_mb_emit_ldarg (mb, argnum);
3355 g_assert (tmp_locals [i]);
3356 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3359 case MONO_TYPE_TYPEDBYREF:
3360 case MONO_TYPE_FNPTR:
3362 g_warning ("type 0x%02x unknown", t->type);
3363 g_assert_not_reached ();
3367 /* call the native method */
3368 mono_mb_emit_native_call (mb, csig, method->addr);
3370 /* Set LastError if needed */
3371 if (piinfo->piflags & PINVOKE_ATTRIBUTE_SUPPORTS_LAST_ERROR) {
3372 MonoMethodSignature *lasterr_sig;
3374 lasterr_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
3375 lasterr_sig->ret = &mono_defaults.void_class->byval_arg;
3376 lasterr_sig->pinvoke = 1;
3378 mono_mb_emit_native_call (mb, lasterr_sig, mono_marshal_set_last_error);
3381 /* convert the result */
3382 if (!sig->ret->byref) {
3383 MonoMarshalSpec *spec = mspecs [0];
3384 type = sig->ret->type;
3386 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
3389 MonoMethod *marshal_native_to_managed;
3390 MonoMethod *get_instance;
3392 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
3393 g_assert (mtype != NULL);
3394 mklass = mono_class_from_mono_type (mtype);
3395 g_assert (mklass != NULL);
3397 marshal_native_to_managed = mono_find_method_by_name (mklass, "MarshalNativeToManaged", 1);
3398 g_assert (marshal_native_to_managed);
3399 get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
3400 g_assert (get_instance);
3403 case MONO_TYPE_CLASS:
3404 case MONO_TYPE_OBJECT:
3405 case MONO_TYPE_STRING:
3406 case MONO_TYPE_ARRAY:
3407 case MONO_TYPE_SZARRAY:
3408 mono_mb_emit_byte (mb, CEE_STLOC_3);
3410 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
3412 mono_mb_emit_byte (mb, CEE_CALL);
3413 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
3415 mono_mb_emit_byte (mb, CEE_LDLOC_3);
3417 mono_mb_emit_byte (mb, CEE_CALLVIRT);
3418 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_native_to_managed));
3420 mono_mb_emit_byte (mb, CEE_STLOC_3);
3423 g_warning ("custom marshalling of type %x is currently not supported", type);
3424 g_assert_not_reached ();
3431 case MONO_TYPE_VOID:
3446 /* no conversions necessary */
3447 mono_mb_emit_byte (mb, CEE_STLOC_3);
3449 case MONO_TYPE_BOOLEAN:
3450 /* maybe we need to make sure that it fits within 8 bits */
3451 mono_mb_emit_byte (mb, CEE_STLOC_3);
3453 case MONO_TYPE_VALUETYPE:
3454 klass = sig->ret->data.klass;
3455 if (klass->enumtype) {
3456 type = sig->ret->data.klass->enum_basetype->type;
3460 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3462 mono_mb_emit_byte (mb, CEE_STLOC_3);
3465 /* load pointer to returned value type */
3466 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3467 mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
3468 /* store the address of the source into local variable 0 */
3469 mono_mb_emit_byte (mb, CEE_STLOC_0);
3471 mono_mb_emit_ldloc_addr (mb, 3);
3472 mono_mb_emit_byte (mb, CEE_STLOC_1);
3474 /* emit valuetype conversion code */
3475 emit_struct_conv (mb, sig->ret->data.klass, TRUE);
3477 case MONO_TYPE_STRING:
3478 #ifdef GTK_SHARP_FIXED
3479 mono_mb_emit_byte (mb, CEE_STLOC_0);
3480 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3483 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3484 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3486 switch (spec->native) {
3487 case MONO_NATIVE_LPWSTR:
3488 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPWSTR_STR);
3491 g_warning ("marshalling conversion not implemented");
3492 g_assert_not_reached ();
3495 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
3497 mono_mb_emit_byte (mb, CEE_STLOC_3);
3499 #ifdef GTK_SHARP_FIXED
3500 /* free the string */
3501 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3502 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3503 mono_mb_emit_byte (mb, CEE_MONO_FREE);
3506 case MONO_TYPE_CLASS:
3507 case MONO_TYPE_OBJECT:
3508 klass = sig->ret->data.klass;
3511 mono_mb_emit_byte (mb, CEE_STLOC_0);
3513 mono_mb_emit_byte (mb, CEE_LDNULL);
3514 mono_mb_emit_byte (mb, CEE_STLOC_3);
3517 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3518 mono_mb_emit_byte (mb, CEE_BRFALSE);
3520 mono_mb_emit_i4 (mb, 0);
3522 /* allocate result object */
3524 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3525 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
3526 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3527 mono_mb_emit_byte (mb, CEE_STLOC_3);
3531 mono_mb_emit_byte (mb, CEE_LDLOC_3);
3532 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3533 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
3534 mono_mb_emit_icon (mb, sizeof (MonoObject));
3535 mono_mb_emit_byte (mb, CEE_ADD);
3536 mono_mb_emit_byte (mb, CEE_STLOC_1);
3538 /* emit conversion code */
3539 emit_struct_conv (mb, klass, TRUE);
3541 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3543 case MONO_TYPE_ARRAY:
3544 case MONO_TYPE_SZARRAY:
3545 /* fixme: we need conversions here */
3546 mono_mb_emit_byte (mb, CEE_STLOC_3);
3548 case MONO_TYPE_CHAR:
3549 /* fixme: we need conversions here */
3550 mono_mb_emit_byte (mb, CEE_STLOC_3);
3552 case MONO_TYPE_TYPEDBYREF:
3553 case MONO_TYPE_FNPTR:
3555 g_warning ("return type 0x%02x unknown", sig->ret->type);
3556 g_assert_not_reached ();
3560 mono_mb_emit_byte (mb, CEE_STLOC_3);
3563 /* we need to convert byref arguments back and free string arrays */
3564 for (i = 0; i < sig->param_count; i++) {
3565 MonoType *t = sig->params [i];
3567 argnum = i + sig->hasthis;
3570 case MONO_TYPE_STRING:
3571 if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT)) {
3572 mono_mb_emit_ldarg (mb, argnum);
3573 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3574 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3575 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3576 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
3577 mono_mb_emit_byte (mb, CEE_STIND_I);
3579 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3580 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3581 mono_mb_emit_byte (mb, CEE_MONO_FREE);
3584 case MONO_TYPE_CLASS:
3585 case MONO_TYPE_OBJECT:
3586 if (t->data.klass == mono_defaults.stringbuilder_class) {
3587 g_assert (!t->byref);
3588 mono_mb_emit_ldarg (mb, argnum);
3589 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3590 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3591 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
3592 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_SB);
3593 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3594 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3595 mono_mb_emit_byte (mb, CEE_MONO_FREE);
3599 if (!(t->byref || (t->attrs & PARAM_ATTRIBUTE_OUT)))
3602 if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT)) {
3603 /* allocate a new object new object */
3604 mono_mb_emit_ldarg (mb, argnum);
3605 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3606 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
3607 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3608 mono_mb_emit_byte (mb, CEE_STIND_I);
3611 /* dst = *argument */
3612 mono_mb_emit_ldarg (mb, argnum);
3615 mono_mb_emit_byte (mb, CEE_LDIND_I);
3617 mono_mb_emit_byte (mb, CEE_STLOC_1);
3619 mono_mb_emit_byte (mb, CEE_LDLOC_1);
3620 mono_mb_emit_byte (mb, CEE_BRFALSE);
3622 mono_mb_emit_i4 (mb, 0);
3624 mono_mb_emit_byte (mb, CEE_LDLOC_1);
3625 mono_mb_emit_icon (mb, sizeof (MonoObject));
3626 mono_mb_emit_byte (mb, CEE_ADD);
3627 mono_mb_emit_byte (mb, CEE_STLOC_1);
3629 /* src = tmp_locals [i] */
3630 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3631 mono_mb_emit_byte (mb, CEE_STLOC_0);
3633 /* emit valuetype conversion code */
3634 emit_struct_conv (mb, klass, TRUE);
3636 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3638 case MONO_TYPE_VALUETYPE:
3642 klass = t->data.klass;
3643 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3644 klass->blittable || klass->enumtype)
3647 /* dst = argument */
3648 mono_mb_emit_ldarg (mb, argnum);
3649 mono_mb_emit_byte (mb, CEE_STLOC_1);
3651 mono_mb_emit_byte (mb, CEE_LDLOC_1);
3652 mono_mb_emit_byte (mb, CEE_BRFALSE);
3654 mono_mb_emit_i4 (mb, 0);
3656 /* src = tmp_locals [i] */
3657 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3658 mono_mb_emit_byte (mb, CEE_STLOC_0);
3660 /* emit valuetype conversion code */
3661 emit_struct_conv (mb, klass, TRUE);
3663 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3665 case MONO_TYPE_SZARRAY:
3669 klass = mono_class_from_mono_type (t);
3671 if (klass->element_class == mono_defaults.string_class) {
3672 g_assert (tmp_locals [i]);
3674 mono_mb_emit_ldarg (mb, argnum);
3675 mono_mb_emit_byte (mb, CEE_BRFALSE);
3677 mono_mb_emit_i4 (mb, 0);
3679 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3680 mono_mb_emit_ldarg (mb, argnum);
3681 mono_mb_emit_byte (mb, CEE_LDLEN);
3682 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3683 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
3684 mono_mb_emit_byte (mb, MONO_MARSHAL_FREE_ARRAY);
3686 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3689 if (t->attrs & PARAM_ATTRIBUTE_OUT) {
3690 /* FIXME: Optimize blittable case */
3692 guint32 label1, label2, label3;
3693 int index_var, src_ptr;
3695 eklass = klass->element_class;
3696 src_ptr = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3699 mono_mb_emit_ldarg (mb, argnum);
3700 mono_mb_emit_byte (mb, CEE_BRFALSE);
3702 mono_mb_emit_i4 (mb, 0);
3704 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3705 mono_mb_emit_stloc (mb, src_ptr);
3707 /* Emit marshalling loop */
3708 index_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3709 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
3710 mono_mb_emit_stloc (mb, index_var);
3712 mono_mb_emit_ldloc (mb, index_var);
3713 mono_mb_emit_ldarg (mb, argnum);
3714 mono_mb_emit_byte (mb, CEE_LDLEN);
3715 mono_mb_emit_byte (mb, CEE_BGE);
3717 mono_mb_emit_i4 (mb, 0);
3719 /* Emit marshalling code */
3721 /* set the src_ptr */
3722 mono_mb_emit_ldloc (mb, src_ptr);
3723 mono_mb_emit_byte (mb, CEE_STLOC_0);
3726 mono_mb_emit_ldarg (mb, argnum);
3727 mono_mb_emit_ldloc (mb, index_var);
3728 mono_mb_emit_byte (mb, CEE_LDELEMA);
3729 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eklass));
3730 mono_mb_emit_byte (mb, CEE_STLOC_1);
3732 /* emit valuetype conversion code */
3733 emit_struct_conv (mb, eklass, TRUE);
3735 mono_mb_emit_add_to_local (mb, index_var, 1);
3736 mono_mb_emit_add_to_local (mb, src_ptr, mono_class_native_size (eklass, NULL));
3738 mono_mb_emit_byte (mb, CEE_BR);
3739 mono_mb_emit_i4 (mb, label2 - (mb->pos + 4));
3741 mono_mb_patch_addr (mb, label1, mb->pos - (label1 + 4));
3742 mono_mb_patch_addr (mb, label3, mb->pos - (label3 + 4));
3745 case MONO_TYPE_BOOLEAN:
3748 mono_mb_emit_ldarg (mb, argnum);
3749 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3750 if (mspecs [i + 1] != NULL && mspecs [i + 1]->native == MONO_NATIVE_VARIANTBOOL)
3751 mono_mb_emit_byte (mb, CEE_NEG);
3752 mono_mb_emit_byte (mb, CEE_STIND_I1);
3756 if (!MONO_TYPE_IS_VOID(sig->ret))
3757 mono_mb_emit_byte (mb, CEE_LDLOC_3);
3759 mono_mb_emit_byte (mb, CEE_RET);
3761 csig = g_memdup (sig, sigsize);
3763 res = mono_mb_create_and_cache (cache, method,
3764 mb, csig, csig->param_count + 16);
3767 for (i = sig->param_count; i >= 0; i--)
3768 g_free (mspecs [i]);
3771 //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));
3777 * mono_marshal_get_struct_to_ptr:
3780 * generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld)
3783 mono_marshal_get_struct_to_ptr (MonoClass *klass)
3785 MonoMethodBuilder *mb;
3786 static MonoMethod *stoptr = NULL;
3789 g_assert (klass != NULL);
3791 if (klass->str_to_ptr)
3792 return klass->str_to_ptr;
3795 stoptr = mono_find_method_by_name (mono_defaults.marshal_class, "StructureToPtr", 3);
3798 mb = mono_mb_new (klass, stoptr->name, MONO_WRAPPER_UNKNOWN);
3800 if (klass->blittable) {
3801 mono_mb_emit_byte (mb, CEE_LDARG_1);
3802 mono_mb_emit_byte (mb, CEE_LDARG_0);
3803 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3804 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
3805 mono_mb_emit_byte (mb, CEE_PREFIX1);
3806 mono_mb_emit_byte (mb, CEE_CPBLK);
3809 /* allocate local 0 (pointer) src_ptr */
3810 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3811 /* allocate local 1 (pointer) dst_ptr */
3812 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3813 /* allocate local 2 (boolean) delete_old */
3814 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
3815 mono_mb_emit_byte (mb, CEE_LDARG_2);
3816 mono_mb_emit_byte (mb, CEE_STLOC_2);
3818 /* initialize src_ptr to point to the start of object data */
3819 mono_mb_emit_byte (mb, CEE_LDARG_0);
3820 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3821 mono_mb_emit_byte (mb, CEE_STLOC_0);
3823 /* initialize dst_ptr */
3824 mono_mb_emit_byte (mb, CEE_LDARG_1);
3825 mono_mb_emit_byte (mb, CEE_STLOC_1);
3827 emit_struct_conv (mb, klass, FALSE);
3830 mono_mb_emit_byte (mb, CEE_RET);
3832 res = mono_mb_create_method (mb, stoptr->signature, 0);
3835 klass->str_to_ptr = res;
3840 * mono_marshal_get_ptr_to_struct:
3843 * generates IL code for PtrToStructure (IntPtr src, object structure)
3846 mono_marshal_get_ptr_to_struct (MonoClass *klass)
3848 MonoMethodBuilder *mb;
3849 static MonoMethod *ptostr = NULL;
3852 g_assert (klass != NULL);
3854 if (klass->ptr_to_str)
3855 return klass->ptr_to_str;
3858 ptostr = mono_find_method_by_name (mono_defaults.marshal_class, "PtrToStructure", 2);
3861 mb = mono_mb_new (klass, ptostr->name, MONO_WRAPPER_UNKNOWN);
3863 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable) {
3864 mono_mb_emit_byte (mb, CEE_LDARG_1);
3865 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3866 mono_mb_emit_byte (mb, CEE_LDARG_0);
3867 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
3868 mono_mb_emit_byte (mb, CEE_PREFIX1);
3869 mono_mb_emit_byte (mb, CEE_CPBLK);
3872 /* allocate local 0 (pointer) src_ptr */
3873 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3874 /* allocate local 1 (pointer) dst_ptr */
3875 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3877 /* initialize src_ptr to point to the start of object data */
3878 mono_mb_emit_byte (mb, CEE_LDARG_0);
3879 mono_mb_emit_byte (mb, CEE_STLOC_0);
3881 /* initialize dst_ptr */
3882 mono_mb_emit_byte (mb, CEE_LDARG_1);
3883 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3884 mono_mb_emit_byte (mb, CEE_STLOC_1);
3886 emit_struct_conv (mb, klass, TRUE);
3889 mono_mb_emit_byte (mb, CEE_RET);
3891 res = mono_mb_create_method (mb, ptostr->signature, 0);
3894 klass->ptr_to_str = res;
3898 static MonoReflectionType *
3899 type_from_handle (MonoType *handle)
3901 MonoDomain *domain = mono_domain_get ();
3902 MonoClass *klass = mono_class_from_mono_type (handle);
3904 MONO_ARCH_SAVE_REGS;
3906 mono_class_init (klass);
3907 return mono_type_get_object (domain, handle);
3911 * generates IL code for the synchronized wrapper: the generated method
3912 * calls METHOD while locking 'this' or the parent type.
3915 mono_marshal_get_synchronized_wrapper (MonoMethod *method)
3917 static MonoMethodSignature *from_handle_sig = NULL;
3918 static MonoMethod *enter_method, *exit_method;
3919 MonoMethodSignature *sig;
3920 MonoExceptionClause *clause;
3921 MonoMethodHeader *header;
3922 MonoMethodBuilder *mb;
3925 int i, pos, this_local, ret_local;
3929 if (method->wrapper_type == MONO_WRAPPER_SYNCHRONIZED)
3932 cache = method->klass->image->synchronized_cache;
3933 if ((res = mono_marshal_find_in_cache (cache, method)))
3936 sig = method->signature;
3938 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_SYNCHRONIZED);
3941 if (!MONO_TYPE_IS_VOID (sig->ret))
3942 ret_local = mono_mb_add_local (mb, sig->ret);
3945 this_local = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
3947 clause = g_new0 (MonoExceptionClause, 1);
3948 clause->flags = MONO_EXCEPTION_CLAUSE_FINALLY;
3950 if (!enter_method) {
3951 MonoMethodDesc *desc;
3953 desc = mono_method_desc_new ("Monitor:Enter", FALSE);
3954 enter_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
3955 g_assert (enter_method);
3956 mono_method_desc_free (desc);
3957 desc = mono_method_desc_new ("Monitor:Exit", FALSE);
3958 exit_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
3959 g_assert (exit_method);
3960 mono_method_desc_free (desc);
3963 * GetTypeFromHandle isn't called as a managed method because it has
3964 * a funky calling sequence, e.g. ldtoken+GetTypeFromHandle gets
3965 * transformed into something else by the JIT.
3967 from_handle_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
3968 from_handle_sig->params [0] = &mono_defaults.object_class->byval_arg;
3969 from_handle_sig->ret = &mono_defaults.object_class->byval_arg;
3972 /* Push this or the type object */
3973 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3974 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3975 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
3976 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, &method->klass->byval_arg));
3977 mono_mb_emit_native_call (mb, from_handle_sig, type_from_handle);
3980 mono_mb_emit_ldarg (mb, 0);
3981 mono_mb_emit_stloc (mb, this_local);
3983 /* Call Monitor::Enter() */
3984 mono_mb_emit_ldloc (mb, this_local);
3985 mono_mb_emit_managed_call (mb, enter_method, NULL);
3987 clause->try_offset = mb->pos;
3989 /* Call the method */
3991 mono_mb_emit_ldarg (mb, 0);
3992 for (i = 0; i < sig->param_count; i++)
3993 mono_mb_emit_ldarg (mb, i + (sig->hasthis == TRUE));
3994 mono_mb_emit_managed_call (mb, method, method->signature);
3995 if (!MONO_TYPE_IS_VOID (sig->ret))
3996 mono_mb_emit_stloc (mb, ret_local);
3998 mono_mb_emit_byte (mb, CEE_LEAVE);
4000 mono_mb_emit_i4 (mb, 0);
4002 clause->try_len = mb->pos - clause->try_offset;
4003 clause->handler_offset = mb->pos;
4005 /* Call Monitor::Exit() */
4006 mono_mb_emit_ldloc (mb, this_local);
4007 // mono_mb_emit_native_call (mb, exit_sig, mono_monitor_exit);
4008 mono_mb_emit_managed_call (mb, exit_method, NULL);
4009 mono_mb_emit_byte (mb, CEE_ENDFINALLY);
4011 clause->handler_len = mb->pos - clause->handler_offset;
4013 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
4014 if (!MONO_TYPE_IS_VOID (sig->ret))
4015 mono_mb_emit_ldloc (mb, ret_local);
4016 mono_mb_emit_byte (mb, CEE_RET);
4018 res = mono_mb_create_and_cache (cache, method,
4019 mb, sig, sig->param_count + 16);
4022 header = ((MonoMethodNormal *)res)->header;
4023 header->num_clauses = 1;
4024 header->clauses = clause;
4029 /* FIXME: on win32 we should probably use GlobalAlloc(). */
4031 mono_marshal_alloc (gpointer size)
4033 MONO_ARCH_SAVE_REGS;
4035 return g_try_malloc ((gulong)size);
4039 mono_marshal_free (gpointer ptr)
4041 MONO_ARCH_SAVE_REGS;
4047 mono_marshal_free_array (gpointer *ptr, int size)
4054 for (i = 0; i < size; i++)
4060 mono_marshal_realloc (gpointer ptr, gpointer size)
4062 MONO_ARCH_SAVE_REGS;
4064 return g_try_realloc (ptr, (gulong)size);
4068 mono_marshal_string_array (MonoArray *array)
4076 len = mono_array_length (array);
4078 result = g_malloc (sizeof (char *) * (len + 1));
4079 for (i = 0; i < len; ++i) {
4080 MonoString *s = (MonoString *)mono_array_get (array, gpointer, i);
4081 result [i] = s ? mono_string_to_utf8 (s): NULL;
4083 /* null terminate the array */
4090 * mono_marshal_set_last_error:
4092 * This function is invoked to set the last error value from a P/Invoke call
4093 * which has SetLastError set.
4096 mono_marshal_set_last_error (void)
4099 TlsSetValue (last_error_tls_id, (gpointer)GetLastError ());
4101 TlsSetValue (last_error_tls_id, (gpointer)errno);
4106 ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArray *src, gint32 start_index,
4107 gpointer dest, gint32 length)
4112 MONO_ARCH_SAVE_REGS;
4114 MONO_CHECK_ARG_NULL (src);
4115 MONO_CHECK_ARG_NULL (dest);
4117 g_assert (src->obj.vtable->klass->rank == 1);
4118 g_assert (start_index >= 0);
4119 g_assert (length >= 0);
4120 g_assert (start_index + length <= mono_array_length (src));
4122 element_size = mono_array_element_size (src->obj.vtable->klass);
4124 source_addr = mono_array_addr_with_size (src, element_size, start_index);
4126 memcpy (dest, source_addr, length * element_size);
4130 ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer src, gint32 start_index,
4131 MonoArray *dest, gint32 length)
4136 MONO_ARCH_SAVE_REGS;
4138 MONO_CHECK_ARG_NULL (src);
4139 MONO_CHECK_ARG_NULL (dest);
4141 g_assert (dest->obj.vtable->klass->rank == 1);
4142 g_assert (start_index >= 0);
4143 g_assert (length >= 0);
4144 g_assert (start_index + length <= mono_array_length (dest));
4146 element_size = mono_array_element_size (dest->obj.vtable->klass);
4148 dest_addr = mono_array_addr_with_size (dest, element_size, start_index);
4150 memcpy (dest_addr, src, length * element_size);
4153 #if NO_UNALIGNED_ACCESS
4154 #define RETURN_UNALIGNED(type, addr) \
4157 memcpy(&val, p + offset, sizeof(val)); \
4160 #define WRITE_UNALIGNED(type, addr, val) \
4161 memcpy(addr, &val, sizeof(type))
4163 #define RETURN_UNALIGNED(type, addr) \
4164 return *(type*)(p + offset);
4165 #define WRITE_UNALIGNED(type, addr, val) \
4166 (*(type *)(addr) = (val))
4170 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr, gint32 offset)
4174 MONO_ARCH_SAVE_REGS;
4176 RETURN_UNALIGNED(gpointer, p + offset);
4180 ves_icall_System_Runtime_InteropServices_Marshal_ReadByte (gpointer ptr, gint32 offset)
4184 MONO_ARCH_SAVE_REGS;
4186 return *(unsigned char*)(p + offset);
4190 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt16 (gpointer ptr, gint32 offset)
4194 MONO_ARCH_SAVE_REGS;
4196 RETURN_UNALIGNED(gint16, p + offset);
4200 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt32 (gpointer ptr, gint32 offset)
4204 MONO_ARCH_SAVE_REGS;
4206 RETURN_UNALIGNED(gint32, p + offset);
4210 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt64 (gpointer ptr, gint32 offset)
4214 MONO_ARCH_SAVE_REGS;
4216 RETURN_UNALIGNED(gint64, p + offset);
4220 ves_icall_System_Runtime_InteropServices_Marshal_WriteByte (gpointer ptr, gint32 offset, unsigned char val)
4224 MONO_ARCH_SAVE_REGS;
4226 *(unsigned char*)(p + offset) = val;
4230 ves_icall_System_Runtime_InteropServices_Marshal_WriteIntPtr (gpointer ptr, gint32 offset, gpointer val)
4234 MONO_ARCH_SAVE_REGS;
4236 WRITE_UNALIGNED(gpointer, p + offset, val);
4240 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt16 (gpointer ptr, gint32 offset, gint16 val)
4244 MONO_ARCH_SAVE_REGS;
4246 WRITE_UNALIGNED(gint16, p + offset, val);
4250 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt32 (gpointer ptr, gint32 offset, gint32 val)
4254 MONO_ARCH_SAVE_REGS;
4256 WRITE_UNALIGNED(gint32, p + offset, val);
4260 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt64 (gpointer ptr, gint32 offset, gint64 val)
4264 MONO_ARCH_SAVE_REGS;
4266 WRITE_UNALIGNED(gint64, p + offset, val);
4270 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (char *ptr)
4272 MONO_ARCH_SAVE_REGS;
4274 return mono_string_new (mono_domain_get (), ptr);
4278 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len (char *ptr, gint32 len)
4280 MONO_ARCH_SAVE_REGS;
4282 return mono_string_new_len (mono_domain_get (), ptr, len);
4286 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni (guint16 *ptr)
4288 MonoDomain *domain = mono_domain_get ();
4292 MONO_ARCH_SAVE_REGS;
4297 return mono_string_new_utf16 (domain, ptr, len);
4301 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len (guint16 *ptr, gint32 len)
4303 MonoDomain *domain = mono_domain_get ();
4305 MONO_ARCH_SAVE_REGS;
4307 return mono_string_new_utf16 (domain, ptr, len);
4311 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR (gpointer ptr)
4313 MONO_ARCH_SAVE_REGS;
4315 g_warning ("PtrToStringBSTR not implemented");
4316 g_assert_not_reached ();
4322 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
4324 MONO_ARCH_SAVE_REGS;
4326 return ((guint32)TlsGetValue (last_error_tls_id));
4330 ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype)
4334 MONO_ARCH_SAVE_REGS;
4336 MONO_CHECK_ARG_NULL (rtype);
4338 klass = mono_class_from_mono_type (rtype->type);
4340 return mono_class_native_size (klass, NULL);
4344 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old)
4349 MONO_ARCH_SAVE_REGS;
4351 MONO_CHECK_ARG_NULL (obj);
4352 MONO_CHECK_ARG_NULL (dst);
4354 method = mono_marshal_get_struct_to_ptr (obj->vtable->klass);
4358 pa [2] = &delete_old;
4360 mono_runtime_invoke (method, NULL, pa, NULL);
4364 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, MonoObject *dst)
4369 MONO_ARCH_SAVE_REGS;
4371 MONO_CHECK_ARG_NULL (src);
4372 MONO_CHECK_ARG_NULL (dst);
4374 method = mono_marshal_get_ptr_to_struct (dst->vtable->klass);
4379 mono_runtime_invoke (method, NULL, pa, NULL);
4383 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer src, MonoReflectionType *type)
4385 MonoDomain *domain = mono_domain_get ();
4388 MONO_ARCH_SAVE_REGS;
4390 MONO_CHECK_ARG_NULL (src);
4391 MONO_CHECK_ARG_NULL (type);
4393 res = mono_object_new (domain, mono_class_from_mono_type (type->type));
4395 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (src, res);
4401 ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *type, MonoString *field_name)
4403 MonoMarshalType *info;
4406 int i, match_index = -1;
4408 MONO_ARCH_SAVE_REGS;
4410 MONO_CHECK_ARG_NULL (type);
4411 MONO_CHECK_ARG_NULL (field_name);
4413 fname = mono_string_to_utf8 (field_name);
4414 klass = mono_class_from_mono_type (type->type);
4416 while(klass && match_index == -1) {
4417 for (i = 0; i < klass->field.count; ++i) {
4418 if (*fname == *klass->fields [i].name && strcmp (fname, klass->fields [i].name) == 0) {
4424 if(match_index == -1)
4425 klass = klass->parent;
4430 if(match_index == -1) {
4434 /* Get back original class instance */
4435 klass = mono_class_from_mono_type (type->type);
4437 tmp = g_strdup_printf ("Field passed in is not a marshaled member of the type %s", klass->name);
4438 exc = mono_get_exception_argument ("fieldName", tmp);
4441 mono_raise_exception ((MonoException*)exc);
4444 info = mono_marshal_load_type_info (klass);
4445 return info->fields [match_index].offset;
4449 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString *string)
4451 MONO_ARCH_SAVE_REGS;
4453 return mono_string_to_utf8 (string);
4457 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni (MonoString *string)
4459 MONO_ARCH_SAVE_REGS;
4461 return g_memdup (mono_string_chars (string), mono_string_length (string)*2);
4465 mono_struct_delete_old (MonoClass *klass, char *ptr)
4467 MonoMarshalType *info;
4470 info = mono_marshal_load_type_info (klass);
4472 for (i = 0; i < info->num_fields; i++) {
4473 MonoMarshalNative ntype;
4474 MonoMarshalConv conv;
4475 MonoType *ftype = info->fields [i].field->type;
4478 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
4481 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE,
4482 klass->unicode, &conv);
4484 cpos = ptr + info->fields [i].offset;
4487 case MONO_MARSHAL_CONV_NONE:
4488 if (MONO_TYPE_ISSTRUCT (ftype)) {
4489 mono_struct_delete_old (ftype->data.klass, cpos);
4493 case MONO_MARSHAL_CONV_STR_LPWSTR:
4494 case MONO_MARSHAL_CONV_STR_LPSTR:
4495 case MONO_MARSHAL_CONV_STR_LPTSTR:
4496 case MONO_MARSHAL_CONV_STR_BSTR:
4497 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
4498 case MONO_MARSHAL_CONV_STR_TBSTR:
4499 g_free (*(gpointer *)cpos);
4508 ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure (gpointer src, MonoReflectionType *type)
4512 MONO_ARCH_SAVE_REGS;
4514 MONO_CHECK_ARG_NULL (src);
4515 MONO_CHECK_ARG_NULL (type);
4517 klass = mono_class_from_mono_type (type->type);
4519 mono_struct_delete_old (klass, (char *)src);
4523 mono_marshal_load_type_info (MonoClass* klass)
4525 int i, j, count = 0, native_size = 0;
4526 MonoMarshalType *info;
4529 g_assert (klass != NULL);
4531 if (klass->marshal_info)
4532 return klass->marshal_info;
4535 mono_class_init (klass);
4537 for (i = 0; i < klass->field.count; ++i) {
4538 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
4540 if (mono_field_is_deleted (&klass->fields [i]))
4545 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
4547 klass->marshal_info = info = g_malloc0 (sizeof (MonoMarshalType) + sizeof (MonoMarshalField) * count);
4548 info->num_fields = count;
4550 /* Try to find a size for this type in metadata */
4551 mono_metadata_packing_from_typedef (klass->image, klass->type_token, NULL, &native_size);
4553 if (klass->parent) {
4554 int parent_size = mono_class_native_size (klass->parent, NULL);
4556 /* Add parent size to real size */
4557 native_size += parent_size;
4558 info->native_size = parent_size;
4561 for (j = i = 0; i < klass->field.count; ++i) {
4564 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
4567 if (mono_field_is_deleted (&klass->fields [i]))
4569 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL)
4570 mono_metadata_field_info (klass->image, klass->field.first + i,
4571 NULL, NULL, &info->fields [j].mspec);
4573 info->fields [j].field = &klass->fields [i];
4575 if ((klass->field.count == 1) && (klass->instance_size == sizeof (MonoObject)) &&
4576 (strcmp (klass->fields [i].name, "$PRIVATE$") == 0)) {
4577 /* This field is a hack inserted by MCS to empty structures */
4582 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
4583 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
4584 size = mono_marshal_type_size (klass->fields [i].type, info->fields [j].mspec,
4585 &align, TRUE, klass->unicode);
4586 align = klass->packing_size ? MIN (klass->packing_size, align): align;
4587 info->fields [j].offset = info->native_size;
4588 info->fields [j].offset += align - 1;
4589 info->fields [j].offset &= ~(align - 1);
4590 info->native_size = info->fields [j].offset + size;
4592 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
4594 info->fields [j].offset = klass->fields [i].offset - sizeof (MonoObject);
4595 info->native_size = klass->instance_size - sizeof (MonoObject);
4601 if(layout != TYPE_ATTRIBUTE_AUTO_LAYOUT) {
4602 info->native_size = MAX (native_size, info->native_size);
4605 if (info->native_size & (klass->min_align - 1)) {
4606 info->native_size += klass->min_align - 1;
4607 info->native_size &= ~(klass->min_align - 1);
4610 return klass->marshal_info;
4614 * mono_class_native_size:
4617 * Returns: the native size of an object instance (when marshaled
4618 * to unmanaged code)
4621 mono_class_native_size (MonoClass *klass, guint32 *align)
4624 if (!klass->marshal_info)
4625 mono_marshal_load_type_info (klass);
4628 *align = klass->min_align;
4630 return klass->marshal_info->native_size;
4634 * mono_type_native_stack_size:
4635 * @t: the type to return the size it uses on the stack
4637 * Returns: the number of bytes required to hold an instance of this
4638 * type on the native stack
4641 mono_type_native_stack_size (MonoType *t, gint *align)
4645 g_assert (t != NULL);
4656 case MONO_TYPE_BOOLEAN:
4657 case MONO_TYPE_CHAR:
4666 case MONO_TYPE_STRING:
4667 case MONO_TYPE_OBJECT:
4668 case MONO_TYPE_CLASS:
4669 case MONO_TYPE_SZARRAY:
4671 case MONO_TYPE_FNPTR:
4672 case MONO_TYPE_ARRAY:
4673 case MONO_TYPE_TYPEDBYREF:
4684 case MONO_TYPE_VALUETYPE: {
4687 if (t->data.klass->enumtype)
4688 return mono_type_native_stack_size (t->data.klass->enum_basetype, align);
4690 size = mono_class_native_size (t->data.klass, align);
4691 *align = *align + 3;
4701 g_error ("type 0x%02x unknown", t->type);
4706 /* __alignof__ returns the preferred alignment of values not the actual alignment used by
4707 the compiler so is wrong e.g. for Linux where doubles are aligned on a 4 byte boundary
4708 but __alignof__ returns 8 - using G_STRUCT_OFFSET works better */
4709 #define ALIGNMENT(type) G_STRUCT_OFFSET(struct { char c; type x; }, x)
4712 mono_marshal_type_size (MonoType *type, MonoMarshalSpec *mspec, gint32 *align,
4713 gboolean as_field, gboolean unicode)
4715 MonoMarshalNative native_type = mono_type_to_unmanaged (type, mspec, as_field, unicode, NULL);
4718 switch (native_type) {
4719 case MONO_NATIVE_BOOLEAN:
4722 case MONO_NATIVE_I1:
4723 case MONO_NATIVE_U1:
4726 case MONO_NATIVE_I2:
4727 case MONO_NATIVE_U2:
4728 case MONO_NATIVE_VARIANTBOOL:
4731 case MONO_NATIVE_I4:
4732 case MONO_NATIVE_U4:
4733 case MONO_NATIVE_ERROR:
4736 case MONO_NATIVE_I8:
4737 case MONO_NATIVE_U8:
4738 *align = ALIGNMENT(guint64);
4740 case MONO_NATIVE_R4:
4743 case MONO_NATIVE_R8:
4744 *align = ALIGNMENT(double);
4746 case MONO_NATIVE_INT:
4747 case MONO_NATIVE_UINT:
4748 case MONO_NATIVE_LPSTR:
4749 case MONO_NATIVE_LPWSTR:
4750 case MONO_NATIVE_LPTSTR:
4751 case MONO_NATIVE_BSTR:
4752 case MONO_NATIVE_ANSIBSTR:
4753 case MONO_NATIVE_TBSTR:
4754 case MONO_NATIVE_LPARRAY:
4755 case MONO_NATIVE_SAFEARRAY:
4756 case MONO_NATIVE_IUNKNOWN:
4757 case MONO_NATIVE_IDISPATCH:
4758 case MONO_NATIVE_INTERFACE:
4759 case MONO_NATIVE_ASANY:
4760 case MONO_NATIVE_FUNC:
4761 case MONO_NATIVE_LPSTRUCT:
4762 *align = ALIGNMENT(gpointer);
4763 return sizeof (gpointer);
4764 case MONO_NATIVE_STRUCT:
4765 klass = mono_class_from_mono_type (type);
4766 return mono_class_native_size (klass, align);
4767 case MONO_NATIVE_BYVALTSTR: {
4768 int esize = unicode ? 2: 1;
4771 return mspec->data.array_data.num_elem * esize;
4773 case MONO_NATIVE_BYVALARRAY: {
4775 klass = mono_class_from_mono_type (type);
4776 esize = mono_class_native_size (klass->element_class, align);
4778 return mspec->data.array_data.num_elem * esize;
4780 case MONO_NATIVE_CUSTOM:
4781 g_assert_not_reached ();
4783 case MONO_NATIVE_CURRENCY:
4784 case MONO_NATIVE_VBBYREFSTR:
4786 g_error ("native type %02x not implemented", native_type);
4789 g_assert_not_reached ();