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, MonoWrapperType type)
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 = type;
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 g_list_length (mw->data);
317 mono_mb_patch_addr (MonoMethodBuilder *mb, int pos, int value)
319 mb->code [pos] = value & 0xff;
320 mb->code [pos + 1] = (value >> 8) & 0xff;
321 mb->code [pos + 2] = (value >> 16) & 0xff;
322 mb->code [pos + 3] = (value >> 24) & 0xff;
326 mono_mb_patch_addr_s (MonoMethodBuilder *mb, int pos, gint8 value)
328 *((gint8 *)(&mb->code [pos])) = value;
332 mono_mb_emit_byte (MonoMethodBuilder *mb, guint8 op)
334 if (mb->pos >= mb->code_size) {
336 mb->code = g_realloc (mb->code, mb->code_size);
339 mb->code [mb->pos++] = op;
343 mono_mb_emit_ldflda (MonoMethodBuilder *mb, gint32 offset)
345 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
346 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
347 mono_mb_emit_icon (mb, offset);
348 mono_mb_emit_byte (mb, CEE_ADD);
352 mono_mb_emit_i4 (MonoMethodBuilder *mb, gint32 data)
354 if ((mb->pos + 4) >= mb->code_size) {
356 mb->code = g_realloc (mb->code, mb->code_size);
359 mono_mb_patch_addr (mb, mb->pos, data);
364 mono_mb_emit_i2 (MonoMethodBuilder *mb, gint16 data)
366 if ((mb->pos + 2) >= mb->code_size) {
368 mb->code = g_realloc (mb->code, mb->code_size);
371 mb->code [mb->pos] = data & 0xff;
372 mb->code [mb->pos + 1] = (data >> 8) & 0xff;
377 mono_mb_emit_ldarg (MonoMethodBuilder *mb, guint argnum)
380 mono_mb_emit_byte (mb, CEE_LDARG_0 + argnum);
381 } else if (argnum < 256) {
382 mono_mb_emit_byte (mb, CEE_LDARG_S);
383 mono_mb_emit_byte (mb, argnum);
385 mono_mb_emit_byte (mb, CEE_PREFIX1);
386 mono_mb_emit_byte (mb, CEE_LDARG);
387 mono_mb_emit_i2 (mb, argnum);
392 mono_mb_emit_ldarg_addr (MonoMethodBuilder *mb, guint argnum)
395 mono_mb_emit_byte (mb, CEE_LDARGA_S);
396 mono_mb_emit_byte (mb, argnum);
398 mono_mb_emit_byte (mb, CEE_PREFIX1);
399 mono_mb_emit_byte (mb, CEE_LDARGA);
400 mono_mb_emit_i2 (mb, argnum);
405 mono_mb_emit_ldloc_addr (MonoMethodBuilder *mb, guint locnum)
408 mono_mb_emit_byte (mb, CEE_LDLOCA_S);
409 mono_mb_emit_byte (mb, locnum);
411 mono_mb_emit_byte (mb, CEE_PREFIX1);
412 mono_mb_emit_byte (mb, CEE_LDLOCA);
413 mono_mb_emit_i2 (mb, locnum);
418 mono_mb_emit_ldloc (MonoMethodBuilder *mb, guint num)
421 mono_mb_emit_byte (mb, CEE_LDLOC_0 + num);
422 } else if (num < 256) {
423 mono_mb_emit_byte (mb, CEE_LDLOC_S);
424 mono_mb_emit_byte (mb, num);
426 mono_mb_emit_byte (mb, CEE_PREFIX1);
427 mono_mb_emit_byte (mb, CEE_LDLOC);
428 mono_mb_emit_i2 (mb, num);
433 mono_mb_emit_stloc (MonoMethodBuilder *mb, guint num)
436 mono_mb_emit_byte (mb, CEE_STLOC_0 + num);
437 } else if (num < 256) {
438 mono_mb_emit_byte (mb, CEE_STLOC_S);
439 mono_mb_emit_byte (mb, num);
441 mono_mb_emit_byte (mb, CEE_PREFIX1);
442 mono_mb_emit_byte (mb, CEE_STLOC);
443 mono_mb_emit_i2 (mb, num);
448 mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value)
450 if (value >= -1 && value < 8) {
451 mono_mb_emit_byte (mb, CEE_LDC_I4_0 + value);
452 } else if (value >= -128 && value <= 127) {
453 mono_mb_emit_byte (mb, CEE_LDC_I4_S);
454 mono_mb_emit_byte (mb, value);
456 mono_mb_emit_byte (mb, CEE_LDC_I4);
457 mono_mb_emit_i4 (mb, value);
462 mono_mb_emit_managed_call (MonoMethodBuilder *mb, MonoMethod *method, MonoMethodSignature *opt_sig)
465 opt_sig = method->signature;
466 mono_mb_emit_byte (mb, CEE_PREFIX1);
467 mono_mb_emit_byte (mb, CEE_LDFTN);
468 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
469 mono_mb_emit_byte (mb, CEE_CALLI);
470 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, opt_sig));
474 mono_mb_emit_native_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, gpointer func)
476 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
477 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
478 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, func));
479 mono_mb_emit_byte (mb, CEE_CALLI);
480 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
484 mono_mb_emit_exception (MonoMethodBuilder *mb)
486 /* fixme: we need a better way to throw exception,
487 * supporting several exception types and messages */
488 static MonoMethod *missing_method_ctor = NULL;
490 if (!missing_method_ctor) {
491 MonoClass *mme = mono_class_from_name (mono_defaults.corlib, "System", "MissingMethodException");
493 mono_class_init (mme);
494 for (i = 0; i < mme->method.count; ++i) {
495 if (strcmp (mme->methods [i]->name, ".ctor") == 0 && mme->methods [i]->signature->param_count == 0) {
496 missing_method_ctor = mme->methods [i];
501 mono_mb_emit_byte (mb, CEE_NEWOBJ);
502 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, missing_method_ctor));
503 mono_mb_emit_byte (mb, CEE_THROW);
508 mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint8 local, gint8 incr)
510 mono_mb_emit_ldloc (mb, local);
511 mono_mb_emit_icon (mb, incr);
512 mono_mb_emit_byte (mb, CEE_ADD);
513 mono_mb_emit_stloc (mb, local);
517 emit_ptr_to_str_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv,
518 int usize, int msize)
521 case MONO_MARSHAL_CONV_BOOL_I4:
522 mono_mb_emit_byte (mb, CEE_LDLOC_0);
523 mono_mb_emit_byte (mb, CEE_LDIND_I);
524 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
525 mono_mb_emit_byte (mb, 5);
526 mono_mb_emit_byte (mb, CEE_LDLOC_1);
527 mono_mb_emit_byte (mb, CEE_LDC_I4_1);
528 mono_mb_emit_byte (mb, CEE_STIND_I1);
529 mono_mb_emit_byte (mb, CEE_BR_S);
530 mono_mb_emit_byte (mb, 3);
531 mono_mb_emit_byte (mb, CEE_LDLOC_1);
532 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
533 mono_mb_emit_byte (mb, CEE_STIND_I1);
535 case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
539 if (type->type == MONO_TYPE_ARRAY)
540 eclass = mono_class_from_mono_type (type->data.array->type);
541 else if (type->type == MONO_TYPE_SZARRAY) {
542 eclass = mono_class_from_mono_type (type->data.type);
544 g_assert_not_reached ();
547 if (eclass->valuetype)
548 esize = mono_class_instance_size (eclass) - sizeof (MonoObject);
550 esize = sizeof (gpointer);
552 /* create a new array */
553 /* fixme: this only works for SZARRAYS */
554 mono_mb_emit_byte (mb, CEE_LDLOC_1);
555 mono_mb_emit_icon (mb, msize / esize);
556 mono_mb_emit_byte (mb, CEE_NEWARR);
557 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eclass));
558 mono_mb_emit_byte (mb, CEE_STIND_I);
560 /* copy the elements */
561 mono_mb_emit_byte (mb, CEE_LDLOC_1);
562 mono_mb_emit_byte (mb, CEE_LDIND_I);
563 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
564 mono_mb_emit_byte (mb, CEE_ADD);
565 mono_mb_emit_byte (mb, CEE_LDLOC_0);
566 mono_mb_emit_icon (mb, usize);
567 mono_mb_emit_byte (mb, CEE_PREFIX1);
568 mono_mb_emit_byte (mb, CEE_CPBLK);
572 case MONO_MARSHAL_CONV_STR_BYVALSTR:
573 mono_mb_emit_byte (mb, CEE_LDLOC_1);
574 mono_mb_emit_byte (mb, CEE_LDLOC_0);
575 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
576 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
577 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
578 mono_mb_emit_byte (mb, CEE_STIND_I);
580 case MONO_MARSHAL_CONV_STR_LPTSTR:
581 case MONO_MARSHAL_CONV_STR_LPSTR:
582 mono_mb_emit_byte (mb, CEE_LDLOC_1);
583 mono_mb_emit_byte (mb, CEE_LDLOC_0);
584 mono_mb_emit_byte (mb, CEE_LDIND_I);
585 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
586 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
587 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
588 mono_mb_emit_byte (mb, CEE_STIND_I);
590 case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
591 MonoClass *klass = mono_class_from_mono_type (type);
592 int src_var, dst_var;
594 src_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
595 dst_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
597 /* *dst = new object */
598 mono_mb_emit_byte (mb, CEE_LDLOC_1);
599 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
600 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
601 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
602 mono_mb_emit_byte (mb, CEE_STIND_I);
604 /* save the old src pointer */
605 mono_mb_emit_byte (mb, CEE_LDLOC_0);
606 mono_mb_emit_stloc (mb, src_var);
607 /* save the old dst pointer */
608 mono_mb_emit_byte (mb, CEE_LDLOC_1);
609 mono_mb_emit_stloc (mb, dst_var);
611 /* dst = pointer to newly created object data */
612 mono_mb_emit_byte (mb, CEE_LDLOC_1);
613 mono_mb_emit_byte (mb, CEE_LDIND_I);
614 mono_mb_emit_icon (mb, sizeof (MonoObject));
615 mono_mb_emit_byte (mb, CEE_ADD);
616 mono_mb_emit_byte (mb, CEE_STLOC_1);
618 emit_struct_conv (mb, klass, TRUE);
620 /* restore the old src pointer */
621 mono_mb_emit_ldloc (mb, src_var);
622 mono_mb_emit_byte (mb, CEE_STLOC_0);
623 /* restore the old dst pointer */
624 mono_mb_emit_ldloc (mb, dst_var);
625 mono_mb_emit_byte (mb, CEE_STLOC_1);
628 case MONO_MARSHAL_CONV_DEL_FTN: {
629 // fixme: we never convert functions back to delegates, dont
630 // know if thats the correct behaviour
633 case MONO_MARSHAL_CONV_STR_LPWSTR:
634 case MONO_MARSHAL_CONV_STR_BSTR:
635 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
636 case MONO_MARSHAL_CONV_STR_TBSTR:
637 case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
638 case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
639 case MONO_MARSHAL_CONV_STR_BYVALWSTR:
640 case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
642 g_warning ("marshaling conversion %d not implemented", conv);
643 g_assert_not_reached ();
648 emit_str_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, int usize, int msize)
653 case MONO_MARSHAL_CONV_BOOL_I4:
654 mono_mb_emit_byte (mb, CEE_LDLOC_1);
655 mono_mb_emit_byte (mb, CEE_LDLOC_0);
656 mono_mb_emit_byte (mb, CEE_LDIND_U1);
657 mono_mb_emit_byte (mb, CEE_STIND_I4);
659 case MONO_MARSHAL_CONV_STR_LPWSTR:
660 case MONO_MARSHAL_CONV_STR_LPSTR:
661 case MONO_MARSHAL_CONV_STR_LPTSTR:
662 case MONO_MARSHAL_CONV_STR_BSTR:
663 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
664 case MONO_MARSHAL_CONV_STR_TBSTR:
665 /* free space if free == true */
666 mono_mb_emit_byte (mb, CEE_LDLOC_2);
667 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
668 mono_mb_emit_byte (mb, 4);
669 mono_mb_emit_byte (mb, CEE_LDLOC_1);
670 mono_mb_emit_byte (mb, CEE_LDIND_I);
671 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
672 mono_mb_emit_byte (mb, CEE_MONO_FREE);
674 mono_mb_emit_byte (mb, CEE_LDLOC_1);
675 mono_mb_emit_byte (mb, CEE_LDLOC_0);
676 mono_mb_emit_byte (mb, CEE_LDIND_I);
677 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
678 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
679 mono_mb_emit_byte (mb, conv);
680 mono_mb_emit_byte (mb, CEE_STIND_I);
682 case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
683 case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
684 case MONO_MARSHAL_CONV_DEL_FTN:
685 mono_mb_emit_byte (mb, CEE_LDLOC_1);
686 mono_mb_emit_byte (mb, CEE_LDLOC_0);
687 mono_mb_emit_byte (mb, CEE_LDIND_I);
688 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
689 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
690 mono_mb_emit_byte (mb, conv);
691 mono_mb_emit_byte (mb, CEE_STIND_I);
693 case MONO_MARSHAL_CONV_STR_BYVALSTR:
694 case MONO_MARSHAL_CONV_STR_BYVALWSTR: {
698 mono_mb_emit_byte (mb, CEE_LDLOC_1); /* dst */
699 mono_mb_emit_byte (mb, CEE_LDLOC_0);
700 mono_mb_emit_byte (mb, CEE_LDIND_I); /* src String */
701 mono_mb_emit_icon (mb, usize);
702 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
703 mono_mb_emit_byte (mb, CEE_MONO_PROC3);
704 mono_mb_emit_byte (mb, conv);
707 case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
711 mono_mb_emit_byte (mb, CEE_LDLOC_0);
712 mono_mb_emit_byte (mb, CEE_LDIND_I);
713 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
715 mono_mb_emit_byte (mb, 0);
717 mono_mb_emit_byte (mb, CEE_LDLOC_1);
718 mono_mb_emit_byte (mb, CEE_LDLOC_0);
719 mono_mb_emit_byte (mb, CEE_LDIND_I);
720 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
721 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
722 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
723 mono_mb_emit_byte (mb, CEE_ADD);
724 mono_mb_emit_icon (mb, usize);
725 mono_mb_emit_byte (mb, CEE_PREFIX1);
726 mono_mb_emit_byte (mb, CEE_CPBLK);
727 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
730 case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
731 int src_var, dst_var;
733 src_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
734 dst_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
736 mono_mb_emit_byte (mb, CEE_LDLOC_0);
737 mono_mb_emit_byte (mb, CEE_LDIND_I);
738 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
740 mono_mb_emit_byte (mb, 0);
742 /* save the old src pointer */
743 mono_mb_emit_byte (mb, CEE_LDLOC_0);
744 mono_mb_emit_stloc (mb, src_var);
745 /* save the old dst pointer */
746 mono_mb_emit_byte (mb, CEE_LDLOC_1);
747 mono_mb_emit_stloc (mb, dst_var);
749 /* src = pointer to object data */
750 mono_mb_emit_byte (mb, CEE_LDLOC_0);
751 mono_mb_emit_byte (mb, CEE_LDIND_I);
752 mono_mb_emit_icon (mb, sizeof (MonoObject));
753 mono_mb_emit_byte (mb, CEE_ADD);
754 mono_mb_emit_byte (mb, CEE_STLOC_0);
756 emit_struct_conv (mb, mono_class_from_mono_type (type), FALSE);
758 /* restore the old src pointer */
759 mono_mb_emit_ldloc (mb, src_var);
760 mono_mb_emit_byte (mb, CEE_STLOC_0);
761 /* restore the old dst pointer */
762 mono_mb_emit_ldloc (mb, dst_var);
763 mono_mb_emit_byte (mb, CEE_STLOC_1);
765 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
768 case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
770 g_warning ("marshalling conversion %d not implemented", conv);
771 g_assert_not_reached ();
776 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
778 MonoMarshalType *info;
781 info = mono_marshal_load_type_info (klass);
783 for (i = 0; i < info->num_fields; i++) {
784 MonoMarshalNative ntype;
785 MonoMarshalConv conv;
786 MonoType *ftype = info->fields [i].field->type;
789 gboolean last_field = i < (info->num_fields -1) ? 0 : 1;
791 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
794 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, klass->unicode, &conv);
797 msize = klass->instance_size - info->fields [i].field->offset;
798 usize = info->native_size - info->fields [i].offset;
800 msize = klass->fields [i + 1].offset - info->fields [i].field->offset;
801 usize = info->fields [i + 1].offset - info->fields [i].offset;
803 g_assert (msize > 0 && usize > 0);
806 case MONO_MARSHAL_CONV_NONE: {
809 if (ftype->byref || ftype->type == MONO_TYPE_I ||
810 ftype->type == MONO_TYPE_U) {
811 mono_mb_emit_byte (mb, CEE_LDLOC_1);
812 mono_mb_emit_byte (mb, CEE_LDLOC_0);
813 mono_mb_emit_byte (mb, CEE_LDIND_I);
814 mono_mb_emit_byte (mb, CEE_STIND_I);
823 mono_mb_emit_byte (mb, CEE_LDLOC_1);
824 mono_mb_emit_byte (mb, CEE_LDLOC_0);
825 mono_mb_emit_byte (mb, CEE_LDIND_I4);
826 mono_mb_emit_byte (mb, CEE_STIND_I4);
830 case MONO_TYPE_BOOLEAN:
831 mono_mb_emit_byte (mb, CEE_LDLOC_1);
832 mono_mb_emit_byte (mb, CEE_LDLOC_0);
833 mono_mb_emit_byte (mb, CEE_LDIND_I1);
834 mono_mb_emit_byte (mb, CEE_STIND_I1);
838 mono_mb_emit_byte (mb, CEE_LDLOC_1);
839 mono_mb_emit_byte (mb, CEE_LDLOC_0);
840 mono_mb_emit_byte (mb, CEE_LDIND_I2);
841 mono_mb_emit_byte (mb, CEE_STIND_I2);
845 mono_mb_emit_byte (mb, CEE_LDLOC_1);
846 mono_mb_emit_byte (mb, CEE_LDLOC_0);
847 mono_mb_emit_byte (mb, CEE_LDIND_I8);
848 mono_mb_emit_byte (mb, CEE_STIND_I8);
851 mono_mb_emit_byte (mb, CEE_LDLOC_1);
852 mono_mb_emit_byte (mb, CEE_LDLOC_0);
853 mono_mb_emit_byte (mb, CEE_LDIND_R4);
854 mono_mb_emit_byte (mb, CEE_STIND_R4);
857 mono_mb_emit_byte (mb, CEE_LDLOC_1);
858 mono_mb_emit_byte (mb, CEE_LDLOC_0);
859 mono_mb_emit_byte (mb, CEE_LDIND_R8);
860 mono_mb_emit_byte (mb, CEE_STIND_R8);
862 case MONO_TYPE_VALUETYPE:
863 if (ftype->data.klass->enumtype) {
864 t = ftype->data.klass->enum_basetype->type;
867 emit_struct_conv (mb, ftype->data.klass, to_object);
870 g_warning ("marshaling type %02x not implemented", ftype->type);
871 g_assert_not_reached ();
877 emit_ptr_to_str_conv (mb, ftype, conv, usize, msize);
879 emit_str_to_ptr_conv (mb, ftype, conv, usize, msize);
883 mono_mb_emit_add_to_local (mb, 0, usize);
884 mono_mb_emit_add_to_local (mb, 1, msize);
886 mono_mb_emit_add_to_local (mb, 0, msize);
887 mono_mb_emit_add_to_local (mb, 1, usize);
892 static MonoAsyncResult *
893 mono_delegate_begin_invoke (MonoDelegate *delegate, gpointer *params)
895 MonoMethodMessage *msg;
896 MonoDelegate *async_callback;
900 MonoMethod *method = NULL;
905 klass = delegate->object.vtable->klass;
907 method = mono_get_delegate_invoke (klass);
908 for (i = 0; i < klass->method.count; ++i) {
909 if (klass->methods [i]->name[0] == 'B' &&
910 !strcmp ("BeginInvoke", klass->methods [i]->name)) {
911 method = klass->methods [i];
916 g_assert (method != NULL);
918 im = mono_get_delegate_invoke (method->klass);
920 msg = mono_method_call_message_new (method, params, im, &async_callback, &state);
922 return mono_thread_pool_add ((MonoObject *)delegate, msg, async_callback, state);
926 mono_mb_emit_save_args (MonoMethodBuilder *mb, MonoMethodSignature *sig, gboolean save_this)
928 int i, params_var, tmp_var;
930 /* allocate local (pointer) *params[] */
931 params_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
932 /* allocate local (pointer) tmp */
933 tmp_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
935 /* alloate space on stack to store an array of pointers to the arguments */
936 mono_mb_emit_icon (mb, sizeof (gpointer) * (sig->param_count + 1));
937 mono_mb_emit_byte (mb, CEE_PREFIX1);
938 mono_mb_emit_byte (mb, CEE_LOCALLOC);
939 mono_mb_emit_stloc (mb, params_var);
942 mono_mb_emit_ldloc (mb, params_var);
943 mono_mb_emit_stloc (mb, tmp_var);
945 if (save_this && sig->hasthis) {
946 mono_mb_emit_ldloc (mb, tmp_var);
947 mono_mb_emit_ldarg_addr (mb, 0);
948 mono_mb_emit_byte (mb, CEE_STIND_I);
949 /* tmp = tmp + sizeof (gpointer) */
950 if (sig->param_count)
951 mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
955 for (i = 0; i < sig->param_count; i++) {
956 mono_mb_emit_ldloc (mb, tmp_var);
957 mono_mb_emit_ldarg_addr (mb, i + sig->hasthis);
958 mono_mb_emit_byte (mb, CEE_STIND_I);
959 /* tmp = tmp + sizeof (gpointer) */
960 if (i < (sig->param_count - 1))
961 mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
968 mono_signature_to_name (MonoMethodSignature *sig, const char *prefix)
972 GString *res = g_string_new ("");
975 g_string_append (res, prefix);
976 g_string_append_c (res, '_');
979 mono_type_get_desc (res, sig->ret, FALSE);
981 for (i = 0; i < sig->param_count; ++i) {
982 g_string_append_c (res, '_');
983 mono_type_get_desc (res, sig->params [i], FALSE);
986 g_string_free (res, FALSE);
991 mono_marshal_get_delegate_begin_invoke (MonoMethod *method)
993 MonoMethodSignature *sig;
994 static MonoMethodSignature *csig = NULL;
995 MonoMethodBuilder *mb;
1001 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1002 !strcmp (method->name, "BeginInvoke"));
1004 sig = method->signature;
1006 cache = method->klass->image->delegate_begin_invoke_cache;
1007 if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1010 g_assert (sig->hasthis);
1013 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1014 csig = g_malloc0 (sigsize);
1016 /* MonoAsyncResult * begin_invoke (MonoDelegate *delegate, gpointer params[]) */
1017 csig->param_count = 2;
1018 csig->ret = &mono_defaults.object_class->byval_arg;
1019 csig->params [0] = &mono_defaults.object_class->byval_arg;
1020 csig->params [1] = &mono_defaults.int_class->byval_arg;
1023 name = mono_signature_to_name (sig, "begin_invoke");
1024 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_BEGIN_INVOKE);
1027 mb->method->save_lmf = 1;
1029 params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1031 mono_mb_emit_ldarg (mb, 0);
1032 mono_mb_emit_ldloc (mb, params_var);
1033 mono_mb_emit_native_call (mb, csig, mono_delegate_begin_invoke);
1034 mono_mb_emit_byte (mb, CEE_RET);
1036 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1038 g_hash_table_insert (cache, sig, res);
1043 mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params)
1045 MonoDomain *domain = mono_domain_get ();
1046 MonoAsyncResult *ares;
1047 MonoMethod *method = NULL;
1048 MonoMethodSignature *sig;
1049 MonoMethodMessage *msg;
1050 MonoObject *res, *exc;
1051 MonoArray *out_args;
1055 g_assert (delegate);
1057 if (!delegate->method_info || !delegate->method_info->method)
1058 g_assert_not_reached ();
1060 klass = delegate->object.vtable->klass;
1062 for (i = 0; i < klass->method.count; ++i) {
1063 if (klass->methods [i]->name[0] == 'E' &&
1064 !strcmp ("EndInvoke", klass->methods [i]->name)) {
1065 method = klass->methods [i];
1070 g_assert (method != NULL);
1072 sig = method->signature;
1074 msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1076 ares = mono_array_get (msg->args, gpointer, sig->param_count - 1);
1079 res = mono_thread_pool_finish (ares, &out_args, &exc);
1082 char *strace = mono_string_to_utf8 (((MonoException*)exc)->stack_trace);
1084 tmp = g_strdup_printf ("%s\nException Rethrown at:\n", strace);
1086 ((MonoException*)exc)->stack_trace = mono_string_new (domain, tmp);
1088 mono_raise_exception ((MonoException*)exc);
1091 mono_method_return_message_restore (method, params, out_args);
1096 mono_mb_emit_restore_result (MonoMethodBuilder *mb, MonoType *return_type)
1098 if (return_type->byref)
1099 return_type = &mono_defaults.int_class->byval_arg;
1100 else if (return_type->type == MONO_TYPE_VALUETYPE && return_type->data.klass->enumtype)
1101 return_type = return_type->data.klass->enum_basetype;
1103 switch (return_type->type) {
1104 case MONO_TYPE_VOID:
1105 g_assert_not_reached ();
1107 case MONO_TYPE_STRING:
1108 case MONO_TYPE_CLASS:
1109 case MONO_TYPE_OBJECT:
1110 case MONO_TYPE_ARRAY:
1111 case MONO_TYPE_SZARRAY:
1115 case MONO_TYPE_BOOLEAN:
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_U1);
1121 mono_mb_emit_byte (mb, CEE_UNBOX);
1122 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1123 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1126 case MONO_TYPE_CHAR:
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_U2);
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_I2);
1138 mono_mb_emit_byte (mb, CEE_UNBOX);
1139 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1140 mono_mb_emit_byte (mb, CEE_LDIND_I);
1143 mono_mb_emit_byte (mb, CEE_UNBOX);
1144 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1145 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1148 mono_mb_emit_byte (mb, CEE_UNBOX);
1149 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1150 mono_mb_emit_byte (mb, CEE_LDIND_U4);
1154 mono_mb_emit_byte (mb, CEE_UNBOX);
1155 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1156 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1159 mono_mb_emit_byte (mb, CEE_UNBOX);
1160 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1161 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1164 mono_mb_emit_byte (mb, CEE_UNBOX);
1165 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1166 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1168 case MONO_TYPE_VALUETYPE: {
1170 mono_mb_emit_byte (mb, CEE_UNBOX);
1171 class = mono_mb_add_data (mb, mono_class_from_mono_type (return_type));
1172 mono_mb_emit_i4 (mb, class);
1173 mono_mb_emit_byte (mb, CEE_LDOBJ);
1174 mono_mb_emit_i4 (mb, class);
1178 g_warning ("type 0x%x not handled", return_type->type);
1179 g_assert_not_reached ();
1182 mono_mb_emit_byte (mb, CEE_RET);
1186 mono_marshal_get_delegate_end_invoke (MonoMethod *method)
1188 MonoMethodSignature *sig;
1189 static MonoMethodSignature *csig = NULL;
1190 MonoMethodBuilder *mb;
1196 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1197 !strcmp (method->name, "EndInvoke"));
1199 sig = method->signature;
1201 cache = method->klass->image->delegate_end_invoke_cache;
1202 if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1205 g_assert (sig->hasthis);
1208 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1209 csig = g_malloc0 (sigsize);
1211 /* MonoObject *end_invoke (MonoDelegate *delegate, gpointer params[]) */
1212 csig->param_count = 2;
1213 csig->ret = &mono_defaults.object_class->byval_arg;
1214 csig->params [0] = &mono_defaults.object_class->byval_arg;
1215 csig->params [1] = &mono_defaults.int_class->byval_arg;
1218 name = mono_signature_to_name (sig, "end_invoke");
1219 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_END_INVOKE);
1222 mb->method->save_lmf = 1;
1224 params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1226 mono_mb_emit_ldarg (mb, 0);
1227 mono_mb_emit_ldloc (mb, params_var);
1228 mono_mb_emit_native_call (mb, csig, mono_delegate_end_invoke);
1230 if (sig->ret->type == MONO_TYPE_VOID) {
1231 mono_mb_emit_byte (mb, CEE_POP);
1232 mono_mb_emit_byte (mb, CEE_RET);
1234 mono_mb_emit_restore_result (mb, sig->ret);
1236 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1238 g_hash_table_insert (cache, sig, res);
1244 mono_remoting_wrapper (MonoMethod *method, gpointer *params)
1246 MonoMethodMessage *msg;
1247 MonoTransparentProxy *this;
1248 MonoObject *res, *exc;
1249 MonoArray *out_args;
1251 this = *((MonoTransparentProxy **)params [0]);
1254 g_assert (((MonoObject *)this)->vtable->klass == mono_defaults.transparent_proxy_class);
1256 /* skip the this pointer */
1259 msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1261 res = mono_remoting_invoke ((MonoObject *)this->rp, msg, &exc, &out_args);
1264 mono_raise_exception ((MonoException *)exc);
1266 mono_method_return_message_restore (method, params, out_args);
1272 mono_marshal_get_remoting_invoke (MonoMethod *method)
1274 MonoMethodSignature *sig;
1275 static MonoMethodSignature *csig = NULL;
1276 MonoMethodBuilder *mb;
1283 if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE)
1286 sig = method->signature;
1288 /* we cant remote methods without this pointer */
1292 cache = method->klass->image->remoting_invoke_cache;
1293 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1297 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1298 csig = g_malloc0 (sigsize);
1300 /* MonoObject *remoting_wrapper (MonoMethod *method, gpointer params[]) */
1301 csig->param_count = 2;
1302 csig->ret = &mono_defaults.object_class->byval_arg;
1303 csig->params [0] = &mono_defaults.int_class->byval_arg;
1304 csig->params [1] = &mono_defaults.int_class->byval_arg;
1307 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE);
1308 mb->method->save_lmf = 1;
1310 params_var = mono_mb_emit_save_args (mb, sig, TRUE);
1312 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1313 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1314 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
1315 mono_mb_emit_ldloc (mb, params_var);
1316 mono_mb_emit_native_call (mb, csig, mono_remoting_wrapper);
1318 if (sig->ret->type == MONO_TYPE_VOID)
1319 mono_mb_emit_byte (mb, CEE_POP);
1321 mono_mb_emit_restore_result (mb, sig->ret);
1323 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1325 g_hash_table_insert (cache, method, res);
1330 * the returned method invokes all methods in a multicast delegate
1333 mono_marshal_get_delegate_invoke (MonoMethod *method)
1335 MonoMethodSignature *sig, *static_sig;
1337 MonoMethodBuilder *mb;
1343 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1344 !strcmp (method->name, "Invoke"));
1346 sig = method->signature;
1348 cache = method->klass->image->delegate_invoke_cache;
1349 if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1352 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1353 static_sig = g_memdup (sig, sigsize);
1354 static_sig->hasthis = 0;
1356 name = mono_signature_to_name (sig, "invoke");
1357 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_INVOKE);
1360 /* allocate local 0 (object) */
1361 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1363 g_assert (sig->hasthis);
1367 * prev.Invoke( args .. );
1368 * return this.<target>( args .. );
1371 /* get this->prev */
1372 mono_mb_emit_ldarg (mb, 0);
1373 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoMulticastDelegate, prev));
1374 mono_mb_emit_byte (mb, CEE_LDIND_I );
1375 mono_mb_emit_stloc (mb, 0);
1377 /* if prev != null */
1378 mono_mb_emit_ldloc (mb, 0);
1379 mono_mb_emit_byte (mb, CEE_BRFALSE);
1382 mono_mb_emit_i4 (mb, 0);
1385 mono_mb_emit_ldloc (mb, 0);
1386 for (i = 0; i < sig->param_count; i++)
1387 mono_mb_emit_ldarg (mb, i + 1);
1388 mono_mb_emit_managed_call (mb, method, method->signature);
1389 if (sig->ret->type != MONO_TYPE_VOID)
1390 mono_mb_emit_byte (mb, CEE_POP);
1392 /* continued or prev == null */
1393 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1395 /* get this->target */
1396 mono_mb_emit_ldarg (mb, 0);
1397 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, target));
1398 mono_mb_emit_byte (mb, CEE_LDIND_I );
1399 mono_mb_emit_stloc (mb, 0);
1401 /* if target != null */
1402 mono_mb_emit_ldloc (mb, 0);
1403 mono_mb_emit_byte (mb, CEE_BRFALSE);
1405 mono_mb_emit_i4 (mb, 0);
1407 /* then call this->method_ptr nonstatic */
1408 mono_mb_emit_ldloc (mb, 0);
1409 for (i = 0; i < sig->param_count; ++i)
1410 mono_mb_emit_ldarg (mb, i + 1);
1411 mono_mb_emit_ldarg (mb, 0);
1412 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1413 mono_mb_emit_byte (mb, CEE_LDIND_I );
1414 mono_mb_emit_byte (mb, CEE_CALLI);
1415 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
1417 mono_mb_emit_byte (mb, CEE_BR);
1419 mono_mb_emit_i4 (mb, 0);
1421 /* else [target == null] call this->method_ptr static */
1422 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1424 for (i = 0; i < sig->param_count; ++i)
1425 mono_mb_emit_ldarg (mb, i + 1);
1426 mono_mb_emit_ldarg (mb, 0);
1427 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1428 mono_mb_emit_byte (mb, CEE_LDIND_I );
1429 mono_mb_emit_byte (mb, CEE_CALLI);
1430 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, static_sig));
1433 mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
1434 mono_mb_emit_byte (mb, CEE_RET);
1436 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1439 g_hash_table_insert (cache, sig, res);
1445 * generates IL code for the runtime invoke function
1446 * MonoObject *runtime_invoke (MonoObject *this, void **params, MonoObject **exc)
1448 * we also catch exceptions if exc != null
1451 mono_marshal_get_runtime_invoke (MonoMethod *method)
1453 MonoMethodSignature *sig, *csig;
1454 MonoExceptionClause *clause;
1455 MonoMethodHeader *header;
1456 MonoMethodBuilder *mb;
1459 static MonoString *string_dummy = NULL;
1460 int i, pos, sigsize;
1464 cache = method->klass->image->runtime_invoke_cache;
1465 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1468 /* to make it work with our special string constructors */
1470 string_dummy = mono_string_new_wrapper ("dummy");
1472 sig = method->signature;
1474 sigsize = sizeof (MonoMethodSignature) + 3 * sizeof (MonoType *);
1475 csig = g_malloc0 (sigsize);
1477 csig->param_count = 3;
1478 csig->ret = &mono_defaults.object_class->byval_arg;
1479 csig->params [0] = &mono_defaults.object_class->byval_arg;
1480 csig->params [1] = &mono_defaults.int_class->byval_arg;
1481 csig->params [2] = &mono_defaults.int_class->byval_arg;
1483 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_RUNTIME_INVOKE);
1485 /* allocate local 0 (object) tmp */
1486 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1487 /* allocate local 1 (object) exc */
1488 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1490 /* cond set *exc to null */
1491 mono_mb_emit_byte (mb, CEE_LDARG_2);
1492 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
1493 mono_mb_emit_byte (mb, 3);
1494 mono_mb_emit_byte (mb, CEE_LDARG_2);
1495 mono_mb_emit_byte (mb, CEE_LDNULL);
1496 mono_mb_emit_byte (mb, CEE_STIND_I);
1499 if (method->string_ctor) {
1500 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1501 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1502 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, string_dummy));
1504 mono_mb_emit_ldarg (mb, 0);
1505 if (method->klass->valuetype) {
1506 mono_mb_emit_byte (mb, CEE_UNBOX);
1507 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method->klass));
1512 for (i = 0; i < sig->param_count; i++) {
1513 MonoType *t = sig->params [i];
1516 mono_mb_emit_ldarg (mb, 1);
1518 mono_mb_emit_icon (mb, sizeof (gpointer) * i);
1519 mono_mb_emit_byte (mb, CEE_ADD);
1521 mono_mb_emit_byte (mb, CEE_LDIND_I);
1526 type = sig->params [i]->type;
1530 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1532 case MONO_TYPE_BOOLEAN:
1534 mono_mb_emit_byte (mb, CEE_LDIND_U1);
1537 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1540 case MONO_TYPE_CHAR:
1541 mono_mb_emit_byte (mb, CEE_LDIND_U2);
1545 mono_mb_emit_byte (mb, CEE_LDIND_I);
1548 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1551 mono_mb_emit_byte (mb, CEE_LDIND_U4);
1554 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1557 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1561 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1563 case MONO_TYPE_STRING:
1564 case MONO_TYPE_CLASS:
1565 case MONO_TYPE_ARRAY:
1567 case MONO_TYPE_SZARRAY:
1568 case MONO_TYPE_OBJECT:
1571 case MONO_TYPE_VALUETYPE:
1572 if (t->data.klass->enumtype) {
1573 type = t->data.klass->enum_basetype->type;
1576 mono_mb_emit_byte (mb, CEE_LDOBJ);
1577 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, t->data.klass));
1580 g_assert_not_reached ();
1584 if (method->string_ctor) {
1585 MonoMethodSignature *strsig;
1587 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1588 strsig = g_memdup (sig, sigsize);
1589 strsig->ret = &mono_defaults.string_class->byval_arg;
1591 mono_mb_emit_managed_call (mb, method, strsig);
1593 mono_mb_emit_managed_call (mb, method, NULL);
1595 if (sig->ret->byref) {
1597 g_assert_not_reached ();
1601 switch (sig->ret->type) {
1602 case MONO_TYPE_VOID:
1603 if (!method->string_ctor)
1604 mono_mb_emit_byte (mb, CEE_LDNULL);
1606 case MONO_TYPE_BOOLEAN:
1607 case MONO_TYPE_CHAR:
1620 case MONO_TYPE_VALUETYPE:
1621 /* box value types */
1622 mono_mb_emit_byte (mb, CEE_BOX);
1623 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (sig->ret)));
1625 case MONO_TYPE_STRING:
1626 case MONO_TYPE_CLASS:
1627 case MONO_TYPE_ARRAY:
1628 case MONO_TYPE_SZARRAY:
1629 case MONO_TYPE_OBJECT:
1634 g_assert_not_reached ();
1637 mono_mb_emit_stloc (mb, 0);
1639 mono_mb_emit_byte (mb, CEE_LEAVE);
1641 mono_mb_emit_i4 (mb, 0);
1643 clause = g_new0 (MonoExceptionClause, 1);
1644 clause->flags = MONO_EXCEPTION_CLAUSE_FILTER;
1645 clause->try_len = mb->pos;
1648 clause->token_or_filter = mb->pos;
1650 mono_mb_emit_byte (mb, CEE_POP);
1651 mono_mb_emit_byte (mb, CEE_LDARG_2);
1652 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
1653 mono_mb_emit_byte (mb, CEE_PREFIX1);
1654 mono_mb_emit_byte (mb, CEE_CGT_UN);
1655 mono_mb_emit_byte (mb, CEE_PREFIX1);
1656 mono_mb_emit_byte (mb, CEE_ENDFILTER);
1658 clause->handler_offset = mb->pos;
1661 /* store exception */
1662 mono_mb_emit_stloc (mb, 1);
1664 mono_mb_emit_byte (mb, CEE_LDARG_2);
1665 mono_mb_emit_ldloc (mb, 1);
1666 mono_mb_emit_byte (mb, CEE_STIND_I);
1668 mono_mb_emit_byte (mb, CEE_LEAVE);
1669 mono_mb_emit_i4 (mb, 0);
1671 clause->handler_len = mb->pos - clause->handler_offset;
1674 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1675 mono_mb_emit_ldloc (mb, 0);
1676 mono_mb_emit_byte (mb, CEE_RET);
1678 res = mono_mb_create_method (mb, csig, sig->param_count + 16);
1681 header = ((MonoMethodNormal *)res)->header;
1682 header->num_clauses = 1;
1683 header->clauses = clause;
1685 g_hash_table_insert (cache, method, res);
1691 * generates IL code to call managed methods from unmanaged code
1694 mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this)
1696 MonoMethodSignature *sig, *csig;
1697 MonoMethodBuilder *mb;
1701 int i, pos, sigsize, *tmp_locals;
1703 g_assert (method != NULL);
1705 cache = method->klass->image->managed_wrapper_cache;
1706 if (!this && (res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1710 /* fime: howto free that memory ? */
1713 sig = method->signature;
1715 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_NATIVE_TO_MANAGED);
1717 /* allocate local 0 (pointer) src_ptr */
1718 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1719 /* allocate local 1 (pointer) dst_ptr */
1720 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1721 /* allocate local 2 (boolean) delete_old */
1722 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
1724 mono_mb_emit_byte (mb, CEE_LDNULL);
1725 mono_mb_emit_byte (mb, CEE_STLOC_2);
1727 /* we copy the signature, so that we can modify it */
1728 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1729 csig = g_memdup (sig, sigsize);
1733 /* fixme: howto handle this ? */
1737 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1738 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1739 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, this));
1744 g_assert_not_reached ();
1749 /* we first do all conversions */
1750 tmp_locals = alloca (sizeof (int) * sig->param_count);
1751 for (i = 0; i < sig->param_count; i ++) {
1752 MonoType *t = sig->params [i];
1757 case MONO_TYPE_VALUETYPE:
1759 klass = sig->params [i]->data.klass;
1760 if (klass->blittable || klass->enumtype)
1763 tmp_locals [i] = mono_mb_add_local (mb, &klass->byval_arg);
1766 mono_mb_emit_ldarg (mb, i);
1768 mono_mb_emit_ldarg_addr (mb, i);
1769 mono_mb_emit_byte (mb, CEE_STLOC_0);
1772 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1773 mono_mb_emit_byte (mb, CEE_BRFALSE);
1775 mono_mb_emit_i4 (mb, 0);
1778 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
1779 mono_mb_emit_byte (mb, CEE_STLOC_1);
1781 /* emit valuetype convnversion code code */
1782 emit_struct_conv (mb, klass, TRUE);
1785 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1787 case MONO_TYPE_STRING:
1791 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1792 csig->params [i] = &mono_defaults.int_class->byval_arg;
1794 mono_mb_emit_ldarg (mb, i);
1795 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1796 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1797 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
1798 mono_mb_emit_stloc (mb, tmp_locals [i]);
1800 case MONO_TYPE_ARRAY:
1801 case MONO_TYPE_SZARRAY:
1805 klass = mono_class_from_mono_type (t);
1807 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1808 csig->params [i] = &mono_defaults.int_class->byval_arg;
1810 g_warning ("array marshaling not implemented");
1811 g_assert_not_reached ();
1816 for (i = 0; i < sig->param_count; i++) {
1817 MonoType *t = sig->params [i];
1820 case MONO_TYPE_BOOLEAN:
1834 mono_mb_emit_ldarg (mb, i);
1836 case MONO_TYPE_STRING:
1838 mono_mb_emit_ldarg (mb, i);
1840 g_assert (tmp_locals [i]);
1841 mono_mb_emit_ldloc (mb, tmp_locals [i]);
1844 case MONO_TYPE_CLASS:
1845 case MONO_TYPE_ARRAY:
1846 case MONO_TYPE_SZARRAY:
1847 case MONO_TYPE_OBJECT:
1848 /* fixme: conversions ? */
1849 mono_mb_emit_ldarg (mb, i);
1851 case MONO_TYPE_VALUETYPE:
1852 klass = sig->params [i]->data.klass;
1853 if (klass->blittable || klass->enumtype) {
1854 mono_mb_emit_ldarg (mb, i);
1858 g_assert (tmp_locals [i]);
1860 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
1862 mono_mb_emit_ldloc (mb, tmp_locals [i]);
1865 g_warning ("type 0x%02x unknown", t->type);
1866 g_assert_not_reached ();
1870 mono_mb_emit_managed_call (mb, method, NULL);
1872 if (!sig->ret->byref) {
1873 switch (sig->ret->type) {
1874 case MONO_TYPE_VOID:
1875 case MONO_TYPE_BOOLEAN:
1891 case MONO_TYPE_STRING:
1892 csig->ret = &mono_defaults.int_class->byval_arg;
1894 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1895 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1896 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
1898 case MONO_TYPE_VALUETYPE: {
1900 klass = sig->ret->data.klass;
1901 if (klass->blittable || klass->enumtype)
1904 /* load pointer to returned value type */
1905 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1906 mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
1908 /* store the address of the source into local variable 0 */
1909 mono_mb_emit_byte (mb, CEE_STLOC_0);
1910 /* allocate space for the native struct and
1911 * store the address into dst_ptr */
1912 tmp = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1914 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
1915 mono_mb_emit_byte (mb, CEE_PREFIX1);
1916 mono_mb_emit_byte (mb, CEE_LOCALLOC);
1917 mono_mb_emit_byte (mb, CEE_STLOC_1);
1918 mono_mb_emit_byte (mb, CEE_LDLOC_1);
1919 mono_mb_emit_stloc (mb, tmp);
1921 /* emit valuetype conversion code */
1922 emit_struct_conv (mb, klass, FALSE);
1923 mono_mb_emit_ldloc (mb, tmp);
1924 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1925 mono_mb_emit_byte (mb, CEE_MONO_RETOBJ);
1926 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
1930 g_warning ("return type 0x%02x unknown", sig->ret->type);
1931 g_assert_not_reached ();
1935 mono_mb_emit_byte (mb, CEE_RET);
1937 res = mono_mb_create_method (mb, csig, sig->param_count + 16);
1941 g_hash_table_insert (cache, method, res);
1947 * generates IL code for the icall wrapper (the generated method
1948 * calls the unamnaged code in func)
1951 mono_marshal_get_icall_wrapper (MonoMethodSignature *sig, const char *name, gpointer func)
1953 MonoMethodSignature *csig;
1954 MonoMethodBuilder *mb;
1958 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_MANAGED_TO_NATIVE);
1960 mb->method->save_lmf = 1;
1962 /* we copy the signature, so that we can modify it */
1963 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1966 mono_mb_emit_byte (mb, CEE_LDARG_0);
1968 for (i = 0; i < sig->param_count; i++)
1969 mono_mb_emit_ldarg (mb, i + sig->hasthis);
1971 csig = g_memdup (sig, sigsize);
1974 mono_mb_emit_native_call (mb, csig, func);
1976 mono_mb_emit_byte (mb, CEE_RET);
1978 res = mono_mb_create_method (mb, csig, csig->param_count + 16);
1985 * generates IL code for the pinvoke wrapper (the generated method
1986 * calls the unamnage code in method->addr)
1989 mono_marshal_get_native_wrapper (MonoMethod *method)
1991 MonoMethodSignature *sig, *csig;
1992 MonoMethodBuilder *mb;
1993 MonoMarshalSpec **mspecs;
1997 gboolean pinvoke = FALSE;
1998 int i, pos, argnum, *tmp_locals;
2001 g_assert (method != NULL);
2003 cache = method->klass->image->native_wrapper_cache;
2004 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
2007 sig = method->signature;
2009 if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
2010 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2013 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_MANAGED_TO_NATIVE);
2015 mb->method->save_lmf = 1;
2017 if (pinvoke && !method->addr)
2018 mono_lookup_pinvoke_call (method);
2020 if (!method->addr) {
2021 mono_mb_emit_exception (mb);
2022 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
2024 g_hash_table_insert (cache, method, res);
2028 /* we copy the signature, so that we can modify it */
2029 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
2031 /* internal calls: we simply push all arguments and call the method (no conversions) */
2032 if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
2034 MonoMethodSignature *call_sig;
2036 /* hack - string constructors returns a value */
2037 if (method->string_ctor) {
2038 csig = g_memdup (sig, sigsize);
2039 csig->ret = &mono_defaults.string_class->byval_arg;
2044 mono_mb_emit_byte (mb, CEE_LDARG_0);
2046 for (i = 0; i < sig->param_count; i++)
2047 mono_mb_emit_ldarg (mb, i + sig->hasthis);
2049 call_sig = g_memdup (csig, sigsize);
2050 call_sig->pinvoke = 1;
2052 g_assert (method->addr);
2053 mono_mb_emit_native_call (mb, call_sig, method->addr);
2055 mono_mb_emit_byte (mb, CEE_RET);
2057 res = mono_mb_create_method (mb, csig, sig->param_count + 16);
2059 g_hash_table_insert (cache, method, res);
2065 mspecs = g_new (MonoMarshalSpec, sig->param_count + 1);
2066 mono_method_get_marshal_info (method, mspecs);
2068 /* pinvoke: we need to convert the arguments if necessary */
2070 csig = g_memdup (sig, sigsize);
2073 /* we allocate local for use with emit_struct_conv() */
2074 /* allocate local 0 (pointer) src_ptr */
2075 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2076 /* allocate local 1 (pointer) dst_ptr */
2077 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2078 /* allocate local 2 (boolean) delete_old */
2079 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2081 /* delete_old = FALSE */
2082 mono_mb_emit_icon (mb, 0);
2083 mono_mb_emit_byte (mb, CEE_STLOC_2);
2085 if (sig->ret->type != MONO_TYPE_VOID) {
2086 /* allocate local 3 to store the return value */
2087 mono_mb_add_local (mb, sig->ret);
2090 /* we first do all conversions */
2091 tmp_locals = alloca (sizeof (int) * sig->param_count);
2092 for (i = 0; i < sig->param_count; i ++) {
2093 MonoType *t = sig->params [i];
2094 MonoMarshalSpec *spec = mspecs [i + 1];
2096 argnum = i + sig->hasthis;
2100 case MONO_TYPE_VALUETYPE:
2101 klass = t->data.klass;
2102 if (klass->blittable || klass->enumtype)
2105 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2107 /* store the address of the source into local variable 0 */
2109 mono_mb_emit_ldarg (mb, argnum);
2111 mono_mb_emit_ldarg_addr (mb, argnum);
2113 mono_mb_emit_byte (mb, CEE_STLOC_0);
2116 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2117 mono_mb_emit_byte (mb, CEE_BRFALSE);
2119 mono_mb_emit_i4 (mb, 0);
2122 /* allocate space for the native struct and
2123 * store the address into local variable 1 (dest) */
2124 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2125 mono_mb_emit_byte (mb, CEE_PREFIX1);
2126 mono_mb_emit_byte (mb, CEE_LOCALLOC);
2127 mono_mb_emit_stloc (mb, tmp_locals [i]);
2129 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2130 mono_mb_emit_byte (mb, CEE_STLOC_1);
2132 /* emit valuetype conversion code */
2133 emit_struct_conv (mb, klass, FALSE);
2136 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2138 case MONO_TYPE_STRING:
2142 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2143 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2145 mono_mb_emit_ldarg (mb, argnum);
2146 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2147 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2150 switch (spec->native) {
2151 case MONO_NATIVE_LPWSTR:
2152 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPWSTR);
2155 g_warning ("marshalling conversion not implemented");
2156 g_assert_not_reached ();
2159 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
2162 mono_mb_emit_stloc (mb, tmp_locals [i]);
2164 case MONO_TYPE_CLASS:
2165 case MONO_TYPE_OBJECT:
2169 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2170 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2172 if (t->data.klass->delegate) {
2173 mono_mb_emit_ldarg (mb, argnum);
2174 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2175 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2176 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_DEL_FTN);
2177 mono_mb_emit_stloc (mb, tmp_locals [i]);
2178 } else if (t->data.klass == mono_defaults.stringbuilder_class) {
2179 mono_mb_emit_ldarg (mb, argnum);
2180 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2181 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2182 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_SB_LPSTR);
2183 mono_mb_emit_stloc (mb, tmp_locals [i]);
2185 mono_mb_emit_ldarg (mb, argnum);
2186 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2187 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2188 /* fixme: convert to what ? */
2189 mono_mb_emit_stloc (mb, tmp_locals [i]);
2193 case MONO_TYPE_ARRAY:
2194 case MONO_TYPE_SZARRAY:
2198 klass = mono_class_from_mono_type (t);
2200 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2201 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2203 mono_mb_emit_ldarg (mb, argnum);
2204 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2205 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2206 if (klass->element_class == mono_defaults.string_class)
2207 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STRARRAY_STRLPARRAY);
2209 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_ARRAY_LPARRAY);
2210 mono_mb_emit_stloc (mb, tmp_locals [i]);
2215 /* push all arguments */
2218 mono_mb_emit_byte (mb, CEE_LDARG_0);
2220 for (i = 0; i < sig->param_count; i++) {
2221 MonoType *t = sig->params [i];
2223 argnum = i + sig->hasthis;
2226 case MONO_TYPE_BOOLEAN:
2228 g_warning ("byref boolean marshalling not inplemented");
2229 mono_mb_emit_ldarg (mb, argnum);
2244 mono_mb_emit_ldarg (mb, argnum);
2246 case MONO_TYPE_VALUETYPE:
2247 klass = sig->params [i]->data.klass;
2248 if (klass->blittable || klass->enumtype) {
2249 mono_mb_emit_ldarg (mb, argnum);
2252 g_assert (tmp_locals [i]);
2253 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2255 mono_mb_emit_byte (mb, CEE_LDOBJ);
2256 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2259 case MONO_TYPE_STRING:
2261 mono_mb_emit_ldarg (mb, argnum);
2263 g_assert (tmp_locals [i]);
2264 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2267 case MONO_TYPE_CLASS:
2268 case MONO_TYPE_OBJECT:
2270 mono_mb_emit_ldarg (mb, argnum);
2272 g_assert (tmp_locals [i]);
2273 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2276 case MONO_TYPE_CHAR:
2277 /* fixme: dont know how to marshal that. We cant simply
2278 * convert it to a one byte UTF8 character, because an
2279 * unicode character may need more that one byte in UTF8 */
2280 mono_mb_emit_ldarg (mb, argnum);
2282 case MONO_TYPE_ARRAY:
2283 case MONO_TYPE_SZARRAY:
2285 mono_mb_emit_ldarg (mb, argnum);
2287 g_assert (tmp_locals [i]);
2288 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2291 case MONO_TYPE_TYPEDBYREF:
2292 case MONO_TYPE_FNPTR:
2294 g_warning ("type 0x%02x unknown", t->type);
2295 g_assert_not_reached ();
2299 /* call the native method */
2300 mono_mb_emit_native_call (mb, csig, method->addr);
2302 /* return the result */
2304 /* we need to convert byref arguments back and free string arrays */
2305 for (i = 0; i < sig->param_count; i++) {
2306 MonoType *t = sig->params [i];
2308 argnum = i + sig->hasthis;
2311 case MONO_TYPE_CLASS:
2312 case MONO_TYPE_OBJECT:
2316 if (t->data.klass == mono_defaults.stringbuilder_class) {
2317 mono_mb_emit_ldarg (mb, argnum);
2318 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2319 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2320 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
2321 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_SB);
2322 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2323 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2324 mono_mb_emit_byte (mb, CEE_MONO_FREE);
2327 case MONO_TYPE_VALUETYPE:
2331 klass = t->data.klass;
2332 if (klass->blittable || klass->enumtype)
2335 /* dst = argument */
2336 mono_mb_emit_ldarg (mb, argnum);
2337 mono_mb_emit_byte (mb, CEE_STLOC_1);
2339 mono_mb_emit_byte (mb, CEE_LDLOC_1);
2340 mono_mb_emit_byte (mb, CEE_BRFALSE);
2342 mono_mb_emit_i4 (mb, 0);
2344 /* src = tmp_locals [i] */
2345 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2346 mono_mb_emit_byte (mb, CEE_STLOC_0);
2348 /* emit valuetype conversion code */
2349 emit_struct_conv (mb, klass, TRUE);
2351 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2353 case MONO_TYPE_SZARRAY:
2357 klass = mono_class_from_mono_type (t);
2359 if (klass->element_class == mono_defaults.string_class) {
2360 g_assert (tmp_locals [i]);
2361 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2362 mono_mb_emit_ldarg (mb, argnum);
2363 mono_mb_emit_byte (mb, CEE_LDLEN);
2364 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2365 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
2366 mono_mb_emit_byte (mb, MONO_MARSHAL_FREE_ARRAY);
2373 if (!sig->ret->byref) {
2374 MonoMarshalSpec *spec = mspecs [0];
2375 type = sig->ret->type;
2379 case MONO_TYPE_VOID:
2393 /* no conversions necessary */
2395 case MONO_TYPE_BOOLEAN:
2396 /* maybe we need to make sure that it fits within 8 bits */
2398 case MONO_TYPE_VALUETYPE: {
2401 klass = sig->ret->data.klass;
2402 if (klass->enumtype) {
2403 type = sig->ret->data.klass->enum_basetype->type;
2407 if (klass->blittable)
2410 tmp = mono_mb_add_local (mb, sig->ret);
2412 /* load pointer to returned value type */
2413 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2414 mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
2415 /* store the address of the source into local variable 0 */
2416 mono_mb_emit_byte (mb, CEE_STLOC_0);
2418 mono_mb_emit_ldloc_addr (mb, tmp);
2419 mono_mb_emit_byte (mb, CEE_STLOC_1);
2421 /* emit valuetype conversion code */
2422 emit_struct_conv (mb, sig->ret->data.klass, TRUE);
2424 mono_mb_emit_ldloc (mb, tmp);
2427 case MONO_TYPE_STRING:
2428 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2429 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2431 switch (spec->native) {
2432 case MONO_NATIVE_LPWSTR:
2433 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPWSTR_STR);
2436 g_warning ("marshalling conversion not implemented");
2437 g_assert_not_reached ();
2440 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
2443 case MONO_TYPE_ARRAY:
2444 case MONO_TYPE_SZARRAY:
2445 case MONO_TYPE_CLASS:
2446 case MONO_TYPE_OBJECT:
2447 /* fixme: we need conversions here */
2449 case MONO_TYPE_CHAR:
2450 /* fixme: we need conversions here */
2452 case MONO_TYPE_TYPEDBYREF:
2453 case MONO_TYPE_FNPTR:
2455 g_warning ("return type 0x%02x unknown", sig->ret->type);
2456 g_assert_not_reached ();
2460 mono_mb_emit_byte (mb, CEE_RET);
2462 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
2465 g_hash_table_insert (cache, method, res);
2467 for (i = sig->param_count; i >= 0; i--)
2468 g_free (mspecs [i]);
2475 * generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld)
2478 mono_marshal_get_struct_to_ptr (MonoClass *klass)
2480 MonoMethodBuilder *mb;
2481 static MonoMethod *stoptr = NULL;
2484 g_assert (klass != NULL);
2486 if (klass->str_to_ptr)
2487 return klass->str_to_ptr;
2490 stoptr = mono_find_method_by_name (mono_defaults.marshal_class, "StructureToPtr", 3);
2493 mb = mono_mb_new (klass, stoptr->name, MONO_WRAPPER_UNKNOWN);
2495 if (klass->blittable) {
2496 mono_mb_emit_byte (mb, CEE_LDARG_1);
2497 mono_mb_emit_byte (mb, CEE_LDARG_0);
2498 mono_mb_emit_icon (mb, sizeof (MonoObject));
2499 mono_mb_emit_byte (mb, CEE_ADD);
2500 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
2501 mono_mb_emit_byte (mb, CEE_PREFIX1);
2502 mono_mb_emit_byte (mb, CEE_CPBLK);
2505 /* allocate local 0 (pointer) src_ptr */
2506 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2507 /* allocate local 1 (pointer) dst_ptr */
2508 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2509 /* allocate local 2 (boolean) delete_old */
2510 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2511 mono_mb_emit_byte (mb, CEE_LDARG_2);
2512 mono_mb_emit_byte (mb, CEE_STLOC_2);
2514 /* initialize src_ptr to point to the start of object data */
2515 mono_mb_emit_byte (mb, CEE_LDARG_0);
2516 mono_mb_emit_icon (mb, sizeof (MonoObject));
2517 mono_mb_emit_byte (mb, CEE_ADD);
2518 mono_mb_emit_byte (mb, CEE_STLOC_0);
2520 /* initialize dst_ptr */
2521 mono_mb_emit_byte (mb, CEE_LDARG_1);
2522 mono_mb_emit_byte (mb, CEE_STLOC_1);
2524 emit_struct_conv (mb, klass, FALSE);
2527 mono_mb_emit_byte (mb, CEE_RET);
2529 res = mono_mb_create_method (mb, stoptr->signature, 0);
2532 klass->str_to_ptr = res;
2537 * generates IL code for PtrToStructure (IntPtr src, object structure)
2540 mono_marshal_get_ptr_to_struct (MonoClass *klass)
2542 MonoMethodBuilder *mb;
2543 static MonoMethod *ptostr = NULL;
2546 g_assert (klass != NULL);
2548 if (klass->ptr_to_str)
2549 return klass->ptr_to_str;
2552 ptostr = mono_find_method_by_name (mono_defaults.marshal_class, "PtrToStructure", 2);
2555 mb = mono_mb_new (klass, ptostr->name, MONO_WRAPPER_UNKNOWN);
2557 if (klass->blittable) {
2558 mono_mb_emit_byte (mb, CEE_LDARG_1);
2559 mono_mb_emit_icon (mb, sizeof (MonoObject));
2560 mono_mb_emit_byte (mb, CEE_ADD);
2561 mono_mb_emit_byte (mb, CEE_LDARG_0);
2562 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
2563 mono_mb_emit_byte (mb, CEE_PREFIX1);
2564 mono_mb_emit_byte (mb, CEE_CPBLK);
2567 /* allocate local 0 (pointer) src_ptr */
2568 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2569 /* allocate local 1 (pointer) dst_ptr */
2570 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2572 /* initialize src_ptr to point to the start of object data */
2573 mono_mb_emit_byte (mb, CEE_LDARG_0);
2574 mono_mb_emit_byte (mb, CEE_STLOC_0);
2576 /* initialize dst_ptr */
2577 mono_mb_emit_byte (mb, CEE_LDARG_1);
2578 mono_mb_emit_icon (mb, sizeof (MonoObject));
2579 mono_mb_emit_byte (mb, CEE_ADD);
2580 mono_mb_emit_byte (mb, CEE_STLOC_1);
2582 emit_struct_conv (mb, klass, TRUE);
2585 mono_mb_emit_byte (mb, CEE_RET);
2587 res = mono_mb_create_method (mb, ptostr->signature, 0);
2590 klass->ptr_to_str = res;
2594 /* FIXME: on win32 we should probably use GlobalAlloc(). */
2596 mono_marshal_alloc (gpointer size)
2598 MONO_ARCH_SAVE_REGS;
2600 return g_try_malloc ((gulong)size);
2604 mono_marshal_free (gpointer ptr)
2606 MONO_ARCH_SAVE_REGS;
2612 mono_marshal_free_array (gpointer *ptr, int size) {
2615 for (i = 0; i < size; i++)
2621 mono_marshal_realloc (gpointer ptr, gpointer size)
2623 MONO_ARCH_SAVE_REGS;
2625 return g_try_realloc (ptr, (gulong)size);
2629 mono_marshal_string_array (MonoArray *array)
2637 len = mono_array_length (array);
2639 result = g_malloc (sizeof (char *) * (len + 1));
2640 for (i = 0; i < len; ++i) {
2641 MonoString *s = (MonoString *)mono_array_get (array, gpointer, i);
2642 result [i] = s ? mono_string_to_utf8 (s): NULL;
2644 /* null terminate the array */
2651 ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArray *src, gint32 start_index,
2652 gpointer dest, gint32 length)
2657 MONO_ARCH_SAVE_REGS;
2659 MONO_CHECK_ARG_NULL (src);
2660 MONO_CHECK_ARG_NULL (dest);
2662 g_assert (src->obj.vtable->klass->rank == 1);
2663 g_assert (start_index >= 0 && start_index < mono_array_length (src));
2664 g_assert (start_index + length <= mono_array_length (src));
2666 element_size = mono_array_element_size (src->obj.vtable->klass);
2668 source_addr = mono_array_addr_with_size (src, element_size, start_index);
2670 memcpy (dest, source_addr, length * element_size);
2674 ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer src, gint32 start_index,
2675 MonoArray *dest, gint32 length)
2680 MONO_ARCH_SAVE_REGS;
2682 MONO_CHECK_ARG_NULL (src);
2683 MONO_CHECK_ARG_NULL (dest);
2685 g_assert (dest->obj.vtable->klass->rank == 1);
2686 g_assert (start_index >= 0 && start_index < mono_array_length (dest));
2687 g_assert (start_index + length <= mono_array_length (dest));
2689 element_size = mono_array_element_size (dest->obj.vtable->klass);
2691 dest_addr = mono_array_addr_with_size (dest, element_size, start_index);
2693 memcpy (dest_addr, src, length * element_size);
2697 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr, gint32 offset)
2701 MONO_ARCH_SAVE_REGS;
2703 return *(gpointer*)(p + offset);
2707 ves_icall_System_Runtime_InteropServices_Marshal_ReadByte (gpointer ptr, gint32 offset)
2711 MONO_ARCH_SAVE_REGS;
2713 return *(unsigned char*)(p + offset);
2717 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt16 (gpointer ptr, gint32 offset)
2721 MONO_ARCH_SAVE_REGS;
2723 return *(gint16*)(p + offset);
2727 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt32 (gpointer ptr, gint32 offset)
2731 MONO_ARCH_SAVE_REGS;
2733 return *(gint32*)(p + offset);
2737 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt64 (gpointer ptr, gint32 offset)
2741 MONO_ARCH_SAVE_REGS;
2743 return *(gint64*)(p + offset);
2747 ves_icall_System_Runtime_InteropServices_Marshal_WriteByte (gpointer ptr, gint32 offset, unsigned char val)
2751 MONO_ARCH_SAVE_REGS;
2753 *(unsigned char*)(p + offset) = val;
2757 ves_icall_System_Runtime_InteropServices_Marshal_WriteIntPtr (gpointer ptr, gint32 offset, gpointer val)
2761 MONO_ARCH_SAVE_REGS;
2763 *(gpointer*)(p + offset) = val;
2767 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt16 (gpointer ptr, gint32 offset, gint16 val)
2771 MONO_ARCH_SAVE_REGS;
2773 *(gint16*)(p + offset) = val;
2777 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt32 (gpointer ptr, gint32 offset, gint32 val)
2781 MONO_ARCH_SAVE_REGS;
2783 *(gint32*)(p + offset) = val;
2787 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt64 (gpointer ptr, gint32 offset, gint64 val)
2791 MONO_ARCH_SAVE_REGS;
2793 *(gint64*)(p + offset) = val;
2797 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (char *ptr)
2799 MONO_ARCH_SAVE_REGS;
2801 return mono_string_new (mono_domain_get (), ptr);
2805 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len (char *ptr, gint32 len)
2807 MONO_ARCH_SAVE_REGS;
2809 return mono_string_new_len (mono_domain_get (), ptr, len);
2813 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni (guint16 *ptr)
2815 MonoDomain *domain = mono_domain_get ();
2819 MONO_ARCH_SAVE_REGS;
2824 return mono_string_new_utf16 (domain, ptr, len);
2828 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len (guint16 *ptr, gint32 len)
2830 MonoDomain *domain = mono_domain_get ();
2832 MONO_ARCH_SAVE_REGS;
2834 return mono_string_new_utf16 (domain, ptr, len);
2838 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR (gpointer ptr)
2840 MONO_ARCH_SAVE_REGS;
2842 g_warning ("PtrToStringBSTR not implemented");
2843 g_assert_not_reached ();
2849 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
2851 MONO_ARCH_SAVE_REGS;
2853 return (GetLastError ());
2857 ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype)
2861 MONO_ARCH_SAVE_REGS;
2863 MONO_CHECK_ARG_NULL (rtype);
2865 klass = mono_class_from_mono_type (rtype->type);
2867 return mono_class_native_size (klass, NULL);
2871 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old)
2876 MONO_ARCH_SAVE_REGS;
2878 MONO_CHECK_ARG_NULL (obj);
2879 MONO_CHECK_ARG_NULL (dst);
2881 method = mono_marshal_get_struct_to_ptr (obj->vtable->klass);
2885 pa [2] = &delete_old;
2887 mono_runtime_invoke (method, NULL, pa, NULL);
2891 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, MonoObject *dst)
2896 MONO_ARCH_SAVE_REGS;
2898 MONO_CHECK_ARG_NULL (src);
2899 MONO_CHECK_ARG_NULL (dst);
2901 method = mono_marshal_get_ptr_to_struct (dst->vtable->klass);
2906 mono_runtime_invoke (method, NULL, pa, NULL);
2910 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer src, MonoReflectionType *type)
2912 MonoDomain *domain = mono_domain_get ();
2915 MONO_ARCH_SAVE_REGS;
2917 MONO_CHECK_ARG_NULL (src);
2918 MONO_CHECK_ARG_NULL (type);
2920 res = mono_object_new (domain, mono_class_from_mono_type (type->type));
2922 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (src, res);
2928 ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *type, MonoString *field_name)
2930 MonoMarshalType *info;
2935 MONO_ARCH_SAVE_REGS;
2937 MONO_CHECK_ARG_NULL (type);
2938 MONO_CHECK_ARG_NULL (field_name);
2940 fname = mono_string_to_utf8 (field_name);
2941 klass = mono_class_from_mono_type (type->type);
2943 info = mono_marshal_load_type_info (klass);
2945 for (i = 0; i < klass->field.count; ++i) {
2946 if (*fname == *klass->fields [i].name &&
2947 strcmp (fname, klass->fields [i].name) == 0)
2952 mono_assert (i < klass->field.count);
2954 return info->fields [i].offset;
2958 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString *string)
2960 MONO_ARCH_SAVE_REGS;
2962 return mono_string_to_utf8 (string);
2966 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni (MonoString *string)
2968 MONO_ARCH_SAVE_REGS;
2970 return g_memdup (mono_string_chars (string), mono_string_length (string)*2);
2974 mono_struct_delete_old (MonoClass *klass, char *ptr)
2976 MonoMarshalType *info;
2979 info = mono_marshal_load_type_info (klass);
2981 for (i = 0; i < info->num_fields; i++) {
2982 MonoMarshalNative ntype;
2983 MonoMarshalConv conv;
2984 MonoType *ftype = info->fields [i].field->type;
2987 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
2990 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE,
2991 klass->unicode, &conv);
2993 cpos = ptr + info->fields [i].offset;
2996 case MONO_MARSHAL_CONV_NONE:
2997 if (MONO_TYPE_ISSTRUCT (ftype)) {
2998 mono_struct_delete_old (ftype->data.klass, cpos);
3002 case MONO_MARSHAL_CONV_STR_LPWSTR:
3003 case MONO_MARSHAL_CONV_STR_LPSTR:
3004 case MONO_MARSHAL_CONV_STR_LPTSTR:
3005 case MONO_MARSHAL_CONV_STR_BSTR:
3006 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
3007 case MONO_MARSHAL_CONV_STR_TBSTR:
3008 g_free (*(gpointer *)cpos);
3017 ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure (gpointer src, MonoReflectionType *type)
3021 MONO_ARCH_SAVE_REGS;
3023 MONO_CHECK_ARG_NULL (src);
3024 MONO_CHECK_ARG_NULL (type);
3026 klass = mono_class_from_mono_type (type->type);
3028 mono_struct_delete_old (klass, (char *)src);