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 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 mono_mb_emit_byte (mb, CEE_LDNULL);
489 mono_mb_emit_byte (mb, CEE_THROW);
494 mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint8 local, gint8 incr)
496 mono_mb_emit_ldloc (mb, local);
497 mono_mb_emit_icon (mb, incr);
498 mono_mb_emit_byte (mb, CEE_ADD);
499 mono_mb_emit_stloc (mb, local);
503 emit_ptr_to_str_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv,
504 int usize, int msize)
507 case MONO_MARSHAL_CONV_BOOL_I4:
508 mono_mb_emit_byte (mb, CEE_LDLOC_0);
509 mono_mb_emit_byte (mb, CEE_LDIND_I);
510 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
511 mono_mb_emit_byte (mb, 5);
512 mono_mb_emit_byte (mb, CEE_LDLOC_1);
513 mono_mb_emit_byte (mb, CEE_LDC_I4_1);
514 mono_mb_emit_byte (mb, CEE_STIND_I1);
515 mono_mb_emit_byte (mb, CEE_BR_S);
516 mono_mb_emit_byte (mb, 3);
517 mono_mb_emit_byte (mb, CEE_LDLOC_1);
518 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
519 mono_mb_emit_byte (mb, CEE_STIND_I1);
521 case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
525 if (type->type == MONO_TYPE_ARRAY)
526 eclass = mono_class_from_mono_type (type->data.array->type);
527 else if (type->type == MONO_TYPE_SZARRAY) {
528 eclass = mono_class_from_mono_type (type->data.type);
530 g_assert_not_reached ();
533 if (eclass->valuetype)
534 esize = mono_class_instance_size (eclass) - sizeof (MonoObject);
536 esize = sizeof (gpointer);
538 /* create a new array */
539 /* fixme: this only works for SZARRAYS */
540 mono_mb_emit_byte (mb, CEE_LDLOC_1);
541 mono_mb_emit_icon (mb, msize / esize);
542 mono_mb_emit_byte (mb, CEE_NEWARR);
543 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eclass));
544 mono_mb_emit_byte (mb, CEE_STIND_I);
546 /* copy the elements */
547 mono_mb_emit_byte (mb, CEE_LDLOC_1);
548 mono_mb_emit_byte (mb, CEE_LDIND_I);
549 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
550 mono_mb_emit_byte (mb, CEE_ADD);
551 mono_mb_emit_byte (mb, CEE_LDLOC_0);
552 mono_mb_emit_icon (mb, usize);
553 mono_mb_emit_byte (mb, CEE_PREFIX1);
554 mono_mb_emit_byte (mb, CEE_CPBLK);
558 case MONO_MARSHAL_CONV_STR_BYVALSTR:
559 mono_mb_emit_byte (mb, CEE_LDLOC_1);
560 mono_mb_emit_byte (mb, CEE_LDLOC_0);
561 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
562 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
563 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
564 mono_mb_emit_byte (mb, CEE_STIND_I);
566 case MONO_MARSHAL_CONV_STR_LPTSTR:
567 case MONO_MARSHAL_CONV_STR_LPSTR:
568 mono_mb_emit_byte (mb, CEE_LDLOC_1);
569 mono_mb_emit_byte (mb, CEE_LDLOC_0);
570 mono_mb_emit_byte (mb, CEE_LDIND_I);
571 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
572 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
573 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
574 mono_mb_emit_byte (mb, CEE_STIND_I);
576 case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
577 MonoClass *klass = mono_class_from_mono_type (type);
578 int src_var, dst_var;
580 src_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
581 dst_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
583 /* *dst = new object */
584 mono_mb_emit_byte (mb, CEE_LDLOC_1);
585 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
586 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
587 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
588 mono_mb_emit_byte (mb, CEE_STIND_I);
590 /* save the old src pointer */
591 mono_mb_emit_byte (mb, CEE_LDLOC_0);
592 mono_mb_emit_stloc (mb, src_var);
593 /* save the old dst pointer */
594 mono_mb_emit_byte (mb, CEE_LDLOC_1);
595 mono_mb_emit_stloc (mb, dst_var);
597 /* dst = pointer to newly created object data */
598 mono_mb_emit_byte (mb, CEE_LDLOC_1);
599 mono_mb_emit_byte (mb, CEE_LDIND_I);
600 mono_mb_emit_icon (mb, sizeof (MonoObject));
601 mono_mb_emit_byte (mb, CEE_ADD);
602 mono_mb_emit_byte (mb, CEE_STLOC_1);
604 emit_struct_conv (mb, klass, TRUE);
606 /* restore the old src pointer */
607 mono_mb_emit_ldloc (mb, src_var);
608 mono_mb_emit_byte (mb, CEE_STLOC_0);
609 /* restore the old dst pointer */
610 mono_mb_emit_ldloc (mb, dst_var);
611 mono_mb_emit_byte (mb, CEE_STLOC_1);
614 case MONO_MARSHAL_CONV_STR_LPWSTR:
615 case MONO_MARSHAL_CONV_STR_BSTR:
616 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
617 case MONO_MARSHAL_CONV_STR_TBSTR:
618 case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
619 case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
620 case MONO_MARSHAL_CONV_STR_BYVALWSTR:
621 case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
623 g_warning ("marshaling conversion %d not implemented", conv);
624 g_assert_not_reached ();
629 emit_str_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, int usize, int msize)
634 case MONO_MARSHAL_CONV_BOOL_I4:
635 mono_mb_emit_byte (mb, CEE_LDLOC_1);
636 mono_mb_emit_byte (mb, CEE_LDLOC_0);
637 mono_mb_emit_byte (mb, CEE_LDIND_U1);
638 mono_mb_emit_byte (mb, CEE_STIND_I4);
640 case MONO_MARSHAL_CONV_STR_LPWSTR:
641 case MONO_MARSHAL_CONV_STR_LPSTR:
642 case MONO_MARSHAL_CONV_STR_LPTSTR:
643 case MONO_MARSHAL_CONV_STR_BSTR:
644 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
645 case MONO_MARSHAL_CONV_STR_TBSTR:
646 /* free space if free == true */
647 mono_mb_emit_byte (mb, CEE_LDLOC_2);
648 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
649 mono_mb_emit_byte (mb, 4);
650 mono_mb_emit_byte (mb, CEE_LDLOC_1);
651 mono_mb_emit_byte (mb, CEE_LDIND_I);
652 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
653 mono_mb_emit_byte (mb, CEE_MONO_FREE);
655 mono_mb_emit_byte (mb, CEE_LDLOC_1);
656 mono_mb_emit_byte (mb, CEE_LDLOC_0);
657 mono_mb_emit_byte (mb, CEE_LDIND_I);
658 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
659 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
660 mono_mb_emit_byte (mb, conv);
661 mono_mb_emit_byte (mb, CEE_STIND_I);
663 case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
664 case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
665 case MONO_MARSHAL_CONV_DEL_FTN:
666 mono_mb_emit_byte (mb, CEE_LDLOC_1);
667 mono_mb_emit_byte (mb, CEE_LDLOC_0);
668 mono_mb_emit_byte (mb, CEE_LDIND_I);
669 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
670 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
671 mono_mb_emit_byte (mb, conv);
672 mono_mb_emit_byte (mb, CEE_STIND_I);
674 case MONO_MARSHAL_CONV_STR_BYVALSTR:
675 case MONO_MARSHAL_CONV_STR_BYVALWSTR: {
679 mono_mb_emit_byte (mb, CEE_LDLOC_1); /* dst */
680 mono_mb_emit_byte (mb, CEE_LDLOC_0);
681 mono_mb_emit_byte (mb, CEE_LDIND_I); /* src String */
682 mono_mb_emit_icon (mb, usize);
683 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
684 mono_mb_emit_byte (mb, CEE_MONO_PROC3);
685 mono_mb_emit_byte (mb, conv);
688 case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
692 mono_mb_emit_byte (mb, CEE_LDLOC_0);
693 mono_mb_emit_byte (mb, CEE_LDIND_I);
694 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
696 mono_mb_emit_byte (mb, 0);
698 mono_mb_emit_byte (mb, CEE_LDLOC_1);
699 mono_mb_emit_byte (mb, CEE_LDLOC_0);
700 mono_mb_emit_byte (mb, CEE_LDIND_I);
701 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
702 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
703 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
704 mono_mb_emit_byte (mb, CEE_ADD);
705 mono_mb_emit_icon (mb, usize);
706 mono_mb_emit_byte (mb, CEE_PREFIX1);
707 mono_mb_emit_byte (mb, CEE_CPBLK);
708 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
711 case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
712 int src_var, dst_var;
714 src_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
715 dst_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
717 mono_mb_emit_byte (mb, CEE_LDLOC_0);
718 mono_mb_emit_byte (mb, CEE_LDIND_I);
719 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
721 mono_mb_emit_byte (mb, 0);
723 /* save the old src pointer */
724 mono_mb_emit_byte (mb, CEE_LDLOC_0);
725 mono_mb_emit_stloc (mb, src_var);
726 /* save the old dst pointer */
727 mono_mb_emit_byte (mb, CEE_LDLOC_1);
728 mono_mb_emit_stloc (mb, dst_var);
730 /* src = pointer to object data */
731 mono_mb_emit_byte (mb, CEE_LDLOC_0);
732 mono_mb_emit_byte (mb, CEE_LDIND_I);
733 mono_mb_emit_icon (mb, sizeof (MonoObject));
734 mono_mb_emit_byte (mb, CEE_ADD);
735 mono_mb_emit_byte (mb, CEE_STLOC_0);
737 emit_struct_conv (mb, mono_class_from_mono_type (type), FALSE);
739 /* restore the old src pointer */
740 mono_mb_emit_ldloc (mb, src_var);
741 mono_mb_emit_byte (mb, CEE_STLOC_0);
742 /* restore the old dst pointer */
743 mono_mb_emit_ldloc (mb, dst_var);
744 mono_mb_emit_byte (mb, CEE_STLOC_1);
746 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
749 case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
751 g_warning ("marshalling conversion %d not implemented", conv);
752 g_assert_not_reached ();
757 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
759 MonoMarshalType *info;
762 info = mono_marshal_load_type_info (klass);
764 for (i = 0; i < info->num_fields; i++) {
765 MonoMarshalNative ntype;
766 MonoMarshalConv conv;
767 MonoType *ftype = info->fields [i].field->type;
770 gboolean last_field = i < (info->num_fields -1) ? 0 : 1;
772 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
775 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, klass->unicode, &conv);
778 msize = klass->instance_size - info->fields [i].field->offset;
779 usize = info->native_size - info->fields [i].offset;
781 msize = klass->fields [i + 1].offset - info->fields [i].field->offset;
782 usize = info->fields [i + 1].offset - info->fields [i].offset;
784 g_assert (msize > 0 && usize > 0);
787 case MONO_MARSHAL_CONV_NONE: {
790 if (ftype->byref || ftype->type == MONO_TYPE_I ||
791 ftype->type == MONO_TYPE_U) {
792 mono_mb_emit_byte (mb, CEE_LDLOC_1);
793 mono_mb_emit_byte (mb, CEE_LDLOC_0);
794 mono_mb_emit_byte (mb, CEE_LDIND_I);
795 mono_mb_emit_byte (mb, CEE_STIND_I);
804 mono_mb_emit_byte (mb, CEE_LDLOC_1);
805 mono_mb_emit_byte (mb, CEE_LDLOC_0);
806 mono_mb_emit_byte (mb, CEE_LDIND_I4);
807 mono_mb_emit_byte (mb, CEE_STIND_I4);
811 case MONO_TYPE_BOOLEAN:
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_I1);
815 mono_mb_emit_byte (mb, CEE_STIND_I1);
819 mono_mb_emit_byte (mb, CEE_LDLOC_1);
820 mono_mb_emit_byte (mb, CEE_LDLOC_0);
821 mono_mb_emit_byte (mb, CEE_LDIND_I2);
822 mono_mb_emit_byte (mb, CEE_STIND_I2);
826 mono_mb_emit_byte (mb, CEE_LDLOC_1);
827 mono_mb_emit_byte (mb, CEE_LDLOC_0);
828 mono_mb_emit_byte (mb, CEE_LDIND_I8);
829 mono_mb_emit_byte (mb, CEE_STIND_I8);
832 mono_mb_emit_byte (mb, CEE_LDLOC_1);
833 mono_mb_emit_byte (mb, CEE_LDLOC_0);
834 mono_mb_emit_byte (mb, CEE_LDIND_R4);
835 mono_mb_emit_byte (mb, CEE_STIND_R4);
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_R8);
841 mono_mb_emit_byte (mb, CEE_STIND_R8);
843 case MONO_TYPE_VALUETYPE:
844 if (ftype->data.klass->enumtype) {
845 t = ftype->data.klass->enum_basetype->type;
848 emit_struct_conv (mb, ftype->data.klass, to_object);
851 g_warning ("marshaling type %02x not implemented", ftype->type);
852 g_assert_not_reached ();
858 emit_ptr_to_str_conv (mb, ftype, conv, usize, msize);
860 emit_str_to_ptr_conv (mb, ftype, conv, usize, msize);
864 mono_mb_emit_add_to_local (mb, 0, usize);
865 mono_mb_emit_add_to_local (mb, 1, msize);
867 mono_mb_emit_add_to_local (mb, 0, msize);
868 mono_mb_emit_add_to_local (mb, 1, usize);
873 static MonoAsyncResult *
874 mono_delegate_begin_invoke (MonoDelegate *delegate, gpointer *params)
876 MonoMethodMessage *msg;
877 MonoDelegate *async_callback;
881 MonoMethod *method = NULL;
886 klass = delegate->object.vtable->klass;
888 method = mono_get_delegate_invoke (klass);
889 for (i = 0; i < klass->method.count; ++i) {
890 if (klass->methods [i]->name[0] == 'B' &&
891 !strcmp ("BeginInvoke", klass->methods [i]->name)) {
892 method = klass->methods [i];
897 g_assert (method != NULL);
899 im = mono_get_delegate_invoke (method->klass);
901 msg = mono_method_call_message_new (method, params, im, &async_callback, &state);
903 return mono_thread_pool_add ((MonoObject *)delegate, msg, async_callback, state);
907 mono_mb_emit_save_args (MonoMethodBuilder *mb, MonoMethodSignature *sig, gboolean save_this)
909 int i, params_var, tmp_var;
911 /* allocate local (pointer) *params[] */
912 params_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
913 /* allocate local (pointer) tmp */
914 tmp_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
916 /* alloate space on stack to store an array of pointers to the arguments */
917 mono_mb_emit_icon (mb, sizeof (gpointer) * (sig->param_count + 1));
918 mono_mb_emit_byte (mb, CEE_PREFIX1);
919 mono_mb_emit_byte (mb, CEE_LOCALLOC);
920 mono_mb_emit_stloc (mb, params_var);
923 mono_mb_emit_ldloc (mb, params_var);
924 mono_mb_emit_stloc (mb, tmp_var);
926 if (save_this && sig->hasthis) {
927 mono_mb_emit_ldloc (mb, tmp_var);
928 mono_mb_emit_ldarg_addr (mb, 0);
929 mono_mb_emit_byte (mb, CEE_STIND_I);
930 /* tmp = tmp + sizeof (gpointer) */
931 if (sig->param_count)
932 mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
936 for (i = 0; i < sig->param_count; i++) {
937 mono_mb_emit_ldloc (mb, tmp_var);
938 mono_mb_emit_ldarg_addr (mb, i + sig->hasthis);
939 mono_mb_emit_byte (mb, CEE_STIND_I);
940 /* tmp = tmp + sizeof (gpointer) */
941 if (i < (sig->param_count - 1))
942 mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
949 mono_signature_to_name (MonoMethodSignature *sig, const char *prefix)
953 GString *res = g_string_new ("");
956 g_string_append (res, prefix);
957 g_string_append_c (res, '_');
960 mono_type_get_desc (res, sig->ret, FALSE);
962 for (i = 0; i < sig->param_count; ++i) {
963 g_string_append_c (res, '_');
964 mono_type_get_desc (res, sig->params [i], FALSE);
967 g_string_free (res, FALSE);
972 mono_marshal_get_delegate_begin_invoke (MonoMethod *method)
974 MonoMethodSignature *sig;
975 static MonoMethodSignature *csig = NULL;
976 MonoMethodBuilder *mb;
982 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
983 !strcmp (method->name, "BeginInvoke"));
985 sig = method->signature;
987 cache = method->klass->image->delegate_begin_invoke_cache;
988 if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
991 g_assert (sig->hasthis);
994 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
995 csig = g_malloc0 (sigsize);
997 /* MonoAsyncResult * begin_invoke (MonoDelegate *delegate, gpointer params[]) */
998 csig->param_count = 2;
999 csig->ret = &mono_defaults.object_class->byval_arg;
1000 csig->params [0] = &mono_defaults.object_class->byval_arg;
1001 csig->params [1] = &mono_defaults.int_class->byval_arg;
1004 name = mono_signature_to_name (sig, "begin_invoke");
1005 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name);
1008 mb->method->wrapper_type = MONO_WRAPPER_DELEGATE_BEGIN_INVOKE;
1009 mb->method->save_lmf = 1;
1011 params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1013 mono_mb_emit_ldarg (mb, 0);
1014 mono_mb_emit_ldloc (mb, params_var);
1015 mono_mb_emit_native_call (mb, csig, mono_delegate_begin_invoke);
1016 mono_mb_emit_byte (mb, CEE_RET);
1018 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1020 g_hash_table_insert (cache, sig, res);
1025 mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params)
1027 MonoDomain *domain = mono_domain_get ();
1028 MonoAsyncResult *ares;
1029 MonoMethod *method = NULL;
1030 MonoMethodSignature *sig;
1031 MonoMethodMessage *msg;
1032 MonoObject *res, *exc;
1033 MonoArray *out_args;
1037 g_assert (delegate);
1039 if (!delegate->method_info || !delegate->method_info->method)
1040 g_assert_not_reached ();
1042 klass = delegate->object.vtable->klass;
1044 for (i = 0; i < klass->method.count; ++i) {
1045 if (klass->methods [i]->name[0] == 'E' &&
1046 !strcmp ("EndInvoke", klass->methods [i]->name)) {
1047 method = klass->methods [i];
1052 g_assert (method != NULL);
1054 sig = method->signature;
1056 msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1058 ares = mono_array_get (msg->args, gpointer, sig->param_count - 1);
1061 res = mono_thread_pool_finish (ares, &out_args, &exc);
1064 char *strace = mono_string_to_utf8 (((MonoException*)exc)->stack_trace);
1066 tmp = g_strdup_printf ("%s\nException Rethrown at:\n", strace);
1068 ((MonoException*)exc)->stack_trace = mono_string_new (domain, tmp);
1070 mono_raise_exception ((MonoException*)exc);
1073 mono_method_return_message_restore (method, params, out_args);
1078 mono_mb_emit_restore_result (MonoMethodBuilder *mb, MonoType *return_type)
1080 if (return_type->byref)
1081 return_type = &mono_defaults.int_class->byval_arg;
1082 else if (return_type->type == MONO_TYPE_VALUETYPE && return_type->data.klass->enumtype)
1083 return_type = return_type->data.klass->enum_basetype;
1085 switch (return_type->type) {
1086 case MONO_TYPE_VOID:
1087 g_assert_not_reached ();
1089 case MONO_TYPE_STRING:
1090 case MONO_TYPE_CLASS:
1091 case MONO_TYPE_OBJECT:
1092 case MONO_TYPE_ARRAY:
1093 case MONO_TYPE_SZARRAY:
1097 case MONO_TYPE_BOOLEAN:
1098 mono_mb_emit_byte (mb, CEE_UNBOX);
1099 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1100 mono_mb_emit_byte (mb, CEE_LDIND_U1);
1103 mono_mb_emit_byte (mb, CEE_UNBOX);
1104 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1105 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1108 case MONO_TYPE_CHAR:
1109 mono_mb_emit_byte (mb, CEE_UNBOX);
1110 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1111 mono_mb_emit_byte (mb, CEE_LDIND_U2);
1114 mono_mb_emit_byte (mb, CEE_UNBOX);
1115 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1116 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1120 mono_mb_emit_byte (mb, CEE_UNBOX);
1121 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1122 mono_mb_emit_byte (mb, CEE_LDIND_I);
1125 mono_mb_emit_byte (mb, CEE_UNBOX);
1126 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1127 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1130 mono_mb_emit_byte (mb, CEE_UNBOX);
1131 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1132 mono_mb_emit_byte (mb, CEE_LDIND_U4);
1136 mono_mb_emit_byte (mb, CEE_UNBOX);
1137 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1138 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1141 mono_mb_emit_byte (mb, CEE_UNBOX);
1142 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1143 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1146 mono_mb_emit_byte (mb, CEE_UNBOX);
1147 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1148 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1150 case MONO_TYPE_VALUETYPE: {
1152 mono_mb_emit_byte (mb, CEE_UNBOX);
1153 class = mono_mb_add_data (mb, mono_class_from_mono_type (return_type));
1154 mono_mb_emit_i4 (mb, class);
1155 mono_mb_emit_byte (mb, CEE_LDOBJ);
1156 mono_mb_emit_i4 (mb, class);
1160 g_warning ("type 0x%x not handled", return_type->type);
1161 g_assert_not_reached ();
1164 mono_mb_emit_byte (mb, CEE_RET);
1168 mono_marshal_get_delegate_end_invoke (MonoMethod *method)
1170 MonoMethodSignature *sig;
1171 static MonoMethodSignature *csig = NULL;
1172 MonoMethodBuilder *mb;
1178 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1179 !strcmp (method->name, "EndInvoke"));
1181 sig = method->signature;
1183 cache = method->klass->image->delegate_end_invoke_cache;
1184 if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1187 g_assert (sig->hasthis);
1190 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1191 csig = g_malloc0 (sigsize);
1193 /* MonoObject *end_invoke (MonoDelegate *delegate, gpointer params[]) */
1194 csig->param_count = 2;
1195 csig->ret = &mono_defaults.object_class->byval_arg;
1196 csig->params [0] = &mono_defaults.object_class->byval_arg;
1197 csig->params [1] = &mono_defaults.int_class->byval_arg;
1200 name = mono_signature_to_name (sig, "end_invoke");
1201 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name);
1204 mb->method->wrapper_type = MONO_WRAPPER_DELEGATE_END_INVOKE;
1205 mb->method->save_lmf = 1;
1207 params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1209 mono_mb_emit_ldarg (mb, 0);
1210 mono_mb_emit_ldloc (mb, params_var);
1211 mono_mb_emit_native_call (mb, csig, mono_delegate_end_invoke);
1213 if (sig->ret->type == MONO_TYPE_VOID) {
1214 mono_mb_emit_byte (mb, CEE_POP);
1215 mono_mb_emit_byte (mb, CEE_RET);
1217 mono_mb_emit_restore_result (mb, sig->ret);
1219 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1221 g_hash_table_insert (cache, sig, res);
1227 mono_remoting_wrapper (MonoMethod *method, gpointer *params)
1229 MonoMethodMessage *msg;
1230 MonoTransparentProxy *this;
1231 MonoObject *res, *exc;
1232 MonoArray *out_args;
1234 this = *((MonoTransparentProxy **)params [0]);
1237 g_assert (((MonoObject *)this)->vtable->klass == mono_defaults.transparent_proxy_class);
1239 /* skip the this pointer */
1242 msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1244 res = mono_remoting_invoke ((MonoObject *)this->rp, msg, &exc, &out_args);
1247 mono_raise_exception ((MonoException *)exc);
1249 mono_method_return_message_restore (method, params, out_args);
1255 mono_marshal_get_remoting_invoke (MonoMethod *method)
1257 MonoMethodSignature *sig;
1258 static MonoMethodSignature *csig = NULL;
1259 MonoMethodBuilder *mb;
1266 if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE)
1269 sig = method->signature;
1271 /* we cant remote methods without this pointer */
1275 cache = method->klass->image->remoting_invoke_cache;
1276 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1280 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1281 csig = g_malloc0 (sigsize);
1283 /* MonoObject *remoting_wrapper (MonoMethod *method, gpointer params[]) */
1284 csig->param_count = 2;
1285 csig->ret = &mono_defaults.object_class->byval_arg;
1286 csig->params [0] = &mono_defaults.int_class->byval_arg;
1287 csig->params [1] = &mono_defaults.int_class->byval_arg;
1290 mb = mono_mb_new (method->klass, method->name);
1291 mb->method->wrapper_type = MONO_WRAPPER_REMOTING_INVOKE;
1292 mb->method->save_lmf = 1;
1294 params_var = mono_mb_emit_save_args (mb, sig, TRUE);
1296 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1297 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1298 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
1299 mono_mb_emit_ldloc (mb, params_var);
1300 mono_mb_emit_native_call (mb, csig, mono_remoting_wrapper);
1302 if (sig->ret->type == MONO_TYPE_VOID)
1303 mono_mb_emit_byte (mb, CEE_POP);
1305 mono_mb_emit_restore_result (mb, sig->ret);
1307 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1309 g_hash_table_insert (cache, method, res);
1314 * the returned method invokes all methods in a multicast delegate
1317 mono_marshal_get_delegate_invoke (MonoMethod *method)
1319 MonoMethodSignature *sig, *static_sig;
1321 MonoMethodBuilder *mb;
1327 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1328 !strcmp (method->name, "Invoke"));
1330 sig = method->signature;
1332 cache = method->klass->image->delegate_invoke_cache;
1333 if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1336 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1337 static_sig = g_memdup (sig, sigsize);
1338 static_sig->hasthis = 0;
1340 name = mono_signature_to_name (sig, "invoke");
1341 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name);
1344 mb->method->wrapper_type = MONO_WRAPPER_DELEGATE_INVOKE;
1346 /* allocate local 0 (object) */
1347 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1349 g_assert (sig->hasthis);
1353 * prev.Invoke( args .. );
1354 * return this.<target>( args .. );
1357 /* get this->prev */
1358 mono_mb_emit_ldarg (mb, 0);
1359 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoMulticastDelegate, prev));
1360 mono_mb_emit_byte (mb, CEE_LDIND_I );
1361 mono_mb_emit_stloc (mb, 0);
1363 /* if prev != null */
1364 mono_mb_emit_ldloc (mb, 0);
1365 mono_mb_emit_byte (mb, CEE_BRFALSE);
1368 mono_mb_emit_i4 (mb, 0);
1371 mono_mb_emit_ldloc (mb, 0);
1372 for (i = 0; i < sig->param_count; i++)
1373 mono_mb_emit_ldarg (mb, i + 1);
1374 mono_mb_emit_managed_call (mb, method, method->signature);
1375 if (sig->ret->type != MONO_TYPE_VOID)
1376 mono_mb_emit_byte (mb, CEE_POP);
1378 /* continued or prev == null */
1379 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1381 /* get this->target */
1382 mono_mb_emit_ldarg (mb, 0);
1383 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, target));
1384 mono_mb_emit_byte (mb, CEE_LDIND_I );
1385 mono_mb_emit_stloc (mb, 0);
1387 /* if target != null */
1388 mono_mb_emit_ldloc (mb, 0);
1389 mono_mb_emit_byte (mb, CEE_BRFALSE);
1391 mono_mb_emit_i4 (mb, 0);
1393 /* then call this->method_ptr nonstatic */
1394 mono_mb_emit_ldloc (mb, 0);
1395 for (i = 0; i < sig->param_count; ++i)
1396 mono_mb_emit_ldarg (mb, i + 1);
1397 mono_mb_emit_ldarg (mb, 0);
1398 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1399 mono_mb_emit_byte (mb, CEE_LDIND_I );
1400 mono_mb_emit_byte (mb, CEE_CALLI);
1401 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
1403 mono_mb_emit_byte (mb, CEE_BR);
1405 mono_mb_emit_i4 (mb, 0);
1407 /* else [target == null] call this->method_ptr static */
1408 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1410 for (i = 0; i < sig->param_count; ++i)
1411 mono_mb_emit_ldarg (mb, i + 1);
1412 mono_mb_emit_ldarg (mb, 0);
1413 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1414 mono_mb_emit_byte (mb, CEE_LDIND_I );
1415 mono_mb_emit_byte (mb, CEE_CALLI);
1416 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, static_sig));
1419 mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
1420 mono_mb_emit_byte (mb, CEE_RET);
1422 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1425 g_hash_table_insert (cache, sig, res);
1431 * generates IL code for the runtime invoke function
1432 * MonoObject *runtime_invoke (MonoObject *this, void **params, MonoObject **exc)
1434 * we also catch exceptions if exc != null
1437 mono_marshal_get_runtime_invoke (MonoMethod *method)
1439 MonoMethodSignature *sig, *csig;
1440 MonoExceptionClause *clause;
1441 MonoMethodHeader *header;
1442 MonoMethodBuilder *mb;
1445 static MonoString *string_dummy = NULL;
1446 int i, pos, sigsize;
1450 cache = method->klass->image->runtime_invoke_cache;
1451 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1454 /* to make it work with our special string constructors */
1456 string_dummy = mono_string_new_wrapper ("dummy");
1458 sig = method->signature;
1460 sigsize = sizeof (MonoMethodSignature) + 3 * sizeof (MonoType *);
1461 csig = g_malloc0 (sigsize);
1463 csig->param_count = 3;
1464 csig->ret = &mono_defaults.object_class->byval_arg;
1465 csig->params [0] = &mono_defaults.object_class->byval_arg;
1466 csig->params [1] = &mono_defaults.int_class->byval_arg;
1467 csig->params [2] = &mono_defaults.int_class->byval_arg;
1469 mb = mono_mb_new (method->klass, method->name);
1470 mb->method->wrapper_type = MONO_WRAPPER_RUNTIME_INVOKE;
1472 /* allocate local 0 (object) tmp */
1473 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1474 /* allocate local 1 (object) exc */
1475 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1477 /* cond set *exc to null */
1478 mono_mb_emit_byte (mb, CEE_LDARG_2);
1479 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
1480 mono_mb_emit_byte (mb, 3);
1481 mono_mb_emit_byte (mb, CEE_LDARG_2);
1482 mono_mb_emit_byte (mb, CEE_LDNULL);
1483 mono_mb_emit_byte (mb, CEE_STIND_I);
1486 if (method->string_ctor) {
1487 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1488 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1489 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, string_dummy));
1491 mono_mb_emit_ldarg (mb, 0);
1492 if (method->klass->valuetype) {
1493 mono_mb_emit_byte (mb, CEE_UNBOX);
1494 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method->klass));
1499 for (i = 0; i < sig->param_count; i++) {
1500 MonoType *t = sig->params [i];
1503 mono_mb_emit_ldarg (mb, 1);
1505 mono_mb_emit_icon (mb, sizeof (gpointer) * i);
1506 mono_mb_emit_byte (mb, CEE_ADD);
1508 mono_mb_emit_byte (mb, CEE_LDIND_I);
1513 type = sig->params [i]->type;
1517 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1519 case MONO_TYPE_BOOLEAN:
1521 mono_mb_emit_byte (mb, CEE_LDIND_U1);
1524 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1527 case MONO_TYPE_CHAR:
1528 mono_mb_emit_byte (mb, CEE_LDIND_U2);
1532 mono_mb_emit_byte (mb, CEE_LDIND_I);
1535 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1538 mono_mb_emit_byte (mb, CEE_LDIND_U4);
1541 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1544 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1548 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1550 case MONO_TYPE_STRING:
1551 case MONO_TYPE_CLASS:
1552 case MONO_TYPE_ARRAY:
1554 case MONO_TYPE_SZARRAY:
1555 case MONO_TYPE_OBJECT:
1558 case MONO_TYPE_VALUETYPE:
1559 if (t->data.klass->enumtype) {
1560 type = t->data.klass->enum_basetype->type;
1563 mono_mb_emit_byte (mb, CEE_LDOBJ);
1564 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, t->data.klass));
1567 g_assert_not_reached ();
1571 if (method->string_ctor) {
1572 MonoMethodSignature *strsig;
1574 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1575 strsig = g_memdup (sig, sigsize);
1576 strsig->ret = &mono_defaults.string_class->byval_arg;
1578 mono_mb_emit_managed_call (mb, method, strsig);
1580 mono_mb_emit_managed_call (mb, method, NULL);
1582 if (sig->ret->byref) {
1584 g_assert_not_reached ();
1588 switch (sig->ret->type) {
1589 case MONO_TYPE_VOID:
1590 if (!method->string_ctor)
1591 mono_mb_emit_byte (mb, CEE_LDNULL);
1593 case MONO_TYPE_BOOLEAN:
1606 case MONO_TYPE_VALUETYPE:
1607 /* box value types */
1608 mono_mb_emit_byte (mb, CEE_BOX);
1609 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (sig->ret)));
1611 case MONO_TYPE_STRING:
1612 case MONO_TYPE_CLASS:
1613 case MONO_TYPE_ARRAY:
1614 case MONO_TYPE_SZARRAY:
1615 case MONO_TYPE_OBJECT:
1620 g_assert_not_reached ();
1623 mono_mb_emit_stloc (mb, 0);
1625 mono_mb_emit_byte (mb, CEE_LEAVE);
1627 mono_mb_emit_i4 (mb, 0);
1629 clause = g_new0 (MonoExceptionClause, 1);
1630 clause->flags = MONO_EXCEPTION_CLAUSE_FILTER;
1631 clause->try_len = mb->pos;
1634 clause->token_or_filter = mb->pos;
1636 mono_mb_emit_byte (mb, CEE_POP);
1637 mono_mb_emit_byte (mb, CEE_LDARG_2);
1638 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
1639 mono_mb_emit_byte (mb, CEE_PREFIX1);
1640 mono_mb_emit_byte (mb, CEE_CGT_UN);
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 (!this && (res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1696 /* fime: howto free that memory ? */
1699 sig = method->signature;
1701 mb = mono_mb_new (method->klass, method->name);
1702 mb->method->wrapper_type = MONO_WRAPPER_NATIVE_TO_MANAGED;
1704 /* allocate local 0 (pointer) src_ptr */
1705 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1706 /* allocate local 1 (pointer) dst_ptr */
1707 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1708 /* allocate local 2 (boolean) delete_old */
1709 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
1711 mono_mb_emit_byte (mb, CEE_LDNULL);
1712 mono_mb_emit_byte (mb, CEE_STLOC_2);
1714 /* we copy the signature, so that we can modify it */
1715 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1716 csig = g_memdup (sig, sigsize);
1720 /* fixme: howto handle this ? */
1724 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1725 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1726 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, this));
1731 g_assert_not_reached ();
1736 /* we first do all conversions */
1737 tmp_locals = alloca (sizeof (int) * sig->param_count);
1738 for (i = 0; i < sig->param_count; i ++) {
1739 MonoType *t = sig->params [i];
1744 case MONO_TYPE_VALUETYPE:
1746 klass = sig->params [i]->data.klass;
1747 if (klass->blittable || klass->enumtype)
1750 tmp_locals [i] = mono_mb_add_local (mb, &klass->byval_arg);
1753 mono_mb_emit_ldarg (mb, i);
1755 mono_mb_emit_ldarg_addr (mb, i);
1756 mono_mb_emit_byte (mb, CEE_STLOC_0);
1759 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1760 mono_mb_emit_byte (mb, CEE_BRFALSE);
1762 mono_mb_emit_i4 (mb, 0);
1765 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
1766 mono_mb_emit_byte (mb, CEE_STLOC_1);
1768 /* emit valuetype convnversion code code */
1769 emit_struct_conv (mb, klass, TRUE);
1772 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1774 case MONO_TYPE_STRING:
1778 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1779 csig->params [i] = &mono_defaults.int_class->byval_arg;
1781 mono_mb_emit_ldarg (mb, i);
1782 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1783 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1784 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
1785 mono_mb_emit_stloc (mb, tmp_locals [i]);
1787 case MONO_TYPE_ARRAY:
1788 case MONO_TYPE_SZARRAY:
1792 klass = mono_class_from_mono_type (t);
1794 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1795 csig->params [i] = &mono_defaults.int_class->byval_arg;
1797 g_warning ("array marshaling not implemented");
1798 g_assert_not_reached ();
1803 for (i = 0; i < sig->param_count; i++) {
1804 MonoType *t = sig->params [i];
1807 case MONO_TYPE_BOOLEAN:
1821 mono_mb_emit_ldarg (mb, i);
1823 case MONO_TYPE_STRING:
1825 mono_mb_emit_ldarg (mb, i);
1827 g_assert (tmp_locals [i]);
1828 mono_mb_emit_ldloc (mb, tmp_locals [i]);
1831 case MONO_TYPE_CLASS:
1832 case MONO_TYPE_ARRAY:
1833 case MONO_TYPE_SZARRAY:
1834 case MONO_TYPE_OBJECT:
1835 /* fixme: conversions ? */
1836 mono_mb_emit_ldarg (mb, i);
1838 case MONO_TYPE_VALUETYPE:
1839 klass = sig->params [i]->data.klass;
1840 if (klass->blittable || klass->enumtype) {
1841 mono_mb_emit_ldarg (mb, i);
1845 g_assert (tmp_locals [i]);
1847 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
1849 mono_mb_emit_ldloc (mb, tmp_locals [i]);
1852 g_warning ("type 0x%02x unknown", t->type);
1853 g_assert_not_reached ();
1857 mono_mb_emit_managed_call (mb, method, NULL);
1859 if (!sig->ret->byref) {
1860 switch (sig->ret->type) {
1861 case MONO_TYPE_VOID:
1862 case MONO_TYPE_BOOLEAN:
1878 case MONO_TYPE_STRING:
1879 csig->ret = &mono_defaults.int_class->byval_arg;
1881 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1882 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1883 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
1885 case MONO_TYPE_VALUETYPE: {
1887 klass = sig->ret->data.klass;
1888 if (klass->blittable || klass->enumtype)
1891 /* load pointer to returned value type */
1892 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1893 mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
1895 /* store the address of the source into local variable 0 */
1896 mono_mb_emit_byte (mb, CEE_STLOC_0);
1897 /* allocate space for the native struct and
1898 * store the address into dst_ptr */
1899 tmp = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1901 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
1902 mono_mb_emit_byte (mb, CEE_PREFIX1);
1903 mono_mb_emit_byte (mb, CEE_LOCALLOC);
1904 mono_mb_emit_byte (mb, CEE_STLOC_1);
1905 mono_mb_emit_byte (mb, CEE_LDLOC_1);
1906 mono_mb_emit_stloc (mb, tmp);
1908 /* emit valuetype conversion code */
1909 emit_struct_conv (mb, klass, FALSE);
1910 mono_mb_emit_ldloc (mb, tmp);
1911 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1912 mono_mb_emit_byte (mb, CEE_MONO_RETOBJ);
1913 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
1917 g_warning ("return type 0x%02x unknown", sig->ret->type);
1918 g_assert_not_reached ();
1922 mono_mb_emit_byte (mb, CEE_RET);
1924 res = mono_mb_create_method (mb, csig, sig->param_count + 16);
1928 g_hash_table_insert (cache, method, res);
1934 * generates IL code for the pinvoke wrapper (the generated method
1935 * calls the unamnage code in method->addr)
1938 mono_marshal_get_native_wrapper (MonoMethod *method)
1940 MonoMethodSignature *sig, *csig;
1941 MonoMethodBuilder *mb;
1945 gboolean pinvoke = FALSE;
1946 int i, pos, argnum, *tmp_locals;
1949 g_assert (method != NULL);
1951 cache = method->klass->image->native_wrapper_cache;
1952 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1955 sig = method->signature;
1957 if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
1958 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
1961 mb = mono_mb_new (method->klass, method->name);
1962 mb->method->wrapper_type = MONO_WRAPPER_MANAGED_TO_NATIVE;
1964 mb->method->save_lmf = 1;
1966 if (pinvoke && !method->addr)
1967 mono_lookup_pinvoke_call (method);
1969 if (!method->addr) {
1970 mono_mb_emit_exception (mb);
1971 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1973 g_hash_table_insert (cache, method, res);
1977 /* we copy the signature, so that we can modify it */
1978 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1980 /* internal calls: we simply push all arguments and call the method (no conversions) */
1981 if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
1983 MonoMethodSignature *call_sig;
1985 /* hack - string constructors returns a value */
1986 if (method->string_ctor) {
1987 csig = g_memdup (sig, sigsize);
1988 csig->ret = &mono_defaults.string_class->byval_arg;
1993 mono_mb_emit_byte (mb, CEE_LDARG_0);
1995 for (i = 0; i < sig->param_count; i++)
1996 mono_mb_emit_ldarg (mb, i + sig->hasthis);
1998 call_sig = g_memdup (csig, sigsize);
1999 call_sig->pinvoke = 1;
2001 g_assert (method->addr);
2002 mono_mb_emit_native_call (mb, call_sig, method->addr);
2004 mono_mb_emit_byte (mb, CEE_RET);
2006 res = mono_mb_create_method (mb, csig, sig->param_count + 16);
2008 g_hash_table_insert (cache, method, res);
2014 /* pinvoke: we need to convert the arguments if necessary */
2016 csig = g_memdup (sig, sigsize);
2019 /* we allocate local for use with emit_struct_conv() */
2020 /* allocate local 0 (pointer) src_ptr */
2021 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2022 /* allocate local 1 (pointer) dst_ptr */
2023 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2024 /* allocate local 2 (boolean) delete_old */
2025 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2027 /* delete_old = FALSE */
2028 mono_mb_emit_icon (mb, 0);
2029 mono_mb_emit_byte (mb, CEE_STLOC_2);
2031 if (sig->ret->type != MONO_TYPE_VOID) {
2032 /* allocate local 3 to store the return value */
2033 mono_mb_add_local (mb, sig->ret);
2036 /* we first do all conversions */
2037 tmp_locals = alloca (sizeof (int) * sig->param_count);
2038 for (i = 0; i < sig->param_count; i ++) {
2039 MonoType *t = sig->params [i];
2041 argnum = i + sig->hasthis;
2045 case MONO_TYPE_VALUETYPE:
2046 klass = t->data.klass;
2047 if (klass->blittable || klass->enumtype)
2050 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2052 /* store the address of the source into local variable 0 */
2054 mono_mb_emit_ldarg (mb, argnum);
2056 mono_mb_emit_ldarg_addr (mb, argnum);
2058 mono_mb_emit_byte (mb, CEE_STLOC_0);
2061 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2062 mono_mb_emit_byte (mb, CEE_BRFALSE);
2064 mono_mb_emit_i4 (mb, 0);
2067 /* allocate space for the native struct and
2068 * store the address into local variable 1 (dest) */
2069 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2070 mono_mb_emit_byte (mb, CEE_PREFIX1);
2071 mono_mb_emit_byte (mb, CEE_LOCALLOC);
2072 mono_mb_emit_stloc (mb, tmp_locals [i]);
2074 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2075 mono_mb_emit_byte (mb, CEE_STLOC_1);
2077 /* emit valuetype conversion code */
2078 emit_struct_conv (mb, klass, FALSE);
2081 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2083 case MONO_TYPE_STRING:
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, MONO_CUSTOM_PREFIX);
2092 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2093 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
2094 mono_mb_emit_stloc (mb, tmp_locals [i]);
2096 case MONO_TYPE_CLASS:
2097 case MONO_TYPE_OBJECT:
2101 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2102 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2104 if (t->data.klass->delegate) {
2105 mono_mb_emit_ldarg (mb, argnum);
2106 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2107 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2108 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_DEL_FTN);
2109 mono_mb_emit_stloc (mb, tmp_locals [i]);
2110 } else if (t->data.klass == mono_defaults.stringbuilder_class) {
2111 mono_mb_emit_ldarg (mb, argnum);
2112 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2113 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2114 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_SB_LPSTR);
2115 mono_mb_emit_stloc (mb, tmp_locals [i]);
2117 mono_mb_emit_ldarg (mb, argnum);
2118 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2119 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2120 /* fixme: convert to what ? */
2121 mono_mb_emit_stloc (mb, tmp_locals [i]);
2125 case MONO_TYPE_ARRAY:
2126 case MONO_TYPE_SZARRAY:
2130 klass = mono_class_from_mono_type (t);
2132 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2133 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2135 mono_mb_emit_ldarg (mb, argnum);
2136 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2137 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2138 if (klass->element_class == mono_defaults.string_class)
2139 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STRARRAY_STRLPARRAY);
2141 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_ARRAY_LPARRAY);
2142 mono_mb_emit_stloc (mb, tmp_locals [i]);
2147 /* push all arguments */
2150 mono_mb_emit_byte (mb, CEE_LDARG_0);
2152 for (i = 0; i < sig->param_count; i++) {
2153 MonoType *t = sig->params [i];
2155 argnum = i + sig->hasthis;
2158 case MONO_TYPE_BOOLEAN:
2160 g_warning ("byref boolean marshalling not inplemented");
2161 mono_mb_emit_ldarg (mb, argnum);
2176 mono_mb_emit_ldarg (mb, argnum);
2178 case MONO_TYPE_VALUETYPE:
2179 klass = sig->params [i]->data.klass;
2180 if (klass->blittable || klass->enumtype) {
2181 mono_mb_emit_ldarg (mb, argnum);
2184 g_assert (tmp_locals [i]);
2185 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2187 mono_mb_emit_byte (mb, CEE_LDOBJ);
2188 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2191 case MONO_TYPE_STRING:
2193 mono_mb_emit_ldarg (mb, argnum);
2195 g_assert (tmp_locals [i]);
2196 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2199 case MONO_TYPE_CLASS:
2200 case MONO_TYPE_OBJECT:
2202 mono_mb_emit_ldarg (mb, argnum);
2204 g_assert (tmp_locals [i]);
2205 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2208 case MONO_TYPE_CHAR:
2209 /* fixme: dont know how to marshal that. We cant simply
2210 * convert it to a one byte UTF8 character, because an
2211 * unicode character may need more that one byte in UTF8 */
2212 mono_mb_emit_ldarg (mb, argnum);
2214 case MONO_TYPE_ARRAY:
2215 case MONO_TYPE_SZARRAY:
2217 mono_mb_emit_ldarg (mb, argnum);
2219 g_assert (tmp_locals [i]);
2220 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2223 case MONO_TYPE_TYPEDBYREF:
2224 case MONO_TYPE_FNPTR:
2226 g_warning ("type 0x%02x unknown", t->type);
2227 g_assert_not_reached ();
2231 /* call the native method */
2232 mono_mb_emit_native_call (mb, csig, method->addr);
2234 /* return the result */
2236 /* we need to convert byref arguments back and free string arrays */
2237 for (i = 0; i < sig->param_count; i++) {
2238 MonoType *t = sig->params [i];
2240 argnum = i + sig->hasthis;
2243 case MONO_TYPE_CLASS:
2244 case MONO_TYPE_OBJECT:
2248 if (t->data.klass == mono_defaults.stringbuilder_class) {
2249 mono_mb_emit_ldarg (mb, argnum);
2250 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2251 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2252 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
2253 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_SB);
2254 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2255 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2256 mono_mb_emit_byte (mb, CEE_MONO_FREE);
2259 case MONO_TYPE_VALUETYPE:
2263 klass = t->data.klass;
2264 if (klass->blittable || klass->enumtype)
2267 /* dst = argument */
2268 mono_mb_emit_ldarg (mb, argnum);
2269 mono_mb_emit_byte (mb, CEE_STLOC_1);
2271 mono_mb_emit_byte (mb, CEE_LDLOC_1);
2272 mono_mb_emit_byte (mb, CEE_BRFALSE);
2274 mono_mb_emit_i4 (mb, 0);
2276 /* src = tmp_locals [i] */
2277 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2278 mono_mb_emit_byte (mb, CEE_STLOC_0);
2280 /* emit valuetype conversion code */
2281 emit_struct_conv (mb, klass, TRUE);
2283 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2285 case MONO_TYPE_SZARRAY:
2289 klass = mono_class_from_mono_type (t);
2291 if (klass->element_class == mono_defaults.string_class) {
2292 g_assert (tmp_locals [i]);
2293 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2294 mono_mb_emit_ldarg (mb, argnum);
2295 mono_mb_emit_byte (mb, CEE_LDLEN);
2296 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2297 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
2298 mono_mb_emit_byte (mb, MONO_MARSHAL_FREE_ARRAY);
2305 if (!sig->ret->byref) {
2306 type = sig->ret->type;
2309 case MONO_TYPE_VOID:
2323 /* no conversions necessary */
2325 case MONO_TYPE_BOOLEAN:
2326 /* maybe we need to make sure that it fits within 8 bits */
2328 case MONO_TYPE_VALUETYPE: {
2331 klass = sig->ret->data.klass;
2332 if (klass->enumtype) {
2333 type = sig->ret->data.klass->enum_basetype->type;
2337 if (klass->blittable)
2340 tmp = mono_mb_add_local (mb, sig->ret);
2342 /* load pointer to returned value type */
2343 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2344 mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
2345 /* store the address of the source into local variable 0 */
2346 mono_mb_emit_byte (mb, CEE_STLOC_0);
2348 mono_mb_emit_ldloc_addr (mb, tmp);
2349 mono_mb_emit_byte (mb, CEE_STLOC_1);
2351 /* emit valuetype conversion code */
2352 emit_struct_conv (mb, sig->ret->data.klass, TRUE);
2354 mono_mb_emit_ldloc (mb, tmp);
2357 case MONO_TYPE_STRING:
2358 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2359 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2360 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
2362 case MONO_TYPE_ARRAY:
2363 case MONO_TYPE_SZARRAY:
2364 case MONO_TYPE_CLASS:
2365 case MONO_TYPE_OBJECT:
2366 /* fixme: we need conversions here */
2368 case MONO_TYPE_CHAR:
2369 /* fixme: we need conversions here */
2371 case MONO_TYPE_TYPEDBYREF:
2372 case MONO_TYPE_FNPTR:
2374 g_warning ("return type 0x%02x unknown", sig->ret->type);
2375 g_assert_not_reached ();
2379 mono_mb_emit_byte (mb, CEE_RET);
2381 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
2384 g_hash_table_insert (cache, method, res);
2390 * generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld)
2393 mono_marshal_get_struct_to_ptr (MonoClass *klass)
2395 MonoMethodBuilder *mb;
2396 static MonoMethod *stoptr = NULL;
2399 g_assert (klass != NULL);
2401 if (klass->str_to_ptr)
2402 return klass->str_to_ptr;
2405 stoptr = mono_find_method_by_name (mono_defaults.marshal_class, "StructureToPtr", 3);
2408 mb = mono_mb_new (klass, stoptr->name);
2410 if (klass->blittable) {
2411 mono_mb_emit_byte (mb, CEE_LDARG_1);
2412 mono_mb_emit_byte (mb, CEE_LDARG_0);
2413 mono_mb_emit_icon (mb, sizeof (MonoObject));
2414 mono_mb_emit_byte (mb, CEE_ADD);
2415 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
2416 mono_mb_emit_byte (mb, CEE_PREFIX1);
2417 mono_mb_emit_byte (mb, CEE_CPBLK);
2420 /* allocate local 0 (pointer) src_ptr */
2421 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2422 /* allocate local 1 (pointer) dst_ptr */
2423 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2424 /* allocate local 2 (boolean) delete_old */
2425 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2426 mono_mb_emit_byte (mb, CEE_LDARG_2);
2427 mono_mb_emit_byte (mb, CEE_STLOC_2);
2429 /* initialize src_ptr to point to the start of object data */
2430 mono_mb_emit_byte (mb, CEE_LDARG_0);
2431 mono_mb_emit_icon (mb, sizeof (MonoObject));
2432 mono_mb_emit_byte (mb, CEE_ADD);
2433 mono_mb_emit_byte (mb, CEE_STLOC_0);
2435 /* initialize dst_ptr */
2436 mono_mb_emit_byte (mb, CEE_LDARG_1);
2437 mono_mb_emit_byte (mb, CEE_STLOC_1);
2439 emit_struct_conv (mb, klass, FALSE);
2442 mono_mb_emit_byte (mb, CEE_RET);
2444 res = mono_mb_create_method (mb, stoptr->signature, 0);
2447 klass->str_to_ptr = res;
2452 * generates IL code for PtrToStructure (IntPtr src, object structure)
2455 mono_marshal_get_ptr_to_struct (MonoClass *klass)
2457 MonoMethodBuilder *mb;
2458 static MonoMethod *ptostr = NULL;
2461 g_assert (klass != NULL);
2463 if (klass->ptr_to_str)
2464 return klass->ptr_to_str;
2467 ptostr = mono_find_method_by_name (mono_defaults.marshal_class, "PtrToStructure", 2);
2470 mb = mono_mb_new (klass, ptostr->name);
2472 if (klass->blittable) {
2473 mono_mb_emit_byte (mb, CEE_LDARG_1);
2474 mono_mb_emit_icon (mb, sizeof (MonoObject));
2475 mono_mb_emit_byte (mb, CEE_ADD);
2476 mono_mb_emit_byte (mb, CEE_LDARG_0);
2477 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
2478 mono_mb_emit_byte (mb, CEE_PREFIX1);
2479 mono_mb_emit_byte (mb, CEE_CPBLK);
2482 /* allocate local 0 (pointer) src_ptr */
2483 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2484 /* allocate local 1 (pointer) dst_ptr */
2485 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2487 /* initialize src_ptr to point to the start of object data */
2488 mono_mb_emit_byte (mb, CEE_LDARG_0);
2489 mono_mb_emit_byte (mb, CEE_STLOC_0);
2491 /* initialize dst_ptr */
2492 mono_mb_emit_byte (mb, CEE_LDARG_1);
2493 mono_mb_emit_icon (mb, sizeof (MonoObject));
2494 mono_mb_emit_byte (mb, CEE_ADD);
2495 mono_mb_emit_byte (mb, CEE_STLOC_1);
2497 emit_struct_conv (mb, klass, TRUE);
2500 mono_mb_emit_byte (mb, CEE_RET);
2502 res = mono_mb_create_method (mb, ptostr->signature, 0);
2505 klass->ptr_to_str = res;
2509 /* FIXME: on win32 we should probably use GlobalAlloc(). */
2511 mono_marshal_alloc (gpointer size) {
2512 return g_try_malloc ((gulong)size);
2516 mono_marshal_free (gpointer ptr) {
2521 mono_marshal_free_array (gpointer *ptr, int size) {
2524 for (i = 0; i < size; i++)
2530 mono_marshal_realloc (gpointer ptr, gpointer size) {
2531 return g_try_realloc (ptr, (gulong)size);
2535 mono_marshal_string_array (MonoArray *array)
2543 len = mono_array_length (array);
2545 result = g_malloc (sizeof (char *) * (len + 1));
2546 for (i = 0; i < len; ++i) {
2547 MonoString *s = (MonoString *)mono_array_get (array, gpointer, i);
2548 result [i] = s ? mono_string_to_utf8 (s): NULL;
2550 /* null terminate the array */
2557 ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArray *src, gint32 start_index,
2558 gpointer dest, gint32 length)
2563 MONO_CHECK_ARG_NULL (src);
2564 MONO_CHECK_ARG_NULL (dest);
2566 g_assert (src->obj.vtable->klass->rank == 1);
2567 g_assert (start_index >= 0 && start_index < mono_array_length (src));
2568 g_assert (start_index + length <= mono_array_length (src));
2570 element_size = mono_array_element_size (src->obj.vtable->klass);
2572 source_addr = mono_array_addr_with_size (src, element_size, start_index);
2574 memcpy (dest, source_addr, length * element_size);
2578 ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer src, gint32 start_index,
2579 MonoArray *dest, gint32 length)
2584 MONO_CHECK_ARG_NULL (src);
2585 MONO_CHECK_ARG_NULL (dest);
2587 g_assert (dest->obj.vtable->klass->rank == 1);
2588 g_assert (start_index >= 0 && start_index < mono_array_length (dest));
2589 g_assert (start_index + length <= mono_array_length (dest));
2591 element_size = mono_array_element_size (dest->obj.vtable->klass);
2593 dest_addr = mono_array_addr_with_size (dest, element_size, start_index);
2595 memcpy (dest_addr, src, length * element_size);
2599 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr, gint32 offset)
2602 return *(gpointer*)(p + offset);
2606 ves_icall_System_Runtime_InteropServices_Marshal_ReadByte (gpointer ptr, gint32 offset)
2609 return *(unsigned char*)(p + offset);
2613 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt16 (gpointer ptr, gint32 offset)
2616 return *(gint16*)(p + offset);
2620 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt32 (gpointer ptr, gint32 offset)
2623 return *(gint32*)(p + offset);
2627 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt64 (gpointer ptr, gint32 offset)
2630 return *(gint64*)(p + offset);
2634 ves_icall_System_Runtime_InteropServices_Marshal_WriteByte (gpointer ptr, gint32 offset, unsigned char val)
2637 *(unsigned char*)(p + offset) = val;
2641 ves_icall_System_Runtime_InteropServices_Marshal_WriteIntPtr (gpointer ptr, gint32 offset, gpointer val)
2644 *(gpointer*)(p + offset) = val;
2648 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt16 (gpointer ptr, gint32 offset, gint16 val)
2651 *(gint16*)(p + offset) = val;
2655 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt32 (gpointer ptr, gint32 offset, gint32 val)
2658 *(gint32*)(p + offset) = val;
2662 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt64 (gpointer ptr, gint32 offset, gint64 val)
2665 *(gint64*)(p + offset) = val;
2669 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (char *ptr)
2671 return mono_string_new (mono_domain_get (), ptr);
2675 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len (char *ptr, gint32 len)
2677 return mono_string_new_len (mono_domain_get (), ptr, len);
2681 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni (guint16 *ptr)
2683 MonoDomain *domain = mono_domain_get ();
2690 return mono_string_new_utf16 (domain, ptr, len);
2694 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len (guint16 *ptr, gint32 len)
2696 MonoDomain *domain = mono_domain_get ();
2698 return mono_string_new_utf16 (domain, ptr, len);
2702 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR (gpointer ptr)
2704 g_warning ("PtrToStringBSTR not implemented");
2705 g_assert_not_reached ();
2711 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
2713 return (GetLastError ());
2717 ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype)
2721 MONO_CHECK_ARG_NULL (rtype);
2723 klass = mono_class_from_mono_type (rtype->type);
2725 return mono_class_native_size (klass, NULL);
2729 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old)
2734 MONO_CHECK_ARG_NULL (obj);
2735 MONO_CHECK_ARG_NULL (dst);
2737 method = mono_marshal_get_struct_to_ptr (obj->vtable->klass);
2741 pa [2] = &delete_old;
2743 mono_runtime_invoke (method, NULL, pa, NULL);
2747 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, MonoObject *dst)
2752 MONO_CHECK_ARG_NULL (src);
2753 MONO_CHECK_ARG_NULL (dst);
2755 method = mono_marshal_get_ptr_to_struct (dst->vtable->klass);
2760 mono_runtime_invoke (method, NULL, pa, NULL);
2764 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer src, MonoReflectionType *type)
2766 MonoDomain *domain = mono_domain_get ();
2769 MONO_CHECK_ARG_NULL (src);
2770 MONO_CHECK_ARG_NULL (type);
2772 res = mono_object_new (domain, mono_class_from_mono_type (type->type));
2774 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (src, res);
2780 ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *type, MonoString *field_name)
2782 MonoMarshalType *info;
2787 MONO_CHECK_ARG_NULL (type);
2788 MONO_CHECK_ARG_NULL (field_name);
2790 fname = mono_string_to_utf8 (field_name);
2791 klass = mono_class_from_mono_type (type->type);
2793 info = mono_marshal_load_type_info (klass);
2795 for (i = 0; i < klass->field.count; ++i) {
2796 if (*fname == *klass->fields [i].name &&
2797 strcmp (fname, klass->fields [i].name) == 0)
2802 mono_assert (i < klass->field.count);
2804 return info->fields [i].offset;
2808 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString *string)
2810 return mono_string_to_utf8 (string);
2814 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni (MonoString *string)
2816 return g_memdup (mono_string_chars (string), mono_string_length (string)*2);
2820 mono_struct_delete_old (MonoClass *klass, char *ptr)
2822 MonoMarshalType *info;
2825 info = mono_marshal_load_type_info (klass);
2827 for (i = 0; i < info->num_fields; i++) {
2828 MonoMarshalNative ntype;
2829 MonoMarshalConv conv;
2830 MonoType *ftype = info->fields [i].field->type;
2833 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
2836 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE,
2837 klass->unicode, &conv);
2839 cpos = ptr + info->fields [i].offset;
2842 case MONO_MARSHAL_CONV_NONE:
2843 if (MONO_TYPE_ISSTRUCT (ftype)) {
2844 mono_struct_delete_old (ftype->data.klass, cpos);
2848 case MONO_MARSHAL_CONV_STR_LPWSTR:
2849 case MONO_MARSHAL_CONV_STR_LPSTR:
2850 case MONO_MARSHAL_CONV_STR_LPTSTR:
2851 case MONO_MARSHAL_CONV_STR_BSTR:
2852 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
2853 case MONO_MARSHAL_CONV_STR_TBSTR:
2854 g_free (*(gpointer *)cpos);
2863 ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure (gpointer src, MonoReflectionType *type)
2867 MONO_CHECK_ARG_NULL (src);
2868 MONO_CHECK_ARG_NULL (type);
2870 klass = mono_class_from_mono_type (type->type);
2872 mono_struct_delete_old (klass, (char *)src);