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"
22 //#define DEBUG_RUNTIME_CODE
24 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
28 #include "mono/cil/opcode.def"
33 struct _MonoMethodBuilder {
37 guint32 code_size, pos;
42 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object);
44 #ifdef DEBUG_RUNTIME_CODE
46 indenter (MonoDisHelper *dh, MonoMethod *method, guint32 ip_offset)
48 return g_strdup (" ");
51 static MonoDisHelper marshal_dh = {
62 mono_delegate_to_ftnptr (MonoDelegate *delegate)
64 MonoMethod *method, *wrapper;
70 if (delegate->delegate_trampoline)
71 return delegate->delegate_trampoline;
73 klass = ((MonoObject *)delegate)->vtable->klass;
74 g_assert (klass->delegate);
76 method = delegate->method_info->method;
77 wrapper = mono_marshal_get_managed_wrapper (method, delegate->target);
79 delegate->delegate_trampoline = mono_compile_method (wrapper);
81 return delegate->delegate_trampoline;
85 mono_array_to_savearray (MonoArray *array)
90 g_assert_not_reached ();
95 mono_array_to_lparray (MonoArray *array)
100 /* fixme: maybe we need to make a copy */
101 return array->vector;
105 mono_string_utf8_to_builder (MonoStringBuilder *sb, char *text)
107 GError *error = NULL;
117 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
119 if (items_written > sb->capacity)
120 items_written = sb->capacity;
123 memcpy (sb->chars->vector, ut, items_written * 2);
124 sb->length = items_written;
126 g_error_free (error);
132 mono_string_builder_to_utf8 (MonoStringBuilder *sb)
139 res = g_malloc (sb->capacity + 1);
141 /* fixme: copy the content of the string builder? */
148 mono_string_to_ansibstr (MonoString *string_obj)
150 g_error ("implement me");
155 mono_string_to_bstr (MonoString *string_obj)
157 g_error ("implement me");
162 mono_string_to_byvalstr (gpointer dst, MonoString *src, int size)
167 g_assert (dst != NULL);
171 memset (dst, 0, size);
175 s = mono_string_to_utf8 (src);
176 len = MIN (size, strlen (s));
177 memcpy (dst, s, len);
180 *((char *)dst + size - 1) = 0;
184 mono_string_to_byvalwstr (gpointer dst, MonoString *src, int size)
188 g_assert (dst != NULL);
192 memset (dst, 0, size);
196 len = MIN (size, (mono_string_length (src) * 2));
197 memcpy (dst, mono_string_chars (src), len);
199 *((char *)dst + size - 1) = 0;
200 *((char *)dst + size - 2) = 0;
205 mono_find_method_by_name (MonoClass *klass, const char *name, int param_count)
207 MonoMethod *res = NULL;
210 for (i = 0; i < klass->method.count; ++i) {
211 if ((klass->methods [i]->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
212 klass->methods [i]->name[0] == name [0] &&
213 !strcmp (name, klass->methods [i]->name) &&
214 klass->methods [i]->signature->param_count == param_count) {
215 res = klass->methods [i];
223 mono_mb_free (MonoMethodBuilder *mb)
225 g_list_free (mb->locals_list);
230 mono_mb_new (MonoClass *klass, const char *name)
232 MonoMethodBuilder *mb;
235 g_assert (klass != NULL);
236 g_assert (name != NULL);
238 mb = g_new0 (MonoMethodBuilder, 1);
240 mb->method = m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
243 m->name = g_strdup (name);
245 m->inline_count = -1;
246 m->wrapper_type = MONO_WRAPPER_UNKNOWN;
249 mb->code = g_malloc (mb->code_size);
255 mono_mb_add_local (MonoMethodBuilder *mb, MonoType *type)
257 int res = mb->locals;
259 g_assert (mb != NULL);
260 g_assert (type != NULL);
262 mb->locals_list = g_list_append (mb->locals_list, type);
269 mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack)
271 MonoMethodHeader *header;
275 g_assert (mb != NULL);
277 ((MonoMethodNormal *)mb->method)->header = header = (MonoMethodHeader *)
278 g_malloc0 (sizeof (MonoMethodHeader) + mb->locals * sizeof (MonoType *));
283 header->max_stack = max_stack;
285 for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
286 header->locals [i] = (MonoType *)l->data;
289 mb->method->signature = signature;
290 header->code = mb->code;
291 header->code_size = mb->pos;
292 header->num_locals = mb->locals;
294 #ifdef DEBUG_RUNTIME_CODE
295 printf ("RUNTIME CODE FOR %s\n", mono_method_full_name (mb->method, TRUE));
296 printf ("%s\n", mono_disasm_code (&marshal_dh, mb->method, mb->code, mb->code + mb->pos));
303 mono_mb_add_data (MonoMethodBuilder *mb, gpointer data)
305 MonoMethodWrapper *mw;
307 g_assert (mb != NULL);
309 mw = (MonoMethodWrapper *)mb->method;
311 mw->data = g_list_append (mw->data, data);
313 return GUINT32_TO_LE (g_list_length (mw->data));
317 mono_mb_patch_addr (MonoMethodBuilder *mb, int pos, int value)
319 *((gint32 *)(&mb->code [pos])) = value;
323 mono_mb_patch_addr_s (MonoMethodBuilder *mb, int pos, gint8 value)
325 *((gint8 *)(&mb->code [pos])) = value;
329 mono_mb_emit_byte (MonoMethodBuilder *mb, guint8 op)
331 if (mb->pos >= mb->code_size) {
333 mb->code = g_realloc (mb->code, mb->code_size);
336 mb->code [mb->pos++] = op;
340 mono_mb_emit_i4 (MonoMethodBuilder *mb, gint32 data)
342 if ((mb->pos + 4) >= mb->code_size) {
344 mb->code = g_realloc (mb->code, mb->code_size);
347 *((gint32 *)(&mb->code [mb->pos])) = data;
352 mono_mb_emit_i2 (MonoMethodBuilder *mb, gint16 data)
354 if ((mb->pos + 2) >= mb->code_size) {
356 mb->code = g_realloc (mb->code, mb->code_size);
359 *((gint16 *)(&mb->code [mb->pos])) = data;
364 mono_mb_emit_ldarg (MonoMethodBuilder *mb, guint argnum)
367 mono_mb_emit_byte (mb, CEE_LDARG_0 + argnum);
368 } else if (argnum < 256) {
369 mono_mb_emit_byte (mb, CEE_LDARG_S);
370 mono_mb_emit_byte (mb, argnum);
372 mono_mb_emit_byte (mb, CEE_PREFIX1);
373 mono_mb_emit_byte (mb, CEE_LDARG);
374 mono_mb_emit_i4 (mb, argnum);
379 mono_mb_emit_ldarg_addr (MonoMethodBuilder *mb, guint argnum)
382 mono_mb_emit_byte (mb, CEE_LDARGA_S);
383 mono_mb_emit_byte (mb, argnum);
385 mono_mb_emit_byte (mb, CEE_PREFIX1);
386 mono_mb_emit_byte (mb, CEE_LDARGA);
387 mono_mb_emit_i4 (mb, argnum);
392 mono_mb_emit_ldloc_addr (MonoMethodBuilder *mb, guint locnum)
395 mono_mb_emit_byte (mb, CEE_LDLOCA_S);
396 mono_mb_emit_byte (mb, locnum);
398 mono_mb_emit_byte (mb, CEE_PREFIX1);
399 mono_mb_emit_byte (mb, CEE_LDLOCA);
400 mono_mb_emit_i4 (mb, locnum);
405 mono_mb_emit_ldloc (MonoMethodBuilder *mb, guint num)
408 mono_mb_emit_byte (mb, CEE_LDLOC_0 + num);
409 } else if (num < 256) {
410 mono_mb_emit_byte (mb, CEE_LDLOC_S);
411 mono_mb_emit_byte (mb, num);
413 mono_mb_emit_byte (mb, CEE_PREFIX1);
414 mono_mb_emit_byte (mb, CEE_LDLOC);
415 mono_mb_emit_i4 (mb, num);
420 mono_mb_emit_stloc (MonoMethodBuilder *mb, guint num)
423 mono_mb_emit_byte (mb, CEE_STLOC_0 + num);
424 } else if (num < 256) {
425 mono_mb_emit_byte (mb, CEE_STLOC_S);
426 mono_mb_emit_byte (mb, num);
428 mono_mb_emit_byte (mb, CEE_PREFIX1);
429 mono_mb_emit_byte (mb, CEE_STLOC);
430 mono_mb_emit_i4 (mb, num);
435 mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value)
437 if (value >= -1 && value < 8) {
438 mono_mb_emit_byte (mb, CEE_LDC_I4_0 + value);
439 } else if (value >= -128 && value <= 127) {
440 mono_mb_emit_byte (mb, CEE_LDC_I4_S);
441 mono_mb_emit_byte (mb, value);
443 mono_mb_emit_byte (mb, CEE_LDC_I4);
444 mono_mb_emit_i4 (mb, value);
449 mono_mb_emit_managed_call (MonoMethodBuilder *mb, MonoMethod *method, MonoMethodSignature *opt_sig)
452 opt_sig = method->signature;
453 mono_mb_emit_byte (mb, CEE_PREFIX1);
454 mono_mb_emit_byte (mb, CEE_LDFTN);
455 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
456 mono_mb_emit_byte (mb, CEE_CALLI);
457 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, opt_sig));
461 mono_mb_emit_native_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, gpointer func)
463 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
464 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
465 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, func));
466 mono_mb_emit_byte (mb, CEE_CALLI);
467 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
471 mono_mb_emit_exception (MonoMethodBuilder *mb)
473 /* fixme: we need a better way to throw exception,
474 * supporting several exception types and messages */
475 mono_mb_emit_byte (mb, CEE_LDNULL);
476 mono_mb_emit_byte (mb, CEE_THROW);
481 mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint8 local, gint8 incr)
483 mono_mb_emit_ldloc (mb, local);
484 mono_mb_emit_icon (mb, incr);
485 mono_mb_emit_byte (mb, CEE_ADD);
486 mono_mb_emit_stloc (mb, local);
490 emit_ptr_to_str_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv,
491 int usize, int msize)
494 case MONO_MARSHAL_CONV_BOOL_I4:
495 mono_mb_emit_byte (mb, CEE_LDLOC_0);
496 mono_mb_emit_byte (mb, CEE_LDIND_I);
497 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
498 mono_mb_emit_byte (mb, 5);
499 mono_mb_emit_byte (mb, CEE_LDLOC_1);
500 mono_mb_emit_byte (mb, CEE_LDC_I4_1);
501 mono_mb_emit_byte (mb, CEE_STIND_I1);
502 mono_mb_emit_byte (mb, CEE_BR_S);
503 mono_mb_emit_byte (mb, 3);
504 mono_mb_emit_byte (mb, CEE_LDLOC_1);
505 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
506 mono_mb_emit_byte (mb, CEE_STIND_I1);
508 case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
512 if (type->type == MONO_TYPE_ARRAY)
513 eclass = mono_class_from_mono_type (type->data.array->type);
514 else if (type->type == MONO_TYPE_SZARRAY) {
515 eclass = mono_class_from_mono_type (type->data.type);
517 g_assert_not_reached ();
520 if (eclass->valuetype)
521 esize = mono_class_instance_size (eclass) - sizeof (MonoObject);
523 esize = sizeof (gpointer);
525 /* create a new array */
526 /* fixme: this only works for SZARRAYS */
527 mono_mb_emit_byte (mb, CEE_LDLOC_1);
528 mono_mb_emit_icon (mb, msize / esize);
529 mono_mb_emit_byte (mb, CEE_NEWARR);
530 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eclass));
531 mono_mb_emit_byte (mb, CEE_STIND_I);
533 /* copy the elements */
534 mono_mb_emit_byte (mb, CEE_LDLOC_1);
535 mono_mb_emit_byte (mb, CEE_LDIND_I);
536 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
537 mono_mb_emit_byte (mb, CEE_ADD);
538 mono_mb_emit_byte (mb, CEE_LDLOC_0);
539 mono_mb_emit_icon (mb, usize);
540 mono_mb_emit_byte (mb, CEE_PREFIX1);
541 mono_mb_emit_byte (mb, CEE_CPBLK);
545 case MONO_MARSHAL_CONV_STR_BYVALSTR:
546 mono_mb_emit_byte (mb, CEE_LDLOC_1);
547 mono_mb_emit_byte (mb, CEE_LDLOC_0);
548 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
549 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
550 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
551 mono_mb_emit_byte (mb, CEE_STIND_I);
553 case MONO_MARSHAL_CONV_STR_LPTSTR:
554 case MONO_MARSHAL_CONV_STR_LPSTR:
555 mono_mb_emit_byte (mb, CEE_LDLOC_1);
556 mono_mb_emit_byte (mb, CEE_LDLOC_0);
557 mono_mb_emit_byte (mb, CEE_LDIND_I);
558 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
559 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
560 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
561 mono_mb_emit_byte (mb, CEE_STIND_I);
563 case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
564 MonoClass *klass = mono_class_from_mono_type (type);
565 int src_var, dst_var;
567 src_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
568 dst_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
570 /* *dst = new object */
571 mono_mb_emit_byte (mb, CEE_LDLOC_1);
572 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
573 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
574 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
575 mono_mb_emit_byte (mb, CEE_STIND_I);
577 /* save the old src pointer */
578 mono_mb_emit_byte (mb, CEE_LDLOC_0);
579 mono_mb_emit_stloc (mb, src_var);
580 /* save the old dst pointer */
581 mono_mb_emit_byte (mb, CEE_LDLOC_1);
582 mono_mb_emit_stloc (mb, dst_var);
584 /* dst = pointer to newly created object data */
585 mono_mb_emit_byte (mb, CEE_LDLOC_1);
586 mono_mb_emit_byte (mb, CEE_LDIND_I);
587 mono_mb_emit_icon (mb, sizeof (MonoObject));
588 mono_mb_emit_byte (mb, CEE_ADD);
589 mono_mb_emit_byte (mb, CEE_STLOC_1);
591 emit_struct_conv (mb, klass, TRUE);
593 /* restore the old src pointer */
594 mono_mb_emit_ldloc (mb, src_var);
595 mono_mb_emit_byte (mb, CEE_STLOC_0);
596 /* restore the old dst pointer */
597 mono_mb_emit_ldloc (mb, dst_var);
598 mono_mb_emit_byte (mb, CEE_STLOC_1);
601 case MONO_MARSHAL_CONV_STR_LPWSTR:
602 case MONO_MARSHAL_CONV_STR_BSTR:
603 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
604 case MONO_MARSHAL_CONV_STR_TBSTR:
605 case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
606 case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
607 case MONO_MARSHAL_CONV_STR_BYVALWSTR:
608 case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
610 g_warning ("marshaling conversion %d not implemented", conv);
611 g_assert_not_reached ();
616 emit_str_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, int usize, int msize)
621 case MONO_MARSHAL_CONV_BOOL_I4:
622 mono_mb_emit_byte (mb, CEE_LDLOC_1);
623 mono_mb_emit_byte (mb, CEE_LDLOC_0);
624 mono_mb_emit_byte (mb, CEE_LDIND_U1);
625 mono_mb_emit_byte (mb, CEE_STIND_I4);
627 case MONO_MARSHAL_CONV_STR_LPWSTR:
628 case MONO_MARSHAL_CONV_STR_LPSTR:
629 case MONO_MARSHAL_CONV_STR_LPTSTR:
630 case MONO_MARSHAL_CONV_STR_BSTR:
631 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
632 case MONO_MARSHAL_CONV_STR_TBSTR:
633 /* free space if free == true */
634 mono_mb_emit_byte (mb, CEE_LDLOC_2);
635 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
636 mono_mb_emit_byte (mb, 4);
637 mono_mb_emit_byte (mb, CEE_LDLOC_1);
638 mono_mb_emit_byte (mb, CEE_LDIND_I);
639 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
640 mono_mb_emit_byte (mb, CEE_MONO_FREE);
642 mono_mb_emit_byte (mb, CEE_LDLOC_1);
643 mono_mb_emit_byte (mb, CEE_LDLOC_0);
644 mono_mb_emit_byte (mb, CEE_LDIND_I);
645 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
646 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
647 mono_mb_emit_byte (mb, conv);
648 mono_mb_emit_byte (mb, CEE_STIND_I);
650 case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
651 case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
652 mono_mb_emit_byte (mb, CEE_LDLOC_1);
653 mono_mb_emit_byte (mb, CEE_LDLOC_0);
654 mono_mb_emit_byte (mb, CEE_LDIND_I);
655 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
656 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
657 mono_mb_emit_byte (mb, conv);
658 mono_mb_emit_byte (mb, CEE_STIND_I);
660 case MONO_MARSHAL_CONV_STR_BYVALSTR:
661 case MONO_MARSHAL_CONV_STR_BYVALWSTR: {
665 mono_mb_emit_byte (mb, CEE_LDLOC_1); /* dst */
666 mono_mb_emit_byte (mb, CEE_LDLOC_0);
667 mono_mb_emit_byte (mb, CEE_LDIND_I); /* src String */
668 mono_mb_emit_icon (mb, usize);
669 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
670 mono_mb_emit_byte (mb, CEE_MONO_PROC3);
671 mono_mb_emit_byte (mb, conv);
674 case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
678 mono_mb_emit_byte (mb, CEE_LDLOC_0);
679 mono_mb_emit_byte (mb, CEE_LDIND_I);
680 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
682 mono_mb_emit_byte (mb, 0);
684 mono_mb_emit_byte (mb, CEE_LDLOC_1);
685 mono_mb_emit_byte (mb, CEE_LDLOC_0);
686 mono_mb_emit_byte (mb, CEE_LDIND_I);
687 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
688 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
689 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
690 mono_mb_emit_byte (mb, CEE_ADD);
691 mono_mb_emit_icon (mb, usize);
692 mono_mb_emit_byte (mb, CEE_PREFIX1);
693 mono_mb_emit_byte (mb, CEE_CPBLK);
694 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
697 case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
698 int src_var, dst_var;
700 src_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
701 dst_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
703 mono_mb_emit_byte (mb, CEE_LDLOC_0);
704 mono_mb_emit_byte (mb, CEE_LDIND_I);
705 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
707 mono_mb_emit_byte (mb, 0);
709 /* save the old src pointer */
710 mono_mb_emit_byte (mb, CEE_LDLOC_0);
711 mono_mb_emit_stloc (mb, src_var);
712 /* save the old dst pointer */
713 mono_mb_emit_byte (mb, CEE_LDLOC_1);
714 mono_mb_emit_stloc (mb, dst_var);
716 /* src = pointer to object data */
717 mono_mb_emit_byte (mb, CEE_LDLOC_0);
718 mono_mb_emit_byte (mb, CEE_LDIND_I);
719 mono_mb_emit_icon (mb, sizeof (MonoObject));
720 mono_mb_emit_byte (mb, CEE_ADD);
721 mono_mb_emit_byte (mb, CEE_STLOC_0);
723 emit_struct_conv (mb, mono_class_from_mono_type (type), FALSE);
725 /* restore the old src pointer */
726 mono_mb_emit_ldloc (mb, src_var);
727 mono_mb_emit_byte (mb, CEE_STLOC_0);
728 /* restore the old dst pointer */
729 mono_mb_emit_ldloc (mb, dst_var);
730 mono_mb_emit_byte (mb, CEE_STLOC_1);
732 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
735 case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
737 g_warning ("marshalling conversion %d not implemented", conv);
738 g_assert_not_reached ();
743 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
745 MonoMarshalType *info;
748 info = mono_marshal_load_type_info (klass);
750 for (i = 0; i < info->num_fields; i++) {
751 MonoMarshalNative ntype;
752 MonoMarshalConv conv;
753 MonoType *ftype = info->fields [i].field->type;
756 gboolean last_field = i < (info->num_fields -1) ? 0 : 1;
758 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
761 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, klass->unicode, &conv);
764 msize = klass->instance_size - info->fields [i].field->offset;
765 usize = info->native_size - info->fields [i].offset;
767 msize = klass->fields [i + 1].offset - info->fields [i].field->offset;
768 usize = info->fields [i + 1].offset - info->fields [i].offset;
770 g_assert (msize > 0 && usize > 0);
773 case MONO_MARSHAL_CONV_NONE: {
776 if (ftype->byref || ftype->type == MONO_TYPE_I ||
777 ftype->type == MONO_TYPE_U) {
778 mono_mb_emit_byte (mb, CEE_LDLOC_1);
779 mono_mb_emit_byte (mb, CEE_LDLOC_0);
780 mono_mb_emit_byte (mb, CEE_LDIND_I);
781 mono_mb_emit_byte (mb, CEE_STIND_I);
790 mono_mb_emit_byte (mb, CEE_LDLOC_1);
791 mono_mb_emit_byte (mb, CEE_LDLOC_0);
792 mono_mb_emit_byte (mb, CEE_LDIND_I4);
793 mono_mb_emit_byte (mb, CEE_STIND_I4);
797 case MONO_TYPE_BOOLEAN:
798 mono_mb_emit_byte (mb, CEE_LDLOC_1);
799 mono_mb_emit_byte (mb, CEE_LDLOC_0);
800 mono_mb_emit_byte (mb, CEE_LDIND_I1);
801 mono_mb_emit_byte (mb, CEE_STIND_I1);
805 mono_mb_emit_byte (mb, CEE_LDLOC_1);
806 mono_mb_emit_byte (mb, CEE_LDLOC_0);
807 mono_mb_emit_byte (mb, CEE_LDIND_I2);
808 mono_mb_emit_byte (mb, CEE_STIND_I2);
812 mono_mb_emit_byte (mb, CEE_LDLOC_1);
813 mono_mb_emit_byte (mb, CEE_LDLOC_0);
814 mono_mb_emit_byte (mb, CEE_LDIND_I8);
815 mono_mb_emit_byte (mb, CEE_STIND_I8);
818 mono_mb_emit_byte (mb, CEE_LDLOC_1);
819 mono_mb_emit_byte (mb, CEE_LDLOC_0);
820 mono_mb_emit_byte (mb, CEE_LDIND_R4);
821 mono_mb_emit_byte (mb, CEE_STIND_R4);
824 mono_mb_emit_byte (mb, CEE_LDLOC_1);
825 mono_mb_emit_byte (mb, CEE_LDLOC_0);
826 mono_mb_emit_byte (mb, CEE_LDIND_R8);
827 mono_mb_emit_byte (mb, CEE_STIND_R8);
829 case MONO_TYPE_VALUETYPE:
830 if (ftype->data.klass->enumtype) {
831 t = ftype->data.klass->enum_basetype->type;
834 emit_struct_conv (mb, ftype->data.klass, to_object);
837 g_warning ("marshaling type %02x not implemented", ftype->type);
838 g_assert_not_reached ();
844 emit_ptr_to_str_conv (mb, ftype, conv, usize, msize);
846 emit_str_to_ptr_conv (mb, ftype, conv, usize, msize);
850 mono_mb_emit_add_to_local (mb, 0, usize);
851 mono_mb_emit_add_to_local (mb, 1, msize);
853 mono_mb_emit_add_to_local (mb, 0, msize);
854 mono_mb_emit_add_to_local (mb, 1, usize);
859 static MonoAsyncResult *
860 mono_delegate_begin_invoke (MonoDelegate *delegate, gpointer *params)
862 MonoMethodMessage *msg;
863 MonoDelegate *async_callback;
867 MonoMethod *method = NULL;
872 klass = delegate->object.vtable->klass;
874 method = mono_get_delegate_invoke (klass);
875 for (i = 0; i < klass->method.count; ++i) {
876 if (klass->methods [i]->name[0] == 'B' &&
877 !strcmp ("BeginInvoke", klass->methods [i]->name)) {
878 method = klass->methods [i];
883 g_assert (method != NULL);
885 im = mono_get_delegate_invoke (method->klass);
887 msg = mono_method_call_message_new (method, params, im, &async_callback, &state);
889 return mono_thread_pool_add ((MonoObject *)delegate, msg, async_callback, state);
893 mono_mb_emit_save_args (MonoMethodBuilder *mb, MonoMethodSignature *sig, gboolean save_this)
895 int i, params_var, tmp_var;
897 /* allocate local (pointer) *params[] */
898 params_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
899 /* allocate local (pointer) tmp */
900 tmp_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
902 /* alloate space on stack to store an array of pointers to the arguments */
903 mono_mb_emit_icon (mb, sizeof (gpointer) * (sig->param_count + 1));
904 mono_mb_emit_byte (mb, CEE_PREFIX1);
905 mono_mb_emit_byte (mb, CEE_LOCALLOC);
906 mono_mb_emit_stloc (mb, params_var);
909 mono_mb_emit_ldloc (mb, params_var);
910 mono_mb_emit_stloc (mb, tmp_var);
912 if (save_this && sig->hasthis) {
913 mono_mb_emit_ldloc (mb, tmp_var);
914 mono_mb_emit_ldarg_addr (mb, 0);
915 mono_mb_emit_byte (mb, CEE_STIND_I);
916 /* tmp = tmp + sizeof (gpointer) */
917 if (sig->param_count)
918 mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
922 for (i = 0; i < sig->param_count; i++) {
923 mono_mb_emit_ldloc (mb, tmp_var);
924 mono_mb_emit_ldarg_addr (mb, i + sig->hasthis);
925 mono_mb_emit_byte (mb, CEE_STIND_I);
926 /* tmp = tmp + sizeof (gpointer) */
927 if (i < (sig->param_count - 1))
928 mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
935 mono_signature_to_name (MonoMethodSignature *sig, const char *prefix)
939 GString *res = g_string_new ("");
942 g_string_append (res, prefix);
943 g_string_append_c (res, '_');
946 mono_type_get_desc (res, sig->ret, FALSE);
948 for (i = 0; i < sig->param_count; ++i) {
949 g_string_append_c (res, '_');
950 mono_type_get_desc (res, sig->params [i], FALSE);
953 g_string_free (res, FALSE);
958 mono_marshal_get_delegate_begin_invoke (MonoMethod *method)
960 MonoMethodSignature *sig;
961 static MonoMethodSignature *csig = NULL;
962 MonoMethodBuilder *mb;
968 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
969 !strcmp (method->name, "BeginInvoke"));
971 sig = method->signature;
973 cache = method->klass->image->delegate_begin_invoke_cache;
974 if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
977 g_assert (sig->hasthis);
980 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
981 csig = g_malloc0 (sigsize);
983 /* MonoAsyncResult * begin_invoke (MonoDelegate *delegate, gpointer params[]) */
984 csig->param_count = 2;
985 csig->ret = &mono_defaults.object_class->byval_arg;
986 csig->params [0] = &mono_defaults.object_class->byval_arg;
987 csig->params [1] = &mono_defaults.int_class->byval_arg;
990 name = mono_signature_to_name (sig, "begin_invoke");
991 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name);
994 mb->method->wrapper_type = MONO_WRAPPER_DELEGATE_BEGIN_INVOKE;
995 mb->method->save_lmf = 1;
997 params_var = mono_mb_emit_save_args (mb, sig, FALSE);
999 mono_mb_emit_ldarg (mb, 0);
1000 mono_mb_emit_ldloc (mb, params_var);
1001 mono_mb_emit_native_call (mb, csig, mono_delegate_begin_invoke);
1002 mono_mb_emit_byte (mb, CEE_RET);
1004 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1006 g_hash_table_insert (cache, sig, res);
1011 mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params)
1013 MonoDomain *domain = mono_domain_get ();
1014 MonoAsyncResult *ares;
1015 MonoMethod *method = NULL;
1016 MonoMethodSignature *sig;
1017 MonoMethodMessage *msg;
1018 MonoObject *res, *exc;
1019 MonoArray *out_args;
1023 g_assert (delegate);
1025 if (!delegate->method_info || !delegate->method_info->method)
1026 g_assert_not_reached ();
1028 klass = delegate->object.vtable->klass;
1030 for (i = 0; i < klass->method.count; ++i) {
1031 if (klass->methods [i]->name[0] == 'E' &&
1032 !strcmp ("EndInvoke", klass->methods [i]->name)) {
1033 method = klass->methods [i];
1038 g_assert (method != NULL);
1040 sig = method->signature;
1042 msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1044 ares = mono_array_get (msg->args, gpointer, sig->param_count - 1);
1047 res = mono_thread_pool_finish (ares, &out_args, &exc);
1050 char *strace = mono_string_to_utf8 (((MonoException*)exc)->stack_trace);
1052 tmp = g_strdup_printf ("%s\nException Rethrown at:\n", strace);
1054 ((MonoException*)exc)->stack_trace = mono_string_new (domain, tmp);
1056 mono_raise_exception ((MonoException*)exc);
1059 mono_method_return_message_restore (method, params, out_args);
1064 mono_mb_emit_restore_result (MonoMethodBuilder *mb, MonoType *return_type)
1066 if (return_type->byref)
1067 return_type = &mono_defaults.int_class->byval_arg;
1068 else if (return_type->type == MONO_TYPE_VALUETYPE && return_type->data.klass->enumtype)
1069 return_type = return_type->data.klass->enum_basetype;
1071 switch (return_type->type) {
1072 case MONO_TYPE_VOID:
1073 g_assert_not_reached ();
1075 case MONO_TYPE_STRING:
1076 case MONO_TYPE_CLASS:
1077 case MONO_TYPE_OBJECT:
1078 case MONO_TYPE_ARRAY:
1079 case MONO_TYPE_SZARRAY:
1083 case MONO_TYPE_BOOLEAN:
1084 mono_mb_emit_byte (mb, CEE_UNBOX);
1085 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1086 mono_mb_emit_byte (mb, CEE_LDIND_U1);
1089 mono_mb_emit_byte (mb, CEE_UNBOX);
1090 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1091 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1094 case MONO_TYPE_CHAR:
1095 mono_mb_emit_byte (mb, CEE_UNBOX);
1096 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1097 mono_mb_emit_byte (mb, CEE_LDIND_U2);
1100 mono_mb_emit_byte (mb, CEE_UNBOX);
1101 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1102 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1106 mono_mb_emit_byte (mb, CEE_UNBOX);
1107 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1108 mono_mb_emit_byte (mb, CEE_LDIND_I);
1111 mono_mb_emit_byte (mb, CEE_UNBOX);
1112 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1113 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1116 mono_mb_emit_byte (mb, CEE_UNBOX);
1117 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1118 mono_mb_emit_byte (mb, CEE_LDIND_U4);
1122 mono_mb_emit_byte (mb, CEE_UNBOX);
1123 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1124 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1127 mono_mb_emit_byte (mb, CEE_UNBOX);
1128 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1129 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1132 mono_mb_emit_byte (mb, CEE_UNBOX);
1133 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1134 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1136 case MONO_TYPE_VALUETYPE: {
1138 mono_mb_emit_byte (mb, CEE_UNBOX);
1139 class = mono_mb_add_data (mb, mono_class_from_mono_type (return_type));
1140 mono_mb_emit_i4 (mb, class);
1141 mono_mb_emit_byte (mb, CEE_LDOBJ);
1142 mono_mb_emit_i4 (mb, class);
1146 g_warning ("type 0x%x not handled", return_type->type);
1147 g_assert_not_reached ();
1150 mono_mb_emit_byte (mb, CEE_RET);
1154 mono_marshal_get_delegate_end_invoke (MonoMethod *method)
1156 MonoMethodSignature *sig;
1157 static MonoMethodSignature *csig = NULL;
1158 MonoMethodBuilder *mb;
1164 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1165 !strcmp (method->name, "EndInvoke"));
1167 sig = method->signature;
1169 cache = method->klass->image->delegate_end_invoke_cache;
1170 if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1173 g_assert (sig->hasthis);
1176 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1177 csig = g_malloc0 (sigsize);
1179 /* MonoObject *end_invoke (MonoDelegate *delegate, gpointer params[]) */
1180 csig->param_count = 2;
1181 csig->ret = &mono_defaults.object_class->byval_arg;
1182 csig->params [0] = &mono_defaults.object_class->byval_arg;
1183 csig->params [1] = &mono_defaults.int_class->byval_arg;
1186 name = mono_signature_to_name (sig, "end_invoke");
1187 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name);
1190 mb->method->wrapper_type = MONO_WRAPPER_DELEGATE_END_INVOKE;
1191 mb->method->save_lmf = 1;
1193 params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1195 mono_mb_emit_ldarg (mb, 0);
1196 mono_mb_emit_ldloc (mb, params_var);
1197 mono_mb_emit_native_call (mb, csig, mono_delegate_end_invoke);
1199 if (sig->ret->type == MONO_TYPE_VOID) {
1200 mono_mb_emit_byte (mb, CEE_POP);
1201 mono_mb_emit_byte (mb, CEE_RET);
1203 mono_mb_emit_restore_result (mb, sig->ret);
1205 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1207 g_hash_table_insert (cache, sig, res);
1213 mono_remoting_wrapper (MonoMethod *method, gpointer *params)
1215 MonoMethodMessage *msg;
1216 MonoTransparentProxy *this;
1217 MonoObject *res, *exc;
1218 MonoArray *out_args;
1220 this = *((MonoTransparentProxy **)params [0]);
1223 g_assert (((MonoObject *)this)->vtable->klass == mono_defaults.transparent_proxy_class);
1225 /* skip the this pointer */
1228 msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1230 res = mono_remoting_invoke ((MonoObject *)this->rp, msg, &exc, &out_args);
1233 mono_raise_exception ((MonoException *)exc);
1235 mono_method_return_message_restore (method, params, out_args);
1241 mono_marshal_get_remoting_invoke (MonoMethod *method)
1243 MonoMethodSignature *sig;
1244 static MonoMethodSignature *csig = NULL;
1245 MonoMethodBuilder *mb;
1252 if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE)
1255 sig = method->signature;
1257 /* we cant remote methods without this pointer */
1261 cache = method->klass->image->remoting_invoke_cache;
1262 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1266 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1267 csig = g_malloc0 (sigsize);
1269 /* MonoObject *remoting_wrapper (MonoMethod *method, gpointer params[]) */
1270 csig->param_count = 2;
1271 csig->ret = &mono_defaults.object_class->byval_arg;
1272 csig->params [0] = &mono_defaults.int_class->byval_arg;
1273 csig->params [1] = &mono_defaults.int_class->byval_arg;
1276 mb = mono_mb_new (method->klass, method->name);
1277 mb->method->wrapper_type = MONO_WRAPPER_REMOTING_INVOKE;
1279 params_var = mono_mb_emit_save_args (mb, sig, TRUE);
1281 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1282 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1283 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
1284 mono_mb_emit_ldloc (mb, params_var);
1285 mono_mb_emit_native_call (mb, csig, mono_remoting_wrapper);
1287 if (sig->ret->type == MONO_TYPE_VOID)
1288 mono_mb_emit_byte (mb, CEE_POP);
1290 mono_mb_emit_restore_result (mb, sig->ret);
1292 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1294 g_hash_table_insert (cache, method, res);
1299 * the returned method invokes all methods in a multicast delegate
1302 mono_marshal_get_delegate_invoke (MonoMethod *method)
1304 MonoMethodSignature *sig, *static_sig;
1306 MonoMethodBuilder *mb;
1312 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1313 !strcmp (method->name, "Invoke"));
1315 sig = method->signature;
1317 cache = method->klass->image->delegate_invoke_cache;
1318 if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1321 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1322 static_sig = g_memdup (sig, sigsize);
1323 static_sig->hasthis = 0;
1325 name = mono_signature_to_name (sig, "invoke");
1326 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name);
1329 mb->method->wrapper_type = MONO_WRAPPER_DELEGATE_INVOKE;
1331 /* allocate local 0 (object) prev */
1332 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1333 /* allocate local 1 (object) target */
1334 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1335 /* allocate local 2 (pointer) mptr */
1336 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1338 /* allocate local 3 to store the return value */
1339 if (sig->ret->type != MONO_TYPE_VOID)
1340 mono_mb_add_local (mb, sig->ret);
1342 g_assert (sig->hasthis);
1344 /* prev = addr of delegate */
1345 mono_mb_emit_ldarg (mb, 0);
1346 mono_mb_emit_stloc (mb, 0);
1350 /* target = delegate->target */
1351 mono_mb_emit_ldloc (mb, 0);
1352 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1353 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
1354 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoDelegate, target));
1355 mono_mb_emit_byte (mb, CEE_ADD);
1356 mono_mb_emit_byte (mb, CEE_LDIND_I);
1357 mono_mb_emit_stloc (mb, 1);
1359 /* mptr = delegate->method_ptr */
1360 mono_mb_emit_ldloc (mb, 0);
1361 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1362 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
1363 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1364 mono_mb_emit_byte (mb, CEE_ADD);
1365 mono_mb_emit_byte (mb, CEE_LDIND_I);
1366 mono_mb_emit_stloc (mb, 2);
1368 /* target == null ? */
1369 mono_mb_emit_ldloc (mb, 1);
1370 mono_mb_emit_byte (mb, CEE_BRTRUE);
1372 mono_mb_emit_i4 (mb, 0);
1374 /* emit static method call */
1376 for (i = 0; i < sig->param_count; i++)
1377 mono_mb_emit_ldarg (mb, i + 1);
1379 mono_mb_emit_ldloc (mb, 2);
1380 mono_mb_emit_byte (mb, CEE_CALLI);
1381 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, static_sig));
1383 if (sig->ret->type != MONO_TYPE_VOID)
1384 mono_mb_emit_stloc (mb, 3);
1386 mono_mb_emit_byte (mb, CEE_BR);
1388 mono_mb_emit_i4 (mb, 0);
1390 /* target != null, emit non static method call */
1392 mono_mb_patch_addr (mb, pos [1], mb->pos - (pos [1] + 4));
1393 mono_mb_emit_ldloc (mb, 1);
1395 for (i = 0; i < sig->param_count; i++)
1396 mono_mb_emit_ldarg (mb, i + 1);
1398 mono_mb_emit_ldloc (mb, 2);
1399 mono_mb_emit_byte (mb, CEE_CALLI);
1400 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
1402 if (sig->ret->type != MONO_TYPE_VOID)
1403 mono_mb_emit_stloc (mb, 3);
1405 mono_mb_patch_addr (mb, pos [2], mb->pos - (pos [2] + 4));
1407 /* prev = delegate->prev */
1408 mono_mb_emit_ldloc (mb, 0);
1409 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1410 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
1411 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoMulticastDelegate, prev));
1412 mono_mb_emit_byte (mb, CEE_ADD);
1413 mono_mb_emit_byte (mb, CEE_LDIND_I);
1414 mono_mb_emit_stloc (mb, 0);
1416 /* if prev != null goto loop */
1417 mono_mb_emit_ldloc (mb, 0);
1418 mono_mb_emit_byte (mb, CEE_BRTRUE);
1419 mono_mb_emit_i4 (mb, pos [0] - (mb->pos + 4));
1421 if (sig->ret->type != MONO_TYPE_VOID)
1422 mono_mb_emit_ldloc (mb, 3);
1424 mono_mb_emit_byte (mb, CEE_RET);
1426 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1429 g_hash_table_insert (cache, sig, res);
1435 * generates IL code for the runtime invoke function
1436 * MonoObject *runtime_invoke (MonoObject *this, void **params, MonoObject **exc)
1438 * we also catch exceptions if exc != null
1441 mono_marshal_get_runtime_invoke (MonoMethod *method)
1443 MonoMethodSignature *sig, *csig;
1444 MonoExceptionClause *clause;
1445 MonoMethodHeader *header;
1446 MonoMethodBuilder *mb;
1449 static MonoString *string_dummy = NULL;
1450 int i, pos, sigsize;
1454 cache = method->klass->image->runtime_invoke_cache;
1455 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1458 /* to make it work with our special string constructors */
1460 string_dummy = mono_string_new_wrapper ("dummy");
1462 sig = method->signature;
1464 sigsize = sizeof (MonoMethodSignature) + 3 * sizeof (MonoType *);
1465 csig = g_malloc0 (sigsize);
1467 csig->param_count = 3;
1468 csig->ret = &mono_defaults.object_class->byval_arg;
1469 csig->params [0] = &mono_defaults.object_class->byval_arg;
1470 csig->params [1] = &mono_defaults.int_class->byval_arg;
1471 csig->params [2] = &mono_defaults.int_class->byval_arg;
1473 mb = mono_mb_new (method->klass, method->name);
1474 mb->method->wrapper_type = MONO_WRAPPER_RUNTIME_INVOKE;
1476 /* allocate local 0 (object) tmp */
1477 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1478 /* allocate local 1 (object) exc */
1479 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1481 /* cond set *exc to null */
1482 mono_mb_emit_byte (mb, CEE_LDARG_2);
1483 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
1484 mono_mb_emit_byte (mb, 3);
1485 mono_mb_emit_byte (mb, CEE_LDARG_2);
1486 mono_mb_emit_byte (mb, CEE_LDNULL);
1487 mono_mb_emit_byte (mb, CEE_STIND_I);
1490 if (method->string_ctor) {
1491 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1492 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1493 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, string_dummy));
1495 mono_mb_emit_ldarg (mb, 0);
1496 if (method->klass->valuetype) {
1497 mono_mb_emit_byte (mb, CEE_UNBOX);
1498 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method->klass));
1503 for (i = 0; i < sig->param_count; i++) {
1504 MonoType *t = sig->params [i];
1507 mono_mb_emit_ldarg (mb, 1);
1509 mono_mb_emit_icon (mb, sizeof (gpointer) * i);
1510 mono_mb_emit_byte (mb, CEE_ADD);
1512 mono_mb_emit_byte (mb, CEE_LDIND_I);
1517 type = sig->params [i]->type;
1521 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1523 case MONO_TYPE_BOOLEAN:
1525 mono_mb_emit_byte (mb, CEE_LDIND_U1);
1528 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1531 case MONO_TYPE_CHAR:
1532 mono_mb_emit_byte (mb, CEE_LDIND_U2);
1536 mono_mb_emit_byte (mb, CEE_LDIND_I);
1539 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1542 mono_mb_emit_byte (mb, CEE_LDIND_U4);
1545 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1548 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1552 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1554 case MONO_TYPE_STRING:
1555 case MONO_TYPE_CLASS:
1556 case MONO_TYPE_ARRAY:
1558 case MONO_TYPE_SZARRAY:
1559 case MONO_TYPE_OBJECT:
1562 case MONO_TYPE_VALUETYPE:
1563 if (t->data.klass->enumtype) {
1564 type = t->data.klass->enum_basetype->type;
1567 mono_mb_emit_byte (mb, CEE_LDOBJ);
1568 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, t->data.klass));
1571 g_assert_not_reached ();
1575 if (method->string_ctor) {
1576 MonoMethodSignature *strsig;
1578 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1579 strsig = g_memdup (sig, sigsize);
1580 strsig->ret = &mono_defaults.string_class->byval_arg;
1582 mono_mb_emit_managed_call (mb, method, strsig);
1584 mono_mb_emit_managed_call (mb, method, NULL);
1586 if (sig->ret->byref) {
1588 g_assert_not_reached ();
1592 switch (sig->ret->type) {
1593 case MONO_TYPE_VOID:
1594 if (!method->string_ctor)
1595 mono_mb_emit_byte (mb, CEE_LDNULL);
1609 case MONO_TYPE_VALUETYPE:
1610 /* box value types */
1611 mono_mb_emit_byte (mb, CEE_BOX);
1612 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (sig->ret)));
1614 case MONO_TYPE_STRING:
1615 case MONO_TYPE_CLASS:
1616 case MONO_TYPE_ARRAY:
1617 case MONO_TYPE_SZARRAY:
1618 case MONO_TYPE_OBJECT:
1623 g_assert_not_reached ();
1626 mono_mb_emit_stloc (mb, 0);
1628 mono_mb_emit_byte (mb, CEE_LEAVE);
1630 mono_mb_emit_i4 (mb, 0);
1632 clause = g_new0 (MonoExceptionClause, 1);
1633 clause->flags = MONO_EXCEPTION_CLAUSE_FILTER;
1634 clause->try_len = mb->pos;
1637 clause->token_or_filter = mb->pos;
1639 mono_mb_emit_byte (mb, CEE_POP);
1640 mono_mb_emit_byte (mb, CEE_LDARG_2);
1641 mono_mb_emit_byte (mb, CEE_PREFIX1);
1642 mono_mb_emit_byte (mb, CEE_ENDFILTER);
1644 clause->handler_offset = mb->pos;
1647 /* store exception */
1648 mono_mb_emit_stloc (mb, 1);
1650 mono_mb_emit_byte (mb, CEE_LDARG_2);
1651 mono_mb_emit_ldloc (mb, 1);
1652 mono_mb_emit_byte (mb, CEE_STIND_I);
1654 mono_mb_emit_byte (mb, CEE_LEAVE);
1655 mono_mb_emit_i4 (mb, 0);
1657 clause->handler_len = mb->pos - clause->handler_offset;
1660 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1661 mono_mb_emit_ldloc (mb, 0);
1662 mono_mb_emit_byte (mb, CEE_RET);
1664 res = mono_mb_create_method (mb, csig, sig->param_count + 16);
1667 header = ((MonoMethodNormal *)res)->header;
1668 header->num_clauses = 1;
1669 header->clauses = clause;
1671 g_hash_table_insert (cache, method, res);
1677 * generates IL code to call managed methods from unmanaged code
1680 mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this)
1682 MonoMethodSignature *sig, *csig;
1683 MonoMethodBuilder *mb;
1687 int i, pos, sigsize, *tmp_locals;
1689 g_assert (method != NULL);
1691 cache = method->klass->image->managed_wrapper_cache;
1692 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1695 sig = method->signature;
1697 mb = mono_mb_new (method->klass, method->name);
1698 mb->method->wrapper_type = MONO_WRAPPER_NATIVE_TO_MANAGED;
1700 /* allocate local 0 (pointer) src_ptr */
1701 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1702 /* allocate local 1 (pointer) dst_ptr */
1703 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1704 /* allocate local 2 (boolean) delete_old */
1705 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
1707 mono_mb_emit_byte (mb, CEE_LDNULL);
1708 mono_mb_emit_byte (mb, CEE_STLOC_2);
1710 /* we copy the signature, so that we can modify it */
1711 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1712 csig = g_memdup (sig, sigsize);
1716 /* fixme: howto handle this ? */
1720 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1721 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1722 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, this));
1727 g_assert_not_reached ();
1732 /* we first do all conversions */
1733 tmp_locals = alloca (sizeof (int) * sig->param_count);
1734 for (i = 0; i < sig->param_count; i ++) {
1735 MonoType *t = sig->params [i];
1740 case MONO_TYPE_VALUETYPE:
1742 klass = sig->params [i]->data.klass;
1743 if (klass->blittable || klass->enumtype)
1746 tmp_locals [i] = mono_mb_add_local (mb, &klass->byval_arg);
1749 mono_mb_emit_ldarg (mb, i);
1751 mono_mb_emit_ldarg_addr (mb, i);
1752 mono_mb_emit_byte (mb, CEE_STLOC_0);
1755 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1756 mono_mb_emit_byte (mb, CEE_BRFALSE);
1758 mono_mb_emit_i4 (mb, 0);
1761 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
1762 mono_mb_emit_byte (mb, CEE_STLOC_1);
1764 /* emit valuetype convnversion code code */
1765 emit_struct_conv (mb, klass, TRUE);
1768 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1770 case MONO_TYPE_STRING:
1774 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1775 csig->params [i] = &mono_defaults.int_class->byval_arg;
1777 mono_mb_emit_ldarg (mb, i);
1778 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1779 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1780 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
1781 mono_mb_emit_stloc (mb, tmp_locals [i]);
1783 case MONO_TYPE_ARRAY:
1784 case MONO_TYPE_SZARRAY:
1788 klass = mono_class_from_mono_type (t);
1790 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1791 csig->params [i] = &mono_defaults.int_class->byval_arg;
1793 g_warning ("array marshaling not implemented");
1794 g_assert_not_reached ();
1799 for (i = 0; i < sig->param_count; i++) {
1800 MonoType *t = sig->params [i];
1816 mono_mb_emit_ldarg (mb, i);
1818 case MONO_TYPE_STRING:
1820 mono_mb_emit_ldarg (mb, i);
1822 g_assert (tmp_locals [i]);
1823 mono_mb_emit_ldloc (mb, tmp_locals [i]);
1826 case MONO_TYPE_CLASS:
1827 case MONO_TYPE_ARRAY:
1828 case MONO_TYPE_SZARRAY:
1829 case MONO_TYPE_OBJECT:
1830 /* fixme: conversions ? */
1831 mono_mb_emit_ldarg (mb, i);
1833 case MONO_TYPE_VALUETYPE:
1834 klass = sig->params [i]->data.klass;
1835 if (klass->blittable || klass->enumtype) {
1836 mono_mb_emit_ldarg (mb, i);
1840 g_assert (tmp_locals [i]);
1842 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
1844 mono_mb_emit_ldloc (mb, tmp_locals [i]);
1847 g_warning ("type 0x%02x unknown", t->type);
1848 g_assert_not_reached ();
1852 mono_mb_emit_managed_call (mb, method, NULL);
1854 if (!sig->ret->byref) {
1855 switch (sig->ret->type) {
1856 case MONO_TYPE_VOID:
1857 case MONO_TYPE_BOOLEAN:
1873 case MONO_TYPE_STRING:
1874 csig->ret = &mono_defaults.int_class->byval_arg;
1876 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1877 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1878 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
1880 case MONO_TYPE_VALUETYPE: {
1882 klass = sig->ret->data.klass;
1883 if (klass->blittable || klass->enumtype)
1886 /* load pointer to returned value type */
1887 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1888 mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
1890 /* store the address of the source into local variable 0 */
1891 mono_mb_emit_byte (mb, CEE_STLOC_0);
1892 /* allocate space for the native struct and
1893 * store the address into dst_ptr */
1894 tmp = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1896 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
1897 mono_mb_emit_byte (mb, CEE_PREFIX1);
1898 mono_mb_emit_byte (mb, CEE_LOCALLOC);
1899 mono_mb_emit_byte (mb, CEE_STLOC_1);
1900 mono_mb_emit_byte (mb, CEE_LDLOC_1);
1901 mono_mb_emit_stloc (mb, tmp);
1903 /* emit valuetype conversion code */
1904 emit_struct_conv (mb, klass, FALSE);
1905 mono_mb_emit_ldloc (mb, tmp);
1906 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1907 mono_mb_emit_byte (mb, CEE_MONO_RETOBJ);
1908 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
1912 g_warning ("return type 0x%02x unknown", sig->ret->type);
1913 g_assert_not_reached ();
1917 mono_mb_emit_byte (mb, CEE_RET);
1919 res = mono_mb_create_method (mb, csig, sig->param_count + 16);
1922 g_hash_table_insert (cache, method, res);
1928 * generates IL code for the pinvoke wrapper (the generated method
1929 * calls the unamnage code in method->addr)
1932 mono_marshal_get_native_wrapper (MonoMethod *method)
1934 MonoMethodSignature *sig, *csig;
1935 MonoMethodBuilder *mb;
1939 gboolean pinvoke = FALSE;
1940 int i, pos, argnum, *tmp_locals;
1943 g_assert (method != NULL);
1945 cache = method->klass->image->native_wrapper_cache;
1946 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1949 sig = method->signature;
1951 if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
1952 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
1955 mb = mono_mb_new (method->klass, method->name);
1956 mb->method->wrapper_type = MONO_WRAPPER_MANAGED_TO_NATIVE;
1958 mb->method->save_lmf = 1;
1960 if (pinvoke && !method->addr)
1961 mono_lookup_pinvoke_call (method);
1963 if (!method->addr) {
1964 mono_mb_emit_exception (mb);
1965 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1967 g_hash_table_insert (cache, method, res);
1971 /* we copy the signature, so that we can modify it */
1972 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1973 csig = g_memdup (sig, sigsize);
1975 /* internal calls: we simply push all arguments and call the method (no conversions) */
1976 if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
1978 /* hack - string constructors returns a value */
1979 if (method->string_ctor)
1980 csig->ret = &mono_defaults.string_class->byval_arg;
1983 mono_mb_emit_byte (mb, CEE_LDARG_0);
1985 for (i = 0; i < sig->param_count; i++)
1986 mono_mb_emit_ldarg (mb, i + sig->hasthis);
1988 g_assert (method->addr);
1989 mono_mb_emit_native_call (mb, csig, method->addr);
1991 mono_mb_emit_byte (mb, CEE_RET);
1993 res = mono_mb_create_method (mb, csig, sig->param_count + 16);
1995 g_hash_table_insert (cache, method, res);
2001 /* pinvoke: we need to convert the arguments if necessary */
2005 /* we allocate local for use with emit_struct_conv() */
2006 /* allocate local 0 (pointer) src_ptr */
2007 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2008 /* allocate local 1 (pointer) dst_ptr */
2009 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2010 /* allocate local 2 (boolean) delete_old */
2011 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2013 /* delete_old = FALSE */
2014 mono_mb_emit_icon (mb, 0);
2015 mono_mb_emit_byte (mb, CEE_STLOC_2);
2017 if (sig->ret->type != MONO_TYPE_VOID) {
2018 /* allocate local 3 to store the return value */
2019 mono_mb_add_local (mb, sig->ret);
2022 /* we first do all conversions */
2023 tmp_locals = alloca (sizeof (int) * sig->param_count);
2024 for (i = 0; i < sig->param_count; i ++) {
2025 MonoType *t = sig->params [i];
2027 argnum = i + sig->hasthis;
2031 case MONO_TYPE_VALUETYPE:
2032 klass = t->data.klass;
2033 if (klass->blittable || klass->enumtype)
2036 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2038 /* store the address of the source into local variable 0 */
2040 mono_mb_emit_ldarg (mb, argnum);
2042 mono_mb_emit_ldarg_addr (mb, argnum);
2044 mono_mb_emit_byte (mb, CEE_STLOC_0);
2047 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2048 mono_mb_emit_byte (mb, CEE_BRFALSE);
2050 mono_mb_emit_i4 (mb, 0);
2053 /* allocate space for the native struct and
2054 * store the address into local variable 1 (dest) */
2055 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2056 mono_mb_emit_byte (mb, CEE_PREFIX1);
2057 mono_mb_emit_byte (mb, CEE_LOCALLOC);
2058 mono_mb_emit_stloc (mb, tmp_locals [i]);
2060 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2061 mono_mb_emit_byte (mb, CEE_STLOC_1);
2063 /* emit valuetype conversion code */
2064 emit_struct_conv (mb, klass, FALSE);
2067 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2069 case MONO_TYPE_STRING:
2073 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2074 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2076 mono_mb_emit_ldarg (mb, argnum);
2077 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2078 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2079 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
2080 mono_mb_emit_stloc (mb, tmp_locals [i]);
2082 case MONO_TYPE_CLASS:
2083 case MONO_TYPE_OBJECT:
2087 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2088 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2090 mono_mb_emit_ldarg (mb, argnum);
2091 mono_mb_emit_byte (mb, CEE_BRFALSE);
2093 mono_mb_emit_i4 (mb, 0);
2095 if (t->data.klass->delegate) {
2096 mono_mb_emit_ldarg (mb, argnum);
2097 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2098 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2099 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_DEL_FTN);
2100 mono_mb_emit_stloc (mb, tmp_locals [i]);
2101 } else if (t->data.klass == mono_defaults.stringbuilder_class) {
2102 mono_mb_emit_ldarg (mb, argnum);
2103 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2104 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2105 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_SB_LPSTR);
2106 mono_mb_emit_stloc (mb, tmp_locals [i]);
2108 mono_mb_emit_ldarg (mb, argnum);
2109 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2110 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2111 /* fixme: convert to what ? */
2112 mono_mb_emit_stloc (mb, tmp_locals [i]);
2115 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2118 case MONO_TYPE_ARRAY:
2119 case MONO_TYPE_SZARRAY:
2123 klass = mono_class_from_mono_type (t);
2125 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2126 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2128 mono_mb_emit_ldarg (mb, argnum);
2129 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2130 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2131 if (klass->element_class == mono_defaults.string_class)
2132 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STRARRAY_STRLPARRAY);
2134 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_ARRAY_LPARRAY);
2135 mono_mb_emit_stloc (mb, tmp_locals [i]);
2140 /* push all arguments */
2143 mono_mb_emit_byte (mb, CEE_LDARG_0);
2145 for (i = 0; i < sig->param_count; i++) {
2146 MonoType *t = sig->params [i];
2148 argnum = i + sig->hasthis;
2151 case MONO_TYPE_BOOLEAN:
2153 g_warning ("byref boolean marshalling not inplemented");
2154 mono_mb_emit_ldarg (mb, argnum);
2169 mono_mb_emit_ldarg (mb, argnum);
2171 case MONO_TYPE_VALUETYPE:
2172 klass = sig->params [i]->data.klass;
2173 if (klass->blittable || klass->enumtype) {
2174 mono_mb_emit_ldarg (mb, argnum);
2177 g_assert (tmp_locals [i]);
2178 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2180 mono_mb_emit_byte (mb, CEE_LDOBJ);
2181 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2184 case MONO_TYPE_STRING:
2186 mono_mb_emit_ldarg (mb, argnum);
2188 g_assert (tmp_locals [i]);
2189 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2192 case MONO_TYPE_CLASS:
2193 case MONO_TYPE_OBJECT:
2195 mono_mb_emit_ldarg (mb, argnum);
2197 g_assert (tmp_locals [i]);
2198 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2201 case MONO_TYPE_CHAR:
2202 /* fixme: dont know how to marshal that. We cant simply
2203 * convert it to a one byte UTF8 character, because an
2204 * unicode character may need more that one byte in UTF8 */
2205 mono_mb_emit_ldarg (mb, argnum);
2207 case MONO_TYPE_ARRAY:
2208 case MONO_TYPE_SZARRAY:
2210 mono_mb_emit_ldarg (mb, argnum);
2212 g_assert (tmp_locals [i]);
2213 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2216 case MONO_TYPE_TYPEDBYREF:
2217 case MONO_TYPE_FNPTR:
2219 g_warning ("type 0x%02x unknown", t->type);
2220 g_assert_not_reached ();
2224 /* call the native method */
2225 mono_mb_emit_native_call (mb, csig, method->addr);
2227 /* return the result */
2229 /* we need to convert byref arguments back and free string arrays */
2230 for (i = 0; i < sig->param_count; i++) {
2231 MonoType *t = sig->params [i];
2233 argnum = i + sig->hasthis;
2236 case MONO_TYPE_CLASS:
2237 case MONO_TYPE_OBJECT:
2241 if (t->data.klass == mono_defaults.stringbuilder_class) {
2242 mono_mb_emit_ldarg (mb, argnum);
2243 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2244 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2245 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
2246 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_SB);
2247 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2248 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2249 mono_mb_emit_byte (mb, CEE_MONO_FREE);
2252 case MONO_TYPE_VALUETYPE:
2256 klass = t->data.klass;
2257 if (klass->blittable || klass->enumtype)
2260 /* dst = argument */
2261 mono_mb_emit_ldarg (mb, argnum);
2262 mono_mb_emit_byte (mb, CEE_STLOC_1);
2264 mono_mb_emit_byte (mb, CEE_LDLOC_1);
2265 mono_mb_emit_byte (mb, CEE_BRFALSE);
2267 mono_mb_emit_i4 (mb, 0);
2269 /* src = tmp_locals [i] */
2270 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2271 mono_mb_emit_byte (mb, CEE_STLOC_0);
2273 /* emit valuetype conversion code */
2274 emit_struct_conv (mb, klass, TRUE);
2276 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2278 case MONO_TYPE_SZARRAY:
2282 klass = mono_class_from_mono_type (t);
2284 if (klass->element_class == mono_defaults.string_class) {
2285 g_assert (tmp_locals [i]);
2286 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2287 mono_mb_emit_ldarg (mb, argnum);
2288 mono_mb_emit_byte (mb, CEE_LDLEN);
2289 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2290 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
2291 mono_mb_emit_byte (mb, MONO_MARSHAL_FREE_ARRAY);
2298 if (!sig->ret->byref) {
2299 type = sig->ret->type;
2302 case MONO_TYPE_VOID:
2316 /* no conversions necessary */
2318 case MONO_TYPE_BOOLEAN:
2319 /* maybe we need to make sure that it fits within 8 bits */
2321 case MONO_TYPE_VALUETYPE: {
2324 klass = sig->ret->data.klass;
2325 if (klass->enumtype) {
2326 type = sig->ret->data.klass->enum_basetype->type;
2330 if (klass->blittable)
2333 tmp = mono_mb_add_local (mb, sig->ret);
2335 /* load pointer to returned value type */
2336 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2337 mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
2338 /* store the address of the source into local variable 0 */
2339 mono_mb_emit_byte (mb, CEE_STLOC_0);
2341 mono_mb_emit_ldloc_addr (mb, tmp);
2342 mono_mb_emit_byte (mb, CEE_STLOC_1);
2344 /* emit valuetype conversion code */
2345 emit_struct_conv (mb, sig->ret->data.klass, TRUE);
2347 mono_mb_emit_ldloc (mb, tmp);
2350 case MONO_TYPE_STRING:
2351 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2352 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2353 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
2355 case MONO_TYPE_ARRAY:
2356 case MONO_TYPE_SZARRAY:
2357 case MONO_TYPE_CLASS:
2358 case MONO_TYPE_OBJECT:
2359 /* fixme: we need conversions here */
2361 case MONO_TYPE_CHAR:
2362 /* fixme: we need conversions here */
2364 case MONO_TYPE_TYPEDBYREF:
2365 case MONO_TYPE_FNPTR:
2367 g_warning ("return type 0x%02x unknown", sig->ret->type);
2368 g_assert_not_reached ();
2372 mono_mb_emit_byte (mb, CEE_RET);
2374 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
2377 g_hash_table_insert (cache, method, res);
2383 * generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld)
2386 mono_marshal_get_struct_to_ptr (MonoClass *klass)
2388 MonoMethodBuilder *mb;
2389 static MonoMethod *stoptr = NULL;
2392 g_assert (klass != NULL);
2394 if (klass->str_to_ptr)
2395 return klass->str_to_ptr;
2398 stoptr = mono_find_method_by_name (mono_defaults.marshal_class, "StructureToPtr", 3);
2401 mb = mono_mb_new (klass, stoptr->name);
2403 if (klass->blittable) {
2404 mono_mb_emit_byte (mb, CEE_LDARG_1);
2405 mono_mb_emit_byte (mb, CEE_LDARG_0);
2406 mono_mb_emit_icon (mb, sizeof (MonoObject));
2407 mono_mb_emit_byte (mb, CEE_ADD);
2408 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
2409 mono_mb_emit_byte (mb, CEE_PREFIX1);
2410 mono_mb_emit_byte (mb, CEE_CPBLK);
2413 /* allocate local 0 (pointer) src_ptr */
2414 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2415 /* allocate local 1 (pointer) dst_ptr */
2416 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2417 /* allocate local 2 (boolean) delete_old */
2418 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2419 mono_mb_emit_byte (mb, CEE_LDARG_2);
2420 mono_mb_emit_byte (mb, CEE_STLOC_2);
2422 /* initialize src_ptr to point to the start of object data */
2423 mono_mb_emit_byte (mb, CEE_LDARG_0);
2424 mono_mb_emit_icon (mb, sizeof (MonoObject));
2425 mono_mb_emit_byte (mb, CEE_ADD);
2426 mono_mb_emit_byte (mb, CEE_STLOC_0);
2428 /* initialize dst_ptr */
2429 mono_mb_emit_byte (mb, CEE_LDARG_1);
2430 mono_mb_emit_byte (mb, CEE_STLOC_1);
2432 emit_struct_conv (mb, klass, FALSE);
2435 mono_mb_emit_byte (mb, CEE_RET);
2437 res = mono_mb_create_method (mb, stoptr->signature, 0);
2440 klass->str_to_ptr = res;
2445 * generates IL code for PtrToStructure (IntPtr src, object structure)
2448 mono_marshal_get_ptr_to_struct (MonoClass *klass)
2450 MonoMethodBuilder *mb;
2451 static MonoMethod *ptostr = NULL;
2454 g_assert (klass != NULL);
2456 if (klass->ptr_to_str)
2457 return klass->ptr_to_str;
2460 ptostr = mono_find_method_by_name (mono_defaults.marshal_class, "PtrToStructure", 2);
2463 mb = mono_mb_new (klass, ptostr->name);
2465 if (klass->blittable) {
2466 mono_mb_emit_byte (mb, CEE_LDARG_1);
2467 mono_mb_emit_icon (mb, sizeof (MonoObject));
2468 mono_mb_emit_byte (mb, CEE_ADD);
2469 mono_mb_emit_byte (mb, CEE_LDARG_0);
2470 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
2471 mono_mb_emit_byte (mb, CEE_PREFIX1);
2472 mono_mb_emit_byte (mb, CEE_CPBLK);
2475 /* allocate local 0 (pointer) src_ptr */
2476 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2477 /* allocate local 1 (pointer) dst_ptr */
2478 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2480 /* initialize src_ptr to point to the start of object data */
2481 mono_mb_emit_byte (mb, CEE_LDARG_0);
2482 mono_mb_emit_byte (mb, CEE_STLOC_0);
2484 /* initialize dst_ptr */
2485 mono_mb_emit_byte (mb, CEE_LDARG_1);
2486 mono_mb_emit_icon (mb, sizeof (MonoObject));
2487 mono_mb_emit_byte (mb, CEE_ADD);
2488 mono_mb_emit_byte (mb, CEE_STLOC_1);
2490 emit_struct_conv (mb, klass, TRUE);
2493 mono_mb_emit_byte (mb, CEE_RET);
2495 res = mono_mb_create_method (mb, ptostr->signature, 0);
2498 klass->ptr_to_str = res;
2502 /* FIXME: on win32 we should probably use GlobalAlloc(). */
2504 mono_marshal_alloc (gpointer size) {
2505 return g_try_malloc ((gulong)size);
2509 mono_marshal_free (gpointer ptr) {
2514 mono_marshal_free_array (gpointer *ptr, int size) {
2517 for (i = 0; i < size; i++)
2523 mono_marshal_realloc (gpointer ptr, gpointer size) {
2524 return g_try_realloc (ptr, (gulong)size);
2528 mono_marshal_string_array (MonoArray *array)
2536 len = mono_array_length (array);
2538 result = g_malloc (sizeof (char *) * (len + 1));
2539 for (i = 0; i < len; ++i) {
2540 MonoString *s = (MonoString *)mono_array_get (array, gpointer, i);
2541 result [i] = s ? mono_string_to_utf8 (s): NULL;
2543 /* null terminate the array */
2550 ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArray *src, gint32 start_index,
2551 gpointer dest, gint32 length)
2556 MONO_CHECK_ARG_NULL (src);
2557 MONO_CHECK_ARG_NULL (dest);
2559 g_assert (src->obj.vtable->klass->rank == 1);
2560 g_assert (start_index >= 0 && start_index < mono_array_length (src));
2561 g_assert (start_index + length <= mono_array_length (src));
2563 element_size = mono_array_element_size (src->obj.vtable->klass);
2565 source_addr = mono_array_addr_with_size (src, element_size, start_index);
2567 memcpy (dest, source_addr, length * element_size);
2571 ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer src, gint32 start_index,
2572 MonoArray *dest, gint32 length)
2577 MONO_CHECK_ARG_NULL (src);
2578 MONO_CHECK_ARG_NULL (dest);
2580 g_assert (dest->obj.vtable->klass->rank == 1);
2581 g_assert (start_index >= 0 && start_index < mono_array_length (dest));
2582 g_assert (start_index + length <= mono_array_length (dest));
2584 element_size = mono_array_element_size (dest->obj.vtable->klass);
2586 dest_addr = mono_array_addr_with_size (dest, element_size, start_index);
2588 memcpy (dest_addr, src, length * element_size);
2592 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr, gint32 offset)
2595 return *(gpointer*)(p + offset);
2599 ves_icall_System_Runtime_InteropServices_Marshal_ReadByte (gpointer ptr, gint32 offset)
2602 return *(unsigned char*)(p + offset);
2606 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt16 (gpointer ptr, gint32 offset)
2609 return *(gint16*)(p + offset);
2613 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt32 (gpointer ptr, gint32 offset)
2616 return *(gint32*)(p + offset);
2620 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt64 (gpointer ptr, gint32 offset)
2623 return *(gint64*)(p + offset);
2627 ves_icall_System_Runtime_InteropServices_Marshal_WriteByte (gpointer ptr, gint32 offset, unsigned char val)
2630 *(unsigned char*)(p + offset) = val;
2634 ves_icall_System_Runtime_InteropServices_Marshal_WriteIntPtr (gpointer ptr, gint32 offset, gpointer val)
2637 *(gpointer*)(p + offset) = val;
2641 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt16 (gpointer ptr, gint32 offset, gint16 val)
2644 *(gint16*)(p + offset) = val;
2648 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt32 (gpointer ptr, gint32 offset, gint32 val)
2651 *(gint32*)(p + offset) = val;
2655 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt64 (gpointer ptr, gint32 offset, gint64 val)
2658 *(gint64*)(p + offset) = val;
2662 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (char *ptr)
2664 return mono_string_new (mono_domain_get (), ptr);
2668 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len (char *ptr, gint32 len)
2670 return mono_string_new_len (mono_domain_get (), ptr, len);
2674 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni (guint16 *ptr)
2676 MonoDomain *domain = mono_domain_get ();
2683 return mono_string_new_utf16 (domain, ptr, len);
2687 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len (guint16 *ptr, gint32 len)
2689 MonoDomain *domain = mono_domain_get ();
2691 return mono_string_new_utf16 (domain, ptr, len);
2695 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR (gpointer ptr)
2697 g_warning ("PtrToStringBSTR not implemented");
2698 g_assert_not_reached ();
2704 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
2706 return (GetLastError ());
2710 ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype)
2714 MONO_CHECK_ARG_NULL (rtype);
2716 klass = mono_class_from_mono_type (rtype->type);
2718 return mono_class_native_size (klass, NULL);
2722 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old)
2727 MONO_CHECK_ARG_NULL (obj);
2728 MONO_CHECK_ARG_NULL (dst);
2730 method = mono_marshal_get_struct_to_ptr (obj->vtable->klass);
2734 pa [2] = &delete_old;
2736 mono_runtime_invoke (method, NULL, pa, NULL);
2740 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, MonoObject *dst)
2745 MONO_CHECK_ARG_NULL (src);
2746 MONO_CHECK_ARG_NULL (dst);
2748 method = mono_marshal_get_ptr_to_struct (dst->vtable->klass);
2753 mono_runtime_invoke (method, NULL, pa, NULL);
2757 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer src, MonoReflectionType *type)
2759 MonoDomain *domain = mono_domain_get ();
2762 MONO_CHECK_ARG_NULL (src);
2763 MONO_CHECK_ARG_NULL (type);
2765 res = mono_object_new (domain, mono_class_from_mono_type (type->type));
2767 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (src, res);
2773 ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *type, MonoString *field_name)
2775 MonoMarshalType *info;
2780 MONO_CHECK_ARG_NULL (type);
2781 MONO_CHECK_ARG_NULL (field_name);
2783 fname = mono_string_to_utf8 (field_name);
2784 klass = mono_class_from_mono_type (type->type);
2786 info = mono_marshal_load_type_info (klass);
2788 for (i = 0; i < klass->field.count; ++i) {
2789 if (*fname == *klass->fields [i].name &&
2790 strcmp (fname, klass->fields [i].name) == 0)
2795 mono_assert (i < klass->field.count);
2797 return info->fields [i].offset;
2801 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString *string)
2803 return mono_string_to_utf8 (string);
2807 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni (MonoString *string)
2809 return g_memdup (mono_string_chars (string), mono_string_length (string)*2);
2813 mono_struct_delete_old (MonoClass *klass, char *ptr)
2815 MonoMarshalType *info;
2818 info = mono_marshal_load_type_info (klass);
2820 for (i = 0; i < info->num_fields; i++) {
2821 MonoMarshalNative ntype;
2822 MonoMarshalConv conv;
2823 MonoType *ftype = info->fields [i].field->type;
2826 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
2829 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE,
2830 klass->unicode, &conv);
2832 cpos = ptr + info->fields [i].offset;
2835 case MONO_MARSHAL_CONV_NONE:
2836 if (MONO_TYPE_ISSTRUCT (ftype)) {
2837 mono_struct_delete_old (ftype->data.klass, cpos);
2841 case MONO_MARSHAL_CONV_STR_LPWSTR:
2842 case MONO_MARSHAL_CONV_STR_LPSTR:
2843 case MONO_MARSHAL_CONV_STR_LPTSTR:
2844 case MONO_MARSHAL_CONV_STR_BSTR:
2845 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
2846 case MONO_MARSHAL_CONV_STR_TBSTR:
2847 g_free (*(gpointer *)cpos);
2856 ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure (gpointer src, MonoReflectionType *type)
2860 MONO_CHECK_ARG_NULL (src);
2861 MONO_CHECK_ARG_NULL (type);
2863 klass = mono_class_from_mono_type (type->type);
2865 mono_struct_delete_old (klass, (char *)src);