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);
349 mono_mb_emit_icon (mb, offset);
350 mono_mb_emit_byte (mb, CEE_ADD);
355 mono_mb_emit_proxy_check (MonoMethodBuilder *mb, int branch_code)
358 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoObject, vtable));
359 mono_mb_emit_byte (mb, CEE_LDIND_I);
360 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoVTable, klass));
361 mono_mb_emit_byte (mb, CEE_ADD);
362 mono_mb_emit_byte (mb, CEE_LDIND_I);
363 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
364 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
365 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_defaults.transparent_proxy_class));
366 mono_mb_emit_byte (mb, branch_code);
368 mono_mb_emit_i4 (mb, 0);
373 mono_mb_emit_i4 (MonoMethodBuilder *mb, gint32 data)
375 if ((mb->pos + 4) >= mb->code_size) {
377 mb->code = g_realloc (mb->code, mb->code_size);
380 mono_mb_patch_addr (mb, mb->pos, data);
385 mono_mb_emit_i2 (MonoMethodBuilder *mb, gint16 data)
387 if ((mb->pos + 2) >= mb->code_size) {
389 mb->code = g_realloc (mb->code, mb->code_size);
392 mb->code [mb->pos] = data & 0xff;
393 mb->code [mb->pos + 1] = (data >> 8) & 0xff;
398 mono_mb_emit_ldarg (MonoMethodBuilder *mb, guint argnum)
401 mono_mb_emit_byte (mb, CEE_LDARG_0 + argnum);
402 } else if (argnum < 256) {
403 mono_mb_emit_byte (mb, CEE_LDARG_S);
404 mono_mb_emit_byte (mb, argnum);
406 mono_mb_emit_byte (mb, CEE_PREFIX1);
407 mono_mb_emit_byte (mb, CEE_LDARG);
408 mono_mb_emit_i2 (mb, argnum);
413 mono_mb_emit_ldarg_addr (MonoMethodBuilder *mb, guint argnum)
416 mono_mb_emit_byte (mb, CEE_LDARGA_S);
417 mono_mb_emit_byte (mb, argnum);
419 mono_mb_emit_byte (mb, CEE_PREFIX1);
420 mono_mb_emit_byte (mb, CEE_LDARGA);
421 mono_mb_emit_i2 (mb, argnum);
426 mono_mb_emit_ldloc_addr (MonoMethodBuilder *mb, guint locnum)
429 mono_mb_emit_byte (mb, CEE_LDLOCA_S);
430 mono_mb_emit_byte (mb, locnum);
432 mono_mb_emit_byte (mb, CEE_PREFIX1);
433 mono_mb_emit_byte (mb, CEE_LDLOCA);
434 mono_mb_emit_i2 (mb, locnum);
439 mono_mb_emit_ldloc (MonoMethodBuilder *mb, guint num)
442 mono_mb_emit_byte (mb, CEE_LDLOC_0 + num);
443 } else if (num < 256) {
444 mono_mb_emit_byte (mb, CEE_LDLOC_S);
445 mono_mb_emit_byte (mb, num);
447 mono_mb_emit_byte (mb, CEE_PREFIX1);
448 mono_mb_emit_byte (mb, CEE_LDLOC);
449 mono_mb_emit_i2 (mb, num);
454 mono_mb_emit_stloc (MonoMethodBuilder *mb, guint num)
457 mono_mb_emit_byte (mb, CEE_STLOC_0 + num);
458 } else if (num < 256) {
459 mono_mb_emit_byte (mb, CEE_STLOC_S);
460 mono_mb_emit_byte (mb, num);
462 mono_mb_emit_byte (mb, CEE_PREFIX1);
463 mono_mb_emit_byte (mb, CEE_STLOC);
464 mono_mb_emit_i2 (mb, num);
469 mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value)
471 if (value >= -1 && value < 8) {
472 mono_mb_emit_byte (mb, CEE_LDC_I4_0 + value);
473 } else if (value >= -128 && value <= 127) {
474 mono_mb_emit_byte (mb, CEE_LDC_I4_S);
475 mono_mb_emit_byte (mb, value);
477 mono_mb_emit_byte (mb, CEE_LDC_I4);
478 mono_mb_emit_i4 (mb, value);
483 mono_mb_emit_managed_call (MonoMethodBuilder *mb, MonoMethod *method, MonoMethodSignature *opt_sig)
486 opt_sig = method->signature;
487 mono_mb_emit_byte (mb, CEE_PREFIX1);
488 mono_mb_emit_byte (mb, CEE_LDFTN);
489 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
490 mono_mb_emit_byte (mb, CEE_CALLI);
491 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, opt_sig));
495 mono_mb_emit_native_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, gpointer func)
497 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
498 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
499 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, func));
500 mono_mb_emit_byte (mb, CEE_CALLI);
501 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
505 mono_mb_emit_exception (MonoMethodBuilder *mb)
507 /* fixme: we need a better way to throw exception,
508 * supporting several exception types and messages */
509 static MonoMethod *missing_method_ctor = NULL;
511 if (!missing_method_ctor) {
512 MonoClass *mme = mono_class_from_name (mono_defaults.corlib, "System", "MissingMethodException");
514 mono_class_init (mme);
515 for (i = 0; i < mme->method.count; ++i) {
516 if (strcmp (mme->methods [i]->name, ".ctor") == 0 && mme->methods [i]->signature->param_count == 0) {
517 missing_method_ctor = mme->methods [i];
522 mono_mb_emit_byte (mb, CEE_NEWOBJ);
523 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, missing_method_ctor));
524 mono_mb_emit_byte (mb, CEE_THROW);
529 mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint16 local, gint32 incr)
531 mono_mb_emit_ldloc (mb, local);
532 mono_mb_emit_icon (mb, incr);
533 mono_mb_emit_byte (mb, CEE_ADD);
534 mono_mb_emit_stloc (mb, local);
538 emit_ptr_to_str_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv,
539 int usize, int msize)
542 case MONO_MARSHAL_CONV_BOOL_I4:
543 mono_mb_emit_byte (mb, CEE_LDLOC_0);
544 mono_mb_emit_byte (mb, CEE_LDIND_I);
545 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
546 mono_mb_emit_byte (mb, 5);
547 mono_mb_emit_byte (mb, CEE_LDLOC_1);
548 mono_mb_emit_byte (mb, CEE_LDC_I4_1);
549 mono_mb_emit_byte (mb, CEE_STIND_I1);
550 mono_mb_emit_byte (mb, CEE_BR_S);
551 mono_mb_emit_byte (mb, 3);
552 mono_mb_emit_byte (mb, CEE_LDLOC_1);
553 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
554 mono_mb_emit_byte (mb, CEE_STIND_I1);
556 case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
560 if (type->type == MONO_TYPE_ARRAY)
561 eclass = mono_class_from_mono_type (type->data.array->type);
562 else if (type->type == MONO_TYPE_SZARRAY) {
563 eclass = mono_class_from_mono_type (type->data.type);
565 g_assert_not_reached ();
568 if (eclass->valuetype)
569 esize = mono_class_instance_size (eclass) - sizeof (MonoObject);
571 esize = sizeof (gpointer);
573 /* create a new array */
574 /* fixme: this only works for SZARRAYS */
575 mono_mb_emit_byte (mb, CEE_LDLOC_1);
576 mono_mb_emit_icon (mb, msize / esize);
577 mono_mb_emit_byte (mb, CEE_NEWARR);
578 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eclass));
579 mono_mb_emit_byte (mb, CEE_STIND_I);
581 /* copy the elements */
582 mono_mb_emit_byte (mb, CEE_LDLOC_1);
583 mono_mb_emit_byte (mb, CEE_LDIND_I);
584 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
585 mono_mb_emit_byte (mb, CEE_ADD);
586 mono_mb_emit_byte (mb, CEE_LDLOC_0);
587 mono_mb_emit_icon (mb, usize);
588 mono_mb_emit_byte (mb, CEE_PREFIX1);
589 mono_mb_emit_byte (mb, CEE_CPBLK);
593 case MONO_MARSHAL_CONV_STR_BYVALSTR:
594 mono_mb_emit_byte (mb, CEE_LDLOC_1);
595 mono_mb_emit_byte (mb, CEE_LDLOC_0);
596 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
597 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
598 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
599 mono_mb_emit_byte (mb, CEE_STIND_I);
601 case MONO_MARSHAL_CONV_STR_LPTSTR:
602 case MONO_MARSHAL_CONV_STR_LPSTR:
603 mono_mb_emit_byte (mb, CEE_LDLOC_1);
604 mono_mb_emit_byte (mb, CEE_LDLOC_0);
605 mono_mb_emit_byte (mb, CEE_LDIND_I);
606 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
607 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
608 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
609 mono_mb_emit_byte (mb, CEE_STIND_I);
611 case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
612 MonoClass *klass = mono_class_from_mono_type (type);
613 int src_var, dst_var;
615 src_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
616 dst_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
618 /* *dst = new object */
619 mono_mb_emit_byte (mb, CEE_LDLOC_1);
620 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
621 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);
622 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
623 mono_mb_emit_byte (mb, CEE_STIND_I);
625 /* save the old src pointer */
626 mono_mb_emit_byte (mb, CEE_LDLOC_0);
627 mono_mb_emit_stloc (mb, src_var);
628 /* save the old dst pointer */
629 mono_mb_emit_byte (mb, CEE_LDLOC_1);
630 mono_mb_emit_stloc (mb, dst_var);
632 /* dst = pointer to newly created object data */
633 mono_mb_emit_byte (mb, CEE_LDLOC_1);
634 mono_mb_emit_byte (mb, CEE_LDIND_I);
635 mono_mb_emit_icon (mb, sizeof (MonoObject));
636 mono_mb_emit_byte (mb, CEE_ADD);
637 mono_mb_emit_byte (mb, CEE_STLOC_1);
639 emit_struct_conv (mb, klass, TRUE);
641 /* restore the old src pointer */
642 mono_mb_emit_ldloc (mb, src_var);
643 mono_mb_emit_byte (mb, CEE_STLOC_0);
644 /* restore the old dst pointer */
645 mono_mb_emit_ldloc (mb, dst_var);
646 mono_mb_emit_byte (mb, CEE_STLOC_1);
649 case MONO_MARSHAL_CONV_DEL_FTN: {
650 // fixme: we never convert functions back to delegates, dont
651 // know if thats the correct behaviour
654 case MONO_MARSHAL_CONV_STR_LPWSTR:
655 case MONO_MARSHAL_CONV_STR_BSTR:
656 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
657 case MONO_MARSHAL_CONV_STR_TBSTR:
658 case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
659 case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
660 case MONO_MARSHAL_CONV_STR_BYVALWSTR:
661 case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
663 g_warning ("marshaling conversion %d not implemented", conv);
664 g_assert_not_reached ();
669 emit_str_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, int usize, int msize)
674 case MONO_MARSHAL_CONV_BOOL_I4:
675 mono_mb_emit_byte (mb, CEE_LDLOC_1);
676 mono_mb_emit_byte (mb, CEE_LDLOC_0);
677 mono_mb_emit_byte (mb, CEE_LDIND_U1);
678 mono_mb_emit_byte (mb, CEE_STIND_I4);
680 case MONO_MARSHAL_CONV_STR_LPWSTR:
681 case MONO_MARSHAL_CONV_STR_LPSTR:
682 case MONO_MARSHAL_CONV_STR_LPTSTR:
683 case MONO_MARSHAL_CONV_STR_BSTR:
684 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
685 case MONO_MARSHAL_CONV_STR_TBSTR:
686 /* free space if free == true */
687 mono_mb_emit_byte (mb, CEE_LDLOC_2);
688 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
689 mono_mb_emit_byte (mb, 4);
690 mono_mb_emit_byte (mb, CEE_LDLOC_1);
691 mono_mb_emit_byte (mb, CEE_LDIND_I);
692 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
693 mono_mb_emit_byte (mb, CEE_MONO_FREE);
695 mono_mb_emit_byte (mb, CEE_LDLOC_1);
696 mono_mb_emit_byte (mb, CEE_LDLOC_0);
697 mono_mb_emit_byte (mb, CEE_LDIND_I);
698 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
699 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
700 mono_mb_emit_byte (mb, conv);
701 mono_mb_emit_byte (mb, CEE_STIND_I);
703 case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
704 case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
705 case MONO_MARSHAL_CONV_DEL_FTN:
706 mono_mb_emit_byte (mb, CEE_LDLOC_1);
707 mono_mb_emit_byte (mb, CEE_LDLOC_0);
708 mono_mb_emit_byte (mb, CEE_LDIND_I);
709 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
710 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
711 mono_mb_emit_byte (mb, conv);
712 mono_mb_emit_byte (mb, CEE_STIND_I);
714 case MONO_MARSHAL_CONV_STR_BYVALSTR:
715 case MONO_MARSHAL_CONV_STR_BYVALWSTR: {
719 mono_mb_emit_byte (mb, CEE_LDLOC_1); /* dst */
720 mono_mb_emit_byte (mb, CEE_LDLOC_0);
721 mono_mb_emit_byte (mb, CEE_LDIND_I); /* src String */
722 mono_mb_emit_icon (mb, usize);
723 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
724 mono_mb_emit_byte (mb, CEE_MONO_PROC3);
725 mono_mb_emit_byte (mb, conv);
728 case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
732 mono_mb_emit_byte (mb, CEE_LDLOC_0);
733 mono_mb_emit_byte (mb, CEE_LDIND_I);
734 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
736 mono_mb_emit_byte (mb, 0);
738 mono_mb_emit_byte (mb, CEE_LDLOC_1);
739 mono_mb_emit_byte (mb, CEE_LDLOC_0);
740 mono_mb_emit_byte (mb, CEE_LDIND_I);
741 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
742 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
743 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
744 mono_mb_emit_byte (mb, CEE_ADD);
745 mono_mb_emit_icon (mb, usize);
746 mono_mb_emit_byte (mb, CEE_PREFIX1);
747 mono_mb_emit_byte (mb, CEE_CPBLK);
748 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
751 case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
752 int src_var, dst_var;
754 src_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
755 dst_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
757 mono_mb_emit_byte (mb, CEE_LDLOC_0);
758 mono_mb_emit_byte (mb, CEE_LDIND_I);
759 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
761 mono_mb_emit_byte (mb, 0);
763 /* save the old src pointer */
764 mono_mb_emit_byte (mb, CEE_LDLOC_0);
765 mono_mb_emit_stloc (mb, src_var);
766 /* save the old dst pointer */
767 mono_mb_emit_byte (mb, CEE_LDLOC_1);
768 mono_mb_emit_stloc (mb, dst_var);
770 /* src = pointer to object data */
771 mono_mb_emit_byte (mb, CEE_LDLOC_0);
772 mono_mb_emit_byte (mb, CEE_LDIND_I);
773 mono_mb_emit_icon (mb, sizeof (MonoObject));
774 mono_mb_emit_byte (mb, CEE_ADD);
775 mono_mb_emit_byte (mb, CEE_STLOC_0);
777 emit_struct_conv (mb, mono_class_from_mono_type (type), FALSE);
779 /* restore the old src pointer */
780 mono_mb_emit_ldloc (mb, src_var);
781 mono_mb_emit_byte (mb, CEE_STLOC_0);
782 /* restore the old dst pointer */
783 mono_mb_emit_ldloc (mb, dst_var);
784 mono_mb_emit_byte (mb, CEE_STLOC_1);
786 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
789 case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
791 g_warning ("marshalling conversion %d not implemented", conv);
792 g_assert_not_reached ();
797 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
799 MonoMarshalType *info;
802 info = mono_marshal_load_type_info (klass);
804 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
805 mono_mb_emit_byte (mb, CEE_LDLOC_1);
806 mono_mb_emit_byte (mb, CEE_LDLOC_0);
807 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
808 mono_mb_emit_byte (mb, CEE_PREFIX1);
809 mono_mb_emit_byte (mb, CEE_CPBLK);
813 for (i = 0; i < info->num_fields; i++) {
814 MonoMarshalNative ntype;
815 MonoMarshalConv conv;
816 MonoType *ftype = info->fields [i].field->type;
819 gboolean last_field = i < (info->num_fields -1) ? 0 : 1;
821 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
824 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, klass->unicode, &conv);
827 msize = klass->instance_size - info->fields [i].field->offset;
828 usize = info->native_size - info->fields [i].offset;
830 msize = klass->fields [i + 1].offset - info->fields [i].field->offset;
831 usize = info->fields [i + 1].offset - info->fields [i].offset;
833 g_assert (msize > 0 && usize > 0);
836 case MONO_MARSHAL_CONV_NONE: {
839 if (ftype->byref || ftype->type == MONO_TYPE_I ||
840 ftype->type == MONO_TYPE_U) {
841 mono_mb_emit_byte (mb, CEE_LDLOC_1);
842 mono_mb_emit_byte (mb, CEE_LDLOC_0);
843 mono_mb_emit_byte (mb, CEE_LDIND_I);
844 mono_mb_emit_byte (mb, CEE_STIND_I);
853 #if SIZEOF_VOID_P == 4
856 mono_mb_emit_byte (mb, CEE_LDLOC_1);
857 mono_mb_emit_byte (mb, CEE_LDLOC_0);
858 mono_mb_emit_byte (mb, CEE_LDIND_I4);
859 mono_mb_emit_byte (mb, CEE_STIND_I4);
863 case MONO_TYPE_BOOLEAN:
864 mono_mb_emit_byte (mb, CEE_LDLOC_1);
865 mono_mb_emit_byte (mb, CEE_LDLOC_0);
866 mono_mb_emit_byte (mb, CEE_LDIND_I1);
867 mono_mb_emit_byte (mb, CEE_STIND_I1);
871 mono_mb_emit_byte (mb, CEE_LDLOC_1);
872 mono_mb_emit_byte (mb, CEE_LDLOC_0);
873 mono_mb_emit_byte (mb, CEE_LDIND_I2);
874 mono_mb_emit_byte (mb, CEE_STIND_I2);
878 #if SIZEOF_VOID_P == 8
881 mono_mb_emit_byte (mb, CEE_LDLOC_1);
882 mono_mb_emit_byte (mb, CEE_LDLOC_0);
883 mono_mb_emit_byte (mb, CEE_LDIND_I8);
884 mono_mb_emit_byte (mb, CEE_STIND_I8);
887 mono_mb_emit_byte (mb, CEE_LDLOC_1);
888 mono_mb_emit_byte (mb, CEE_LDLOC_0);
889 mono_mb_emit_byte (mb, CEE_LDIND_R4);
890 mono_mb_emit_byte (mb, CEE_STIND_R4);
893 mono_mb_emit_byte (mb, CEE_LDLOC_1);
894 mono_mb_emit_byte (mb, CEE_LDLOC_0);
895 mono_mb_emit_byte (mb, CEE_LDIND_R8);
896 mono_mb_emit_byte (mb, CEE_STIND_R8);
898 case MONO_TYPE_VALUETYPE:
899 if (ftype->data.klass->enumtype) {
900 t = ftype->data.klass->enum_basetype->type;
903 emit_struct_conv (mb, ftype->data.klass, to_object);
906 g_warning ("marshaling type %02x not implemented", ftype->type);
907 g_assert_not_reached ();
913 emit_ptr_to_str_conv (mb, ftype, conv, usize, msize);
915 emit_str_to_ptr_conv (mb, ftype, conv, usize, msize);
919 mono_mb_emit_add_to_local (mb, 0, usize);
920 mono_mb_emit_add_to_local (mb, 1, msize);
922 mono_mb_emit_add_to_local (mb, 0, msize);
923 mono_mb_emit_add_to_local (mb, 1, usize);
928 static MonoAsyncResult *
929 mono_delegate_begin_invoke (MonoDelegate *delegate, gpointer *params)
931 MonoMethodMessage *msg;
932 MonoDelegate *async_callback;
936 MonoMethod *method = NULL;
941 klass = delegate->object.vtable->klass;
943 method = mono_get_delegate_invoke (klass);
944 for (i = 0; i < klass->method.count; ++i) {
945 if (klass->methods [i]->name[0] == 'B' &&
946 !strcmp ("BeginInvoke", klass->methods [i]->name)) {
947 method = klass->methods [i];
952 g_assert (method != NULL);
954 im = mono_get_delegate_invoke (method->klass);
956 msg = mono_method_call_message_new (method, params, im, &async_callback, &state);
958 return mono_thread_pool_add ((MonoObject *)delegate, msg, async_callback, state);
962 mono_mb_emit_save_args (MonoMethodBuilder *mb, MonoMethodSignature *sig, gboolean save_this)
964 int i, params_var, tmp_var;
966 /* allocate local (pointer) *params[] */
967 params_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
968 /* allocate local (pointer) tmp */
969 tmp_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
971 /* alloate space on stack to store an array of pointers to the arguments */
972 mono_mb_emit_icon (mb, sizeof (gpointer) * (sig->param_count + 1));
973 mono_mb_emit_byte (mb, CEE_PREFIX1);
974 mono_mb_emit_byte (mb, CEE_LOCALLOC);
975 mono_mb_emit_stloc (mb, params_var);
978 mono_mb_emit_ldloc (mb, params_var);
979 mono_mb_emit_stloc (mb, tmp_var);
981 if (save_this && sig->hasthis) {
982 mono_mb_emit_ldloc (mb, tmp_var);
983 mono_mb_emit_ldarg_addr (mb, 0);
984 mono_mb_emit_byte (mb, CEE_STIND_I);
985 /* tmp = tmp + sizeof (gpointer) */
986 if (sig->param_count)
987 mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
991 for (i = 0; i < sig->param_count; i++) {
992 mono_mb_emit_ldloc (mb, tmp_var);
993 mono_mb_emit_ldarg_addr (mb, i + sig->hasthis);
994 mono_mb_emit_byte (mb, CEE_STIND_I);
995 /* tmp = tmp + sizeof (gpointer) */
996 if (i < (sig->param_count - 1))
997 mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
1004 mono_signature_to_name (MonoMethodSignature *sig, const char *prefix)
1008 GString *res = g_string_new ("");
1011 g_string_append (res, prefix);
1012 g_string_append_c (res, '_');
1015 mono_type_get_desc (res, sig->ret, FALSE);
1017 for (i = 0; i < sig->param_count; ++i) {
1018 g_string_append_c (res, '_');
1019 mono_type_get_desc (res, sig->params [i], FALSE);
1022 g_string_free (res, FALSE);
1027 mono_marshal_get_delegate_begin_invoke (MonoMethod *method)
1029 MonoMethodSignature *sig;
1030 static MonoMethodSignature *csig = NULL;
1031 MonoMethodBuilder *mb;
1037 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1038 !strcmp (method->name, "BeginInvoke"));
1040 sig = method->signature;
1042 cache = method->klass->image->delegate_begin_invoke_cache;
1043 if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1046 g_assert (sig->hasthis);
1049 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1050 csig = g_malloc0 (sigsize);
1052 /* MonoAsyncResult * begin_invoke (MonoDelegate *delegate, gpointer params[]) */
1053 csig->param_count = 2;
1054 csig->ret = &mono_defaults.object_class->byval_arg;
1055 csig->params [0] = &mono_defaults.object_class->byval_arg;
1056 csig->params [1] = &mono_defaults.int_class->byval_arg;
1059 name = mono_signature_to_name (sig, "begin_invoke");
1060 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_BEGIN_INVOKE);
1063 mb->method->save_lmf = 1;
1065 params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1067 mono_mb_emit_ldarg (mb, 0);
1068 mono_mb_emit_ldloc (mb, params_var);
1069 mono_mb_emit_native_call (mb, csig, mono_delegate_begin_invoke);
1070 mono_mb_emit_byte (mb, CEE_RET);
1072 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1074 g_hash_table_insert (cache, sig, res);
1079 mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params)
1081 MonoDomain *domain = mono_domain_get ();
1082 MonoAsyncResult *ares;
1083 MonoMethod *method = NULL;
1084 MonoMethodSignature *sig;
1085 MonoMethodMessage *msg;
1086 MonoObject *res, *exc;
1087 MonoArray *out_args;
1091 g_assert (delegate);
1093 if (!delegate->method_info || !delegate->method_info->method)
1094 g_assert_not_reached ();
1096 klass = delegate->object.vtable->klass;
1098 for (i = 0; i < klass->method.count; ++i) {
1099 if (klass->methods [i]->name[0] == 'E' &&
1100 !strcmp ("EndInvoke", klass->methods [i]->name)) {
1101 method = klass->methods [i];
1106 g_assert (method != NULL);
1108 sig = method->signature;
1110 msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1112 ares = mono_array_get (msg->args, gpointer, sig->param_count - 1);
1115 res = mono_thread_pool_finish (ares, &out_args, &exc);
1118 char *strace = mono_string_to_utf8 (((MonoException*)exc)->stack_trace);
1120 tmp = g_strdup_printf ("%s\nException Rethrown at:\n", strace);
1122 ((MonoException*)exc)->stack_trace = mono_string_new (domain, tmp);
1124 mono_raise_exception ((MonoException*)exc);
1127 mono_method_return_message_restore (method, params, out_args);
1132 mono_mb_emit_restore_result (MonoMethodBuilder *mb, MonoType *return_type)
1134 if (return_type->byref)
1135 return_type = &mono_defaults.int_class->byval_arg;
1136 else if (return_type->type == MONO_TYPE_VALUETYPE && return_type->data.klass->enumtype)
1137 return_type = return_type->data.klass->enum_basetype;
1139 switch (return_type->type) {
1140 case MONO_TYPE_VOID:
1141 g_assert_not_reached ();
1143 case MONO_TYPE_STRING:
1144 case MONO_TYPE_CLASS:
1145 case MONO_TYPE_OBJECT:
1146 case MONO_TYPE_ARRAY:
1147 case MONO_TYPE_SZARRAY:
1151 case MONO_TYPE_BOOLEAN:
1152 mono_mb_emit_byte (mb, CEE_UNBOX);
1153 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1154 mono_mb_emit_byte (mb, CEE_LDIND_U1);
1157 mono_mb_emit_byte (mb, CEE_UNBOX);
1158 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1159 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1162 case MONO_TYPE_CHAR:
1163 mono_mb_emit_byte (mb, CEE_UNBOX);
1164 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1165 mono_mb_emit_byte (mb, CEE_LDIND_U2);
1168 mono_mb_emit_byte (mb, CEE_UNBOX);
1169 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1170 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1174 mono_mb_emit_byte (mb, CEE_UNBOX);
1175 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1176 mono_mb_emit_byte (mb, CEE_LDIND_I);
1179 mono_mb_emit_byte (mb, CEE_UNBOX);
1180 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1181 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1184 mono_mb_emit_byte (mb, CEE_UNBOX);
1185 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1186 mono_mb_emit_byte (mb, CEE_LDIND_U4);
1190 mono_mb_emit_byte (mb, CEE_UNBOX);
1191 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1192 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1195 mono_mb_emit_byte (mb, CEE_UNBOX);
1196 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1197 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1200 mono_mb_emit_byte (mb, CEE_UNBOX);
1201 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1202 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1204 case MONO_TYPE_VALUETYPE: {
1206 mono_mb_emit_byte (mb, CEE_UNBOX);
1207 class = mono_mb_add_data (mb, mono_class_from_mono_type (return_type));
1208 mono_mb_emit_i4 (mb, class);
1209 mono_mb_emit_byte (mb, CEE_LDOBJ);
1210 mono_mb_emit_i4 (mb, class);
1214 g_warning ("type 0x%x not handled", return_type->type);
1215 g_assert_not_reached ();
1218 mono_mb_emit_byte (mb, CEE_RET);
1222 mono_marshal_get_delegate_end_invoke (MonoMethod *method)
1224 MonoMethodSignature *sig;
1225 static MonoMethodSignature *csig = NULL;
1226 MonoMethodBuilder *mb;
1232 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1233 !strcmp (method->name, "EndInvoke"));
1235 sig = method->signature;
1237 cache = method->klass->image->delegate_end_invoke_cache;
1238 if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1241 g_assert (sig->hasthis);
1244 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1245 csig = g_malloc0 (sigsize);
1247 /* MonoObject *end_invoke (MonoDelegate *delegate, gpointer params[]) */
1248 csig->param_count = 2;
1249 csig->ret = &mono_defaults.object_class->byval_arg;
1250 csig->params [0] = &mono_defaults.object_class->byval_arg;
1251 csig->params [1] = &mono_defaults.int_class->byval_arg;
1254 name = mono_signature_to_name (sig, "end_invoke");
1255 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_END_INVOKE);
1258 mb->method->save_lmf = 1;
1260 params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1262 mono_mb_emit_ldarg (mb, 0);
1263 mono_mb_emit_ldloc (mb, params_var);
1264 mono_mb_emit_native_call (mb, csig, mono_delegate_end_invoke);
1266 if (sig->ret->type == MONO_TYPE_VOID) {
1267 mono_mb_emit_byte (mb, CEE_POP);
1268 mono_mb_emit_byte (mb, CEE_RET);
1270 mono_mb_emit_restore_result (mb, sig->ret);
1272 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1274 g_hash_table_insert (cache, sig, res);
1280 mono_remoting_wrapper (MonoMethod *method, gpointer *params)
1282 MonoMethodMessage *msg;
1283 MonoTransparentProxy *this;
1284 MonoObject *res, *exc;
1285 MonoArray *out_args;
1287 this = *((MonoTransparentProxy **)params [0]);
1290 g_assert (((MonoObject *)this)->vtable->klass == mono_defaults.transparent_proxy_class);
1292 /* skip the this pointer */
1295 msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1297 res = mono_remoting_invoke ((MonoObject *)this->rp, msg, &exc, &out_args);
1300 mono_raise_exception ((MonoException *)exc);
1302 mono_method_return_message_restore (method, params, out_args);
1308 mono_marshal_get_remoting_invoke (MonoMethod *method)
1310 MonoMethodSignature *sig;
1311 static MonoMethodSignature *csig = NULL;
1312 MonoMethodBuilder *mb;
1319 if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE)
1322 sig = method->signature;
1324 /* we cant remote methods without this pointer */
1328 cache = method->klass->image->remoting_invoke_cache;
1329 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1333 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
1334 csig->params [0] = &mono_defaults.int_class->byval_arg;
1335 csig->params [1] = &mono_defaults.int_class->byval_arg;
1336 csig->ret = &mono_defaults.object_class->byval_arg;
1340 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE);
1341 mb->method->save_lmf = 1;
1343 params_var = mono_mb_emit_save_args (mb, sig, TRUE);
1345 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1346 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1347 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
1348 mono_mb_emit_ldloc (mb, params_var);
1349 mono_mb_emit_native_call (mb, csig, mono_remoting_wrapper);
1351 if (sig->ret->type == MONO_TYPE_VOID) {
1352 mono_mb_emit_byte (mb, CEE_POP);
1353 mono_mb_emit_byte (mb, CEE_RET);
1355 mono_mb_emit_restore_result (mb, sig->ret);
1358 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1360 g_hash_table_insert (cache, method, res);
1365 mono_marshal_get_remoting_invoke_with_check (MonoMethod *method)
1367 MonoMethodSignature *sig;
1368 MonoMethodBuilder *mb;
1369 MonoMethod *res, *native;
1375 if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)
1378 sig = method->signature;
1380 /* we cant remote methods without this pointer */
1381 g_assert (sig->hasthis);
1383 cache = method->klass->image->remoting_invoke_cache;
1384 if ((res = (MonoMethod *)g_hash_table_lookup (cache, (char *)method + 1)))
1387 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK);
1389 mono_mb_emit_ldarg (mb, 0);
1390 pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
1392 native = mono_marshal_get_remoting_invoke (method);
1394 for (i = 0; i <= sig->param_count; i++)
1395 mono_mb_emit_ldarg (mb, i);
1397 mono_mb_emit_managed_call (mb, native, native->signature);
1398 mono_mb_emit_byte (mb, CEE_RET);
1400 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1402 for (i = 0; i <= sig->param_count; i++)
1403 mono_mb_emit_ldarg (mb, i);
1405 mono_mb_emit_managed_call (mb, method, method->signature);
1406 mono_mb_emit_byte (mb, CEE_RET);
1408 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1410 g_hash_table_insert (cache, (char *)method + 1, res);
1415 * the returned method invokes all methods in a multicast delegate
1418 mono_marshal_get_delegate_invoke (MonoMethod *method)
1420 MonoMethodSignature *sig, *static_sig;
1422 MonoMethodBuilder *mb;
1428 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1429 !strcmp (method->name, "Invoke"));
1431 sig = method->signature;
1433 cache = method->klass->image->delegate_invoke_cache;
1434 if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1437 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1438 static_sig = g_memdup (sig, sigsize);
1439 static_sig->hasthis = 0;
1441 name = mono_signature_to_name (sig, "invoke");
1442 mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_INVOKE);
1445 /* allocate local 0 (object) */
1446 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1448 g_assert (sig->hasthis);
1452 * prev.Invoke( args .. );
1453 * return this.<target>( args .. );
1456 /* get this->prev */
1457 mono_mb_emit_ldarg (mb, 0);
1458 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoMulticastDelegate, prev));
1459 mono_mb_emit_byte (mb, CEE_LDIND_I );
1460 mono_mb_emit_stloc (mb, 0);
1462 /* if prev != null */
1463 mono_mb_emit_ldloc (mb, 0);
1464 mono_mb_emit_byte (mb, CEE_BRFALSE);
1467 mono_mb_emit_i4 (mb, 0);
1470 mono_mb_emit_ldloc (mb, 0);
1471 for (i = 0; i < sig->param_count; i++)
1472 mono_mb_emit_ldarg (mb, i + 1);
1473 mono_mb_emit_managed_call (mb, method, method->signature);
1474 if (sig->ret->type != MONO_TYPE_VOID)
1475 mono_mb_emit_byte (mb, CEE_POP);
1477 /* continued or prev == null */
1478 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1480 /* get this->target */
1481 mono_mb_emit_ldarg (mb, 0);
1482 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, target));
1483 mono_mb_emit_byte (mb, CEE_LDIND_I );
1484 mono_mb_emit_stloc (mb, 0);
1486 /* if target != null */
1487 mono_mb_emit_ldloc (mb, 0);
1488 mono_mb_emit_byte (mb, CEE_BRFALSE);
1490 mono_mb_emit_i4 (mb, 0);
1492 /* then call this->method_ptr nonstatic */
1493 mono_mb_emit_ldloc (mb, 0);
1494 for (i = 0; i < sig->param_count; ++i)
1495 mono_mb_emit_ldarg (mb, i + 1);
1496 mono_mb_emit_ldarg (mb, 0);
1497 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1498 mono_mb_emit_byte (mb, CEE_LDIND_I );
1499 mono_mb_emit_byte (mb, CEE_CALLI);
1500 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
1502 mono_mb_emit_byte (mb, CEE_BR);
1504 mono_mb_emit_i4 (mb, 0);
1506 /* else [target == null] call this->method_ptr static */
1507 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1509 for (i = 0; i < sig->param_count; ++i)
1510 mono_mb_emit_ldarg (mb, i + 1);
1511 mono_mb_emit_ldarg (mb, 0);
1512 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1513 mono_mb_emit_byte (mb, CEE_LDIND_I );
1514 mono_mb_emit_byte (mb, CEE_CALLI);
1515 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, static_sig));
1518 mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
1519 mono_mb_emit_byte (mb, CEE_RET);
1521 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1524 g_hash_table_insert (cache, sig, res);
1530 * generates IL code for the runtime invoke function
1531 * MonoObject *runtime_invoke (MonoObject *this, void **params, MonoObject **exc)
1533 * we also catch exceptions if exc != null
1536 mono_marshal_get_runtime_invoke (MonoMethod *method)
1538 MonoMethodSignature *sig, *csig;
1539 MonoExceptionClause *clause;
1540 MonoMethodHeader *header;
1541 MonoMethodBuilder *mb;
1544 static MonoString *string_dummy = NULL;
1545 int i, pos, sigsize;
1549 cache = method->klass->image->runtime_invoke_cache;
1550 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1553 /* to make it work with our special string constructors */
1555 string_dummy = mono_string_new_wrapper ("dummy");
1557 sig = method->signature;
1559 sigsize = sizeof (MonoMethodSignature) + 3 * sizeof (MonoType *);
1560 csig = g_malloc0 (sigsize);
1562 csig->param_count = 3;
1563 csig->ret = &mono_defaults.object_class->byval_arg;
1564 csig->params [0] = &mono_defaults.object_class->byval_arg;
1565 csig->params [1] = &mono_defaults.int_class->byval_arg;
1566 csig->params [2] = &mono_defaults.int_class->byval_arg;
1568 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_RUNTIME_INVOKE);
1570 /* allocate local 0 (object) tmp */
1571 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1572 /* allocate local 1 (object) exc */
1573 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1575 /* cond set *exc to null */
1576 mono_mb_emit_byte (mb, CEE_LDARG_2);
1577 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
1578 mono_mb_emit_byte (mb, 3);
1579 mono_mb_emit_byte (mb, CEE_LDARG_2);
1580 mono_mb_emit_byte (mb, CEE_LDNULL);
1581 mono_mb_emit_byte (mb, CEE_STIND_I);
1584 if (method->string_ctor) {
1585 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1586 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1587 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, string_dummy));
1589 mono_mb_emit_ldarg (mb, 0);
1590 if (method->klass->valuetype) {
1591 mono_mb_emit_byte (mb, CEE_UNBOX);
1592 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method->klass));
1597 for (i = 0; i < sig->param_count; i++) {
1598 MonoType *t = sig->params [i];
1601 mono_mb_emit_ldarg (mb, 1);
1603 mono_mb_emit_icon (mb, sizeof (gpointer) * i);
1604 mono_mb_emit_byte (mb, CEE_ADD);
1606 mono_mb_emit_byte (mb, CEE_LDIND_I);
1611 type = sig->params [i]->type;
1615 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1617 case MONO_TYPE_BOOLEAN:
1619 mono_mb_emit_byte (mb, CEE_LDIND_U1);
1622 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1625 case MONO_TYPE_CHAR:
1626 mono_mb_emit_byte (mb, CEE_LDIND_U2);
1630 mono_mb_emit_byte (mb, CEE_LDIND_I);
1633 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1636 mono_mb_emit_byte (mb, CEE_LDIND_U4);
1639 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1642 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1646 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1648 case MONO_TYPE_STRING:
1649 case MONO_TYPE_CLASS:
1650 case MONO_TYPE_ARRAY:
1652 case MONO_TYPE_SZARRAY:
1653 case MONO_TYPE_OBJECT:
1656 case MONO_TYPE_VALUETYPE:
1657 if (t->data.klass->enumtype) {
1658 type = t->data.klass->enum_basetype->type;
1661 mono_mb_emit_byte (mb, CEE_LDOBJ);
1662 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, t->data.klass));
1665 g_assert_not_reached ();
1669 if (method->string_ctor) {
1670 MonoMethodSignature *strsig;
1672 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1673 strsig = g_memdup (sig, sigsize);
1674 strsig->ret = &mono_defaults.string_class->byval_arg;
1676 mono_mb_emit_managed_call (mb, method, strsig);
1678 mono_mb_emit_managed_call (mb, method, NULL);
1680 if (sig->ret->byref) {
1682 g_assert_not_reached ();
1686 switch (sig->ret->type) {
1687 case MONO_TYPE_VOID:
1688 if (!method->string_ctor)
1689 mono_mb_emit_byte (mb, CEE_LDNULL);
1691 case MONO_TYPE_BOOLEAN:
1692 case MONO_TYPE_CHAR:
1705 case MONO_TYPE_VALUETYPE:
1706 /* box value types */
1707 mono_mb_emit_byte (mb, CEE_BOX);
1708 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (sig->ret)));
1710 case MONO_TYPE_STRING:
1711 case MONO_TYPE_CLASS:
1712 case MONO_TYPE_ARRAY:
1713 case MONO_TYPE_SZARRAY:
1714 case MONO_TYPE_OBJECT:
1719 g_assert_not_reached ();
1722 mono_mb_emit_stloc (mb, 0);
1724 mono_mb_emit_byte (mb, CEE_LEAVE);
1726 mono_mb_emit_i4 (mb, 0);
1728 clause = g_new0 (MonoExceptionClause, 1);
1729 clause->flags = MONO_EXCEPTION_CLAUSE_FILTER;
1730 clause->try_len = mb->pos;
1733 clause->token_or_filter = mb->pos;
1735 mono_mb_emit_byte (mb, CEE_POP);
1736 mono_mb_emit_byte (mb, CEE_LDARG_2);
1737 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
1738 mono_mb_emit_byte (mb, CEE_PREFIX1);
1739 mono_mb_emit_byte (mb, CEE_CGT_UN);
1740 mono_mb_emit_byte (mb, CEE_PREFIX1);
1741 mono_mb_emit_byte (mb, CEE_ENDFILTER);
1743 clause->handler_offset = mb->pos;
1746 /* store exception */
1747 mono_mb_emit_stloc (mb, 1);
1749 mono_mb_emit_byte (mb, CEE_LDARG_2);
1750 mono_mb_emit_ldloc (mb, 1);
1751 mono_mb_emit_byte (mb, CEE_STIND_I);
1753 mono_mb_emit_byte (mb, CEE_LEAVE);
1754 mono_mb_emit_i4 (mb, 0);
1756 clause->handler_len = mb->pos - clause->handler_offset;
1759 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1760 mono_mb_emit_ldloc (mb, 0);
1761 mono_mb_emit_byte (mb, CEE_RET);
1763 res = mono_mb_create_method (mb, csig, sig->param_count + 16);
1766 header = ((MonoMethodNormal *)res)->header;
1767 header->num_clauses = 1;
1768 header->clauses = clause;
1770 g_hash_table_insert (cache, method, res);
1776 * generates IL code to call managed methods from unmanaged code
1779 mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this)
1781 MonoMethodSignature *sig, *csig;
1782 MonoMethodBuilder *mb;
1786 int i, pos, sigsize, *tmp_locals;
1788 g_assert (method != NULL);
1789 g_assert (!method->signature->pinvoke);
1791 cache = method->klass->image->managed_wrapper_cache;
1792 if (!this && (res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1796 /* fime: howto free that memory ? */
1799 sig = method->signature;
1801 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_NATIVE_TO_MANAGED);
1803 /* allocate local 0 (pointer) src_ptr */
1804 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1805 /* allocate local 1 (pointer) dst_ptr */
1806 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1807 /* allocate local 2 (boolean) delete_old */
1808 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
1810 mono_mb_emit_byte (mb, CEE_LDNULL);
1811 mono_mb_emit_byte (mb, CEE_STLOC_2);
1813 /* we copy the signature, so that we can modify it */
1814 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1815 csig = g_memdup (sig, sigsize);
1819 /* fixme: howto handle this ? */
1823 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1824 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1825 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, this));
1830 g_assert_not_reached ();
1835 /* we first do all conversions */
1836 tmp_locals = alloca (sizeof (int) * sig->param_count);
1837 for (i = 0; i < sig->param_count; i ++) {
1838 MonoType *t = sig->params [i];
1843 case MONO_TYPE_VALUETYPE:
1845 klass = sig->params [i]->data.klass;
1846 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
1847 klass->blittable || klass->enumtype)
1850 tmp_locals [i] = mono_mb_add_local (mb, &klass->byval_arg);
1853 mono_mb_emit_ldarg (mb, i);
1855 mono_mb_emit_ldarg_addr (mb, i);
1856 mono_mb_emit_byte (mb, CEE_STLOC_0);
1859 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1860 mono_mb_emit_byte (mb, CEE_BRFALSE);
1862 mono_mb_emit_i4 (mb, 0);
1865 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
1866 mono_mb_emit_byte (mb, CEE_STLOC_1);
1868 /* emit valuetype convnversion code code */
1869 emit_struct_conv (mb, klass, TRUE);
1872 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1874 case MONO_TYPE_STRING:
1878 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1879 csig->params [i] = &mono_defaults.int_class->byval_arg;
1881 mono_mb_emit_ldarg (mb, i);
1882 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1883 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1884 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
1885 mono_mb_emit_stloc (mb, tmp_locals [i]);
1887 case MONO_TYPE_ARRAY:
1888 case MONO_TYPE_SZARRAY:
1892 klass = mono_class_from_mono_type (t);
1894 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1895 csig->params [i] = &mono_defaults.int_class->byval_arg;
1897 g_warning ("array marshaling not implemented");
1898 g_assert_not_reached ();
1903 for (i = 0; i < sig->param_count; i++) {
1904 MonoType *t = sig->params [i];
1907 case MONO_TYPE_BOOLEAN:
1921 mono_mb_emit_ldarg (mb, i);
1923 case MONO_TYPE_STRING:
1925 mono_mb_emit_ldarg (mb, i);
1927 g_assert (tmp_locals [i]);
1928 mono_mb_emit_ldloc (mb, tmp_locals [i]);
1931 case MONO_TYPE_CLASS:
1932 case MONO_TYPE_ARRAY:
1933 case MONO_TYPE_SZARRAY:
1934 case MONO_TYPE_OBJECT:
1935 /* fixme: conversions ? */
1936 mono_mb_emit_ldarg (mb, i);
1938 case MONO_TYPE_VALUETYPE:
1939 klass = sig->params [i]->data.klass;
1940 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
1941 klass->blittable || klass->enumtype) {
1942 mono_mb_emit_ldarg (mb, i);
1946 g_assert (tmp_locals [i]);
1948 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
1950 mono_mb_emit_ldloc (mb, tmp_locals [i]);
1953 g_warning ("type 0x%02x unknown", t->type);
1954 g_assert_not_reached ();
1958 mono_mb_emit_managed_call (mb, method, NULL);
1960 if (!sig->ret->byref) {
1961 switch (sig->ret->type) {
1962 case MONO_TYPE_VOID:
1963 case MONO_TYPE_BOOLEAN:
1977 mono_mb_emit_byte (mb, CEE_RET);
1979 case MONO_TYPE_STRING:
1980 csig->ret = &mono_defaults.int_class->byval_arg;
1982 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1983 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1984 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
1985 mono_mb_emit_byte (mb, CEE_RET);
1987 case MONO_TYPE_VALUETYPE: {
1989 klass = sig->ret->data.klass;
1990 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
1991 klass->blittable || klass->enumtype)
1994 /* load pointer to returned value type */
1995 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1996 mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
1998 /* store the address of the source into local variable 0 */
1999 mono_mb_emit_byte (mb, CEE_STLOC_0);
2000 /* allocate space for the native struct and
2001 * store the address into dst_ptr */
2002 tmp = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2004 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2005 mono_mb_emit_byte (mb, CEE_PREFIX1);
2006 mono_mb_emit_byte (mb, CEE_LOCALLOC);
2007 mono_mb_emit_byte (mb, CEE_STLOC_1);
2008 mono_mb_emit_byte (mb, CEE_LDLOC_1);
2009 mono_mb_emit_stloc (mb, tmp);
2011 /* emit valuetype conversion code */
2012 emit_struct_conv (mb, klass, FALSE);
2013 mono_mb_emit_ldloc (mb, tmp);
2014 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2015 mono_mb_emit_byte (mb, CEE_MONO_RETOBJ);
2016 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2020 g_warning ("return type 0x%02x unknown", sig->ret->type);
2021 g_assert_not_reached ();
2024 mono_mb_emit_byte (mb, CEE_RET);
2027 res = mono_mb_create_method (mb, csig, sig->param_count + 16);
2031 g_hash_table_insert (cache, method, res);
2037 * mono_marshal_get_ldfld_wrapper:
2038 * @type: the type of the field
2040 * This method generates a function which can be use to load a field with type
2041 * @type from an object. The generated function has the following signature:
2042 * <@type> ldfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset)
2045 mono_marshal_get_ldfld_wrapper (MonoType *type)
2047 MonoMethodSignature *sig, *csig;
2048 MonoMethodBuilder *mb;
2051 static GHashTable *ldfld_hash = NULL;
2056 ldfld_hash = g_hash_table_new (NULL, NULL);
2062 if (type->type == MONO_TYPE_SZARRAY) {
2063 klass = mono_defaults.array_class;
2064 } else if (type->type == MONO_TYPE_VALUETYPE) {
2065 klass = type->data.klass;
2066 if (klass->enumtype) {
2067 t = klass->enum_basetype->type;
2068 klass = mono_class_from_mono_type (klass->enum_basetype);
2070 } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
2071 t == MONO_TYPE_CLASS) {
2072 klass = mono_defaults.object_class;
2073 } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
2074 klass = mono_defaults.int_class;
2076 klass = mono_class_from_mono_type (type);
2079 klass = mono_defaults.int_class;
2082 if ((res = g_hash_table_lookup (ldfld_hash, klass)))
2085 name = g_strdup_printf ("__ldfld_wrapper_%s.%s", klass->name_space, klass->name);
2086 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_LDFLD);
2089 mb->method->save_lmf = 1;
2091 sig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
2092 sig->params [0] = &mono_defaults.object_class->byval_arg;
2093 sig->params [1] = &mono_defaults.int_class->byval_arg;
2094 sig->params [2] = &mono_defaults.int_class->byval_arg;
2095 sig->params [3] = &mono_defaults.int_class->byval_arg;
2096 sig->ret = &klass->byval_arg;
2098 mono_mb_emit_ldarg (mb, 0);
2099 pos0 = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
2101 mono_mb_emit_ldarg (mb, 0);
2102 mono_mb_emit_ldarg (mb, 1);
2103 mono_mb_emit_ldarg (mb, 2);
2105 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
2106 csig->params [0] = &mono_defaults.object_class->byval_arg;
2107 csig->params [1] = &mono_defaults.int_class->byval_arg;
2108 csig->params [2] = &mono_defaults.int_class->byval_arg;
2109 csig->ret = &klass->this_arg;
2112 mono_mb_emit_native_call (mb, csig, mono_load_remote_field_new);
2114 if (klass->valuetype) {
2115 mono_mb_emit_byte (mb, CEE_UNBOX);
2116 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2117 mono_mb_emit_byte (mb, CEE_BR);
2119 mono_mb_emit_i4 (mb, 0);
2121 mono_mb_emit_byte (mb, CEE_RET);
2125 mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
2127 mono_mb_emit_ldarg (mb, 0);
2128 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2129 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2130 mono_mb_emit_ldarg (mb, 3);
2131 mono_mb_emit_byte (mb, CEE_ADD);
2133 if (klass->valuetype)
2134 mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
2139 case MONO_TYPE_BOOLEAN:
2140 mono_mb_emit_byte (mb, CEE_LDIND_I1);
2142 case MONO_TYPE_CHAR:
2145 mono_mb_emit_byte (mb, CEE_LDIND_I2);
2149 mono_mb_emit_byte (mb, CEE_LDIND_I4);
2153 mono_mb_emit_byte (mb, CEE_LDIND_I8);
2156 mono_mb_emit_byte (mb, CEE_LDIND_R4);
2159 mono_mb_emit_byte (mb, CEE_LDIND_R8);
2161 case MONO_TYPE_ARRAY:
2163 case MONO_TYPE_FNPTR:
2164 case MONO_TYPE_SZARRAY:
2165 case MONO_TYPE_OBJECT:
2166 case MONO_TYPE_CLASS:
2167 case MONO_TYPE_STRING:
2170 mono_mb_emit_byte (mb, CEE_LDIND_I);
2172 case MONO_TYPE_VALUETYPE:
2173 g_assert (!klass->enumtype);
2174 mono_mb_emit_byte (mb, CEE_LDOBJ);
2175 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2178 g_warning ("type %x not implemented", type->type);
2179 g_assert_not_reached ();
2182 mono_mb_emit_byte (mb, CEE_RET);
2184 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
2187 g_hash_table_insert (ldfld_hash, klass, res);
2193 * mono_marshal_get_stfld_wrapper:
2194 * @type: the type of the field
2196 * This method generates a function which can be use to store a field with type
2197 * @type. The generated function has the following signature:
2198 * void stfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset, <@type> val)
2201 mono_marshal_get_stfld_wrapper (MonoType *type)
2203 MonoMethodSignature *sig, *csig;
2204 MonoMethodBuilder *mb;
2207 static GHashTable *stfld_hash = NULL;
2212 stfld_hash = g_hash_table_new (NULL, NULL);
2217 if (type->type == MONO_TYPE_SZARRAY) {
2218 klass = mono_defaults.array_class;
2219 } else if (type->type == MONO_TYPE_VALUETYPE) {
2220 klass = type->data.klass;
2221 if (klass->enumtype) {
2222 t = klass->enum_basetype->type;
2223 klass = mono_class_from_mono_type (klass->enum_basetype);
2225 } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
2226 t == MONO_TYPE_CLASS) {
2227 klass = mono_defaults.object_class;
2228 } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
2229 klass = mono_defaults.int_class;
2231 klass = mono_class_from_mono_type (type);
2234 klass = mono_defaults.int_class;
2237 if ((res = g_hash_table_lookup (stfld_hash, klass)))
2240 name = g_strdup_printf ("__stfld_wrapper_%s.%s", klass->name_space, klass->name);
2241 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_STFLD);
2244 mb->method->save_lmf = 1;
2246 sig = mono_metadata_signature_alloc (mono_defaults.corlib, 5);
2247 sig->params [0] = &mono_defaults.object_class->byval_arg;
2248 sig->params [1] = &mono_defaults.int_class->byval_arg;
2249 sig->params [2] = &mono_defaults.int_class->byval_arg;
2250 sig->params [3] = &mono_defaults.int_class->byval_arg;
2251 sig->params [4] = &klass->byval_arg;
2252 sig->ret = &mono_defaults.void_class->byval_arg;
2254 mono_mb_emit_ldarg (mb, 0);
2255 pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
2257 mono_mb_emit_ldarg (mb, 0);
2258 mono_mb_emit_ldarg (mb, 1);
2259 mono_mb_emit_ldarg (mb, 2);
2260 mono_mb_emit_ldarg (mb, 4);
2262 if (klass->valuetype) {
2263 mono_mb_emit_byte (mb, CEE_BOX);
2264 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2267 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
2268 csig->params [0] = &mono_defaults.object_class->byval_arg;
2269 csig->params [1] = &mono_defaults.int_class->byval_arg;
2270 csig->params [2] = &mono_defaults.int_class->byval_arg;
2271 csig->params [3] = &klass->this_arg;
2272 csig->ret = &mono_defaults.void_class->byval_arg;
2275 mono_mb_emit_native_call (mb, csig, mono_store_remote_field_new);
2277 mono_mb_emit_byte (mb, CEE_RET);
2279 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2281 mono_mb_emit_ldarg (mb, 0);
2282 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2283 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2284 mono_mb_emit_ldarg (mb, 3);
2285 mono_mb_emit_byte (mb, CEE_ADD);
2286 mono_mb_emit_ldarg (mb, 4);
2291 case MONO_TYPE_BOOLEAN:
2292 mono_mb_emit_byte (mb, CEE_STIND_I1);
2294 case MONO_TYPE_CHAR:
2297 mono_mb_emit_byte (mb, CEE_STIND_I2);
2301 mono_mb_emit_byte (mb, CEE_STIND_I4);
2305 mono_mb_emit_byte (mb, CEE_STIND_I8);
2308 mono_mb_emit_byte (mb, CEE_STIND_R4);
2311 mono_mb_emit_byte (mb, CEE_STIND_R8);
2313 case MONO_TYPE_ARRAY:
2315 case MONO_TYPE_FNPTR:
2316 case MONO_TYPE_SZARRAY:
2317 case MONO_TYPE_OBJECT:
2318 case MONO_TYPE_CLASS:
2319 case MONO_TYPE_STRING:
2322 mono_mb_emit_byte (mb, CEE_STIND_I);
2324 case MONO_TYPE_VALUETYPE:
2325 g_assert (!klass->enumtype);
2326 mono_mb_emit_byte (mb, CEE_STOBJ);
2327 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2330 g_warning ("type %x not implemented", type->type);
2331 g_assert_not_reached ();
2334 mono_mb_emit_byte (mb, CEE_RET);
2336 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
2339 g_hash_table_insert (stfld_hash, klass, res);
2345 * generates IL code for the icall wrapper (the generated method
2346 * calls the unamnaged code in func)
2349 mono_marshal_get_icall_wrapper (MonoMethodSignature *sig, const char *name, gconstpointer func)
2351 MonoMethodSignature *csig;
2352 MonoMethodBuilder *mb;
2356 g_assert (sig->pinvoke);
2358 mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_MANAGED_TO_NATIVE);
2360 mb->method->save_lmf = 1;
2362 /* we copy the signature, so that we can modify it */
2363 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
2366 mono_mb_emit_byte (mb, CEE_LDARG_0);
2368 for (i = 0; i < sig->param_count; i++)
2369 mono_mb_emit_ldarg (mb, i + sig->hasthis);
2371 mono_mb_emit_native_call (mb, sig, func);
2373 mono_mb_emit_byte (mb, CEE_RET);
2375 csig = g_memdup (sig, sigsize);
2378 res = mono_mb_create_method (mb, csig, csig->param_count + 16);
2385 * generates IL code for the pinvoke wrapper (the generated method
2386 * calls the unamnage code in method->addr)
2389 mono_marshal_get_native_wrapper (MonoMethod *method)
2391 MonoMethodSignature *sig, *csig;
2392 MonoMethodBuilder *mb;
2393 MonoMarshalSpec **mspecs;
2397 gboolean pinvoke = FALSE;
2398 int i, pos, argnum, *tmp_locals;
2401 g_assert (method != NULL);
2402 g_assert (method->signature->pinvoke);
2404 cache = method->klass->image->native_wrapper_cache;
2405 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
2408 sig = method->signature;
2409 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
2411 if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
2412 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2415 mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_MANAGED_TO_NATIVE);
2417 mb->method->save_lmf = 1;
2419 if (pinvoke && !method->addr)
2420 mono_lookup_pinvoke_call (method);
2422 if (!method->addr) {
2423 mono_mb_emit_exception (mb);
2424 csig = g_memdup (sig, sigsize);
2426 res = mono_mb_create_method (mb, csig, csig->param_count + 16);
2428 g_hash_table_insert (cache, method, res);
2432 /* internal calls: we simply push all arguments and call the method (no conversions) */
2433 if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
2435 /* hack - string constructors returns a value */
2436 if (method->string_ctor) {
2437 csig = g_memdup (sig, sigsize);
2438 csig->ret = &mono_defaults.string_class->byval_arg;
2443 mono_mb_emit_byte (mb, CEE_LDARG_0);
2445 for (i = 0; i < sig->param_count; i++)
2446 mono_mb_emit_ldarg (mb, i + sig->hasthis);
2448 g_assert (method->addr);
2449 mono_mb_emit_native_call (mb, csig, method->addr);
2451 mono_mb_emit_byte (mb, CEE_RET);
2453 csig = g_memdup (csig, sigsize);
2455 res = mono_mb_create_method (mb, csig, csig->param_count + 16);
2457 g_hash_table_insert (cache, method, res);
2463 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
2464 mono_method_get_marshal_info (method, mspecs);
2466 /* pinvoke: we need to convert the arguments if necessary */
2468 /* we copy the signature, so that we can set pinvoke to 0 */
2469 csig = g_memdup (sig, sigsize);
2472 /* we allocate local for use with emit_struct_conv() */
2473 /* allocate local 0 (pointer) src_ptr */
2474 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2475 /* allocate local 1 (pointer) dst_ptr */
2476 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2477 /* allocate local 2 (boolean) delete_old */
2478 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2480 /* delete_old = FALSE */
2481 mono_mb_emit_icon (mb, 0);
2482 mono_mb_emit_byte (mb, CEE_STLOC_2);
2484 if (sig->ret->type != MONO_TYPE_VOID) {
2485 /* allocate local 3 to store the return value */
2486 mono_mb_add_local (mb, sig->ret);
2489 /* we first do all conversions */
2490 tmp_locals = alloca (sizeof (int) * sig->param_count);
2491 for (i = 0; i < sig->param_count; i ++) {
2492 MonoType *t = sig->params [i];
2493 MonoMarshalSpec *spec = mspecs [i + 1];
2495 argnum = i + sig->hasthis;
2499 case MONO_TYPE_VALUETYPE:
2500 klass = t->data.klass;
2502 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2503 klass->blittable || klass->enumtype)
2506 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2508 /* store the address of the source into local variable 0 */
2510 mono_mb_emit_ldarg (mb, argnum);
2512 mono_mb_emit_ldarg_addr (mb, argnum);
2514 mono_mb_emit_byte (mb, CEE_STLOC_0);
2516 /* allocate space for the native struct and
2517 * store the address into local variable 1 (dest) */
2518 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2519 mono_mb_emit_byte (mb, CEE_PREFIX1);
2520 mono_mb_emit_byte (mb, CEE_LOCALLOC);
2521 mono_mb_emit_stloc (mb, tmp_locals [i]);
2524 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2525 mono_mb_emit_byte (mb, CEE_BRFALSE);
2527 mono_mb_emit_i4 (mb, 0);
2531 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2532 mono_mb_emit_byte (mb, CEE_STLOC_1);
2534 /* emit valuetype conversion code */
2535 emit_struct_conv (mb, klass, FALSE);
2538 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2540 case MONO_TYPE_STRING:
2544 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2545 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2547 mono_mb_emit_ldarg (mb, argnum);
2548 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2549 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2552 switch (spec->native) {
2553 case MONO_NATIVE_LPWSTR:
2554 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPWSTR);
2556 case MONO_NATIVE_LPSTR:
2557 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
2560 g_warning ("marshalling conversion %d not implemented", spec->native);
2561 g_assert_not_reached ();
2564 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
2567 mono_mb_emit_stloc (mb, tmp_locals [i]);
2569 case MONO_TYPE_CLASS:
2573 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2574 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2576 if (t->data.klass->delegate) {
2577 mono_mb_emit_ldarg (mb, argnum);
2578 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2579 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2580 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_DEL_FTN);
2581 mono_mb_emit_stloc (mb, tmp_locals [i]);
2582 } else if (t->data.klass == mono_defaults.stringbuilder_class) {
2583 mono_mb_emit_ldarg (mb, argnum);
2584 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2585 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2586 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_SB_LPSTR);
2587 mono_mb_emit_stloc (mb, tmp_locals [i]);
2589 mono_mb_emit_ldarg (mb, argnum);
2590 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2591 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2592 /* fixme: convert to what ? */
2593 mono_mb_emit_stloc (mb, tmp_locals [i]);
2597 case MONO_TYPE_OBJECT:
2600 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2601 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2603 * FIXME: this may need special handling to inspect the type
2606 mono_mb_emit_ldarg (mb, argnum);
2607 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2608 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2609 /* fixme: convert to what ? */
2610 mono_mb_emit_stloc (mb, tmp_locals [i]);
2612 case MONO_TYPE_ARRAY:
2613 case MONO_TYPE_SZARRAY:
2617 klass = mono_class_from_mono_type (t);
2619 csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2620 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2622 mono_mb_emit_ldarg (mb, argnum);
2623 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2624 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2625 if (klass->element_class == mono_defaults.string_class)
2626 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STRARRAY_STRLPARRAY);
2628 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_ARRAY_LPARRAY);
2629 mono_mb_emit_stloc (mb, tmp_locals [i]);
2634 /* push all arguments */
2637 mono_mb_emit_byte (mb, CEE_LDARG_0);
2639 for (i = 0; i < sig->param_count; i++) {
2640 MonoType *t = sig->params [i];
2642 argnum = i + sig->hasthis;
2645 case MONO_TYPE_BOOLEAN:
2647 g_warning ("byref boolean marshalling not inplemented");
2648 mono_mb_emit_ldarg (mb, argnum);
2663 mono_mb_emit_ldarg (mb, argnum);
2665 case MONO_TYPE_VALUETYPE:
2666 klass = sig->params [i]->data.klass;
2667 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2668 klass->blittable || klass->enumtype) {
2669 mono_mb_emit_ldarg (mb, argnum);
2672 g_assert (tmp_locals [i]);
2673 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2675 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2676 mono_mb_emit_byte (mb, CEE_MONO_LDNATIVEOBJ);
2677 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2680 case MONO_TYPE_STRING:
2682 mono_mb_emit_ldarg (mb, argnum);
2684 g_assert (tmp_locals [i]);
2685 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2688 case MONO_TYPE_CLASS:
2689 case MONO_TYPE_OBJECT:
2691 mono_mb_emit_ldarg (mb, argnum);
2693 g_assert (tmp_locals [i]);
2694 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2697 case MONO_TYPE_CHAR:
2698 /* fixme: dont know how to marshal that. We cant simply
2699 * convert it to a one byte UTF8 character, because an
2700 * unicode character may need more that one byte in UTF8 */
2701 mono_mb_emit_ldarg (mb, argnum);
2703 case MONO_TYPE_ARRAY:
2704 case MONO_TYPE_SZARRAY:
2706 mono_mb_emit_ldarg (mb, argnum);
2708 g_assert (tmp_locals [i]);
2709 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2712 case MONO_TYPE_TYPEDBYREF:
2713 case MONO_TYPE_FNPTR:
2715 g_warning ("type 0x%02x unknown", t->type);
2716 g_assert_not_reached ();
2720 /* call the native method */
2721 mono_mb_emit_native_call (mb, csig, method->addr);
2723 /* return the result */
2725 /* we need to convert byref arguments back and free string arrays */
2726 for (i = 0; i < sig->param_count; i++) {
2727 MonoType *t = sig->params [i];
2729 argnum = i + sig->hasthis;
2732 case MONO_TYPE_CLASS:
2733 case MONO_TYPE_OBJECT:
2737 if (t->data.klass == mono_defaults.stringbuilder_class) {
2738 mono_mb_emit_ldarg (mb, argnum);
2739 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2740 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2741 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
2742 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_SB);
2743 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2744 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2745 mono_mb_emit_byte (mb, CEE_MONO_FREE);
2748 case MONO_TYPE_VALUETYPE:
2752 klass = t->data.klass;
2753 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2754 klass->blittable || klass->enumtype)
2757 /* dst = argument */
2758 mono_mb_emit_ldarg (mb, argnum);
2759 mono_mb_emit_byte (mb, CEE_STLOC_1);
2761 mono_mb_emit_byte (mb, CEE_LDLOC_1);
2762 mono_mb_emit_byte (mb, CEE_BRFALSE);
2764 mono_mb_emit_i4 (mb, 0);
2766 /* src = tmp_locals [i] */
2767 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2768 mono_mb_emit_byte (mb, CEE_STLOC_0);
2770 /* emit valuetype conversion code */
2771 emit_struct_conv (mb, klass, TRUE);
2773 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2775 case MONO_TYPE_SZARRAY:
2779 klass = mono_class_from_mono_type (t);
2781 if (klass->element_class == mono_defaults.string_class) {
2782 g_assert (tmp_locals [i]);
2784 mono_mb_emit_ldarg (mb, argnum);
2785 mono_mb_emit_byte (mb, CEE_BRFALSE);
2787 mono_mb_emit_i4 (mb, 0);
2789 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2790 mono_mb_emit_ldarg (mb, argnum);
2791 mono_mb_emit_byte (mb, CEE_LDLEN);
2792 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2793 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
2794 mono_mb_emit_byte (mb, MONO_MARSHAL_FREE_ARRAY);
2796 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2803 if (!sig->ret->byref) {
2804 MonoMarshalSpec *spec = mspecs [0];
2805 type = sig->ret->type;
2809 case MONO_TYPE_VOID:
2823 /* no conversions necessary */
2825 case MONO_TYPE_BOOLEAN:
2826 /* maybe we need to make sure that it fits within 8 bits */
2828 case MONO_TYPE_VALUETYPE: {
2831 klass = sig->ret->data.klass;
2832 if (klass->enumtype) {
2833 type = sig->ret->data.klass->enum_basetype->type;
2837 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2841 tmp = mono_mb_add_local (mb, sig->ret);
2843 /* load pointer to returned value type */
2844 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2845 mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
2846 /* store the address of the source into local variable 0 */
2847 mono_mb_emit_byte (mb, CEE_STLOC_0);
2849 mono_mb_emit_ldloc_addr (mb, tmp);
2850 mono_mb_emit_byte (mb, CEE_STLOC_1);
2852 /* emit valuetype conversion code */
2853 emit_struct_conv (mb, sig->ret->data.klass, TRUE);
2855 mono_mb_emit_ldloc (mb, tmp);
2858 case MONO_TYPE_STRING:
2859 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2860 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2862 switch (spec->native) {
2863 case MONO_NATIVE_LPWSTR:
2864 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPWSTR_STR);
2867 g_warning ("marshalling conversion not implemented");
2868 g_assert_not_reached ();
2871 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
2874 case MONO_TYPE_ARRAY:
2875 case MONO_TYPE_SZARRAY:
2876 case MONO_TYPE_CLASS:
2877 case MONO_TYPE_OBJECT:
2878 /* fixme: we need conversions here */
2880 case MONO_TYPE_CHAR:
2881 /* fixme: we need conversions here */
2883 case MONO_TYPE_TYPEDBYREF:
2884 case MONO_TYPE_FNPTR:
2886 g_warning ("return type 0x%02x unknown", sig->ret->type);
2887 g_assert_not_reached ();
2891 mono_mb_emit_byte (mb, CEE_RET);
2893 csig = g_memdup (sig, sigsize);
2895 res = mono_mb_create_method (mb, csig, csig->param_count + 16);
2898 g_hash_table_insert (cache, method, res);
2900 for (i = sig->param_count; i >= 0; i--)
2901 g_free (mspecs [i]);
2908 * generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld)
2911 mono_marshal_get_struct_to_ptr (MonoClass *klass)
2913 MonoMethodBuilder *mb;
2914 static MonoMethod *stoptr = NULL;
2917 g_assert (klass != NULL);
2919 if (klass->str_to_ptr)
2920 return klass->str_to_ptr;
2923 stoptr = mono_find_method_by_name (mono_defaults.marshal_class, "StructureToPtr", 3);
2926 mb = mono_mb_new (klass, stoptr->name, MONO_WRAPPER_UNKNOWN);
2928 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable) {
2929 mono_mb_emit_byte (mb, CEE_LDARG_1);
2930 mono_mb_emit_byte (mb, CEE_LDARG_0);
2931 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
2932 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
2933 mono_mb_emit_byte (mb, CEE_PREFIX1);
2934 mono_mb_emit_byte (mb, CEE_CPBLK);
2937 /* allocate local 0 (pointer) src_ptr */
2938 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2939 /* allocate local 1 (pointer) dst_ptr */
2940 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2941 /* allocate local 2 (boolean) delete_old */
2942 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2943 mono_mb_emit_byte (mb, CEE_LDARG_2);
2944 mono_mb_emit_byte (mb, CEE_STLOC_2);
2946 /* initialize src_ptr to point to the start of object data */
2947 mono_mb_emit_byte (mb, CEE_LDARG_0);
2948 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
2949 mono_mb_emit_byte (mb, CEE_STLOC_0);
2951 /* initialize dst_ptr */
2952 mono_mb_emit_byte (mb, CEE_LDARG_1);
2953 mono_mb_emit_byte (mb, CEE_STLOC_1);
2955 emit_struct_conv (mb, klass, FALSE);
2958 mono_mb_emit_byte (mb, CEE_RET);
2960 res = mono_mb_create_method (mb, stoptr->signature, 0);
2963 klass->str_to_ptr = res;
2968 * generates IL code for PtrToStructure (IntPtr src, object structure)
2971 mono_marshal_get_ptr_to_struct (MonoClass *klass)
2973 MonoMethodBuilder *mb;
2974 static MonoMethod *ptostr = NULL;
2977 g_assert (klass != NULL);
2979 if (klass->ptr_to_str)
2980 return klass->ptr_to_str;
2983 ptostr = mono_find_method_by_name (mono_defaults.marshal_class, "PtrToStructure", 2);
2986 mb = mono_mb_new (klass, ptostr->name, MONO_WRAPPER_UNKNOWN);
2988 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable) {
2989 mono_mb_emit_byte (mb, CEE_LDARG_1);
2990 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
2991 mono_mb_emit_byte (mb, CEE_LDARG_0);
2992 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
2993 mono_mb_emit_byte (mb, CEE_PREFIX1);
2994 mono_mb_emit_byte (mb, CEE_CPBLK);
2997 /* allocate local 0 (pointer) src_ptr */
2998 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2999 /* allocate local 1 (pointer) dst_ptr */
3000 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3002 /* initialize src_ptr to point to the start of object data */
3003 mono_mb_emit_byte (mb, CEE_LDARG_0);
3004 mono_mb_emit_byte (mb, CEE_STLOC_0);
3006 /* initialize dst_ptr */
3007 mono_mb_emit_byte (mb, CEE_LDARG_1);
3008 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3009 mono_mb_emit_byte (mb, CEE_STLOC_1);
3011 emit_struct_conv (mb, klass, TRUE);
3014 mono_mb_emit_byte (mb, CEE_RET);
3016 res = mono_mb_create_method (mb, ptostr->signature, 0);
3019 klass->ptr_to_str = res;
3023 /* FIXME: on win32 we should probably use GlobalAlloc(). */
3025 mono_marshal_alloc (gpointer size)
3027 MONO_ARCH_SAVE_REGS;
3029 return g_try_malloc ((gulong)size);
3033 mono_marshal_free (gpointer ptr)
3035 MONO_ARCH_SAVE_REGS;
3041 mono_marshal_free_array (gpointer *ptr, int size)
3045 printf ("TESTFREE %p\n", ptr);
3049 for (i = 0; i < size; i++)
3055 mono_marshal_realloc (gpointer ptr, gpointer size)
3057 MONO_ARCH_SAVE_REGS;
3059 return g_try_realloc (ptr, (gulong)size);
3063 mono_marshal_string_array (MonoArray *array)
3071 len = mono_array_length (array);
3073 result = g_malloc (sizeof (char *) * (len + 1));
3074 for (i = 0; i < len; ++i) {
3075 MonoString *s = (MonoString *)mono_array_get (array, gpointer, i);
3076 result [i] = s ? mono_string_to_utf8 (s): NULL;
3078 /* null terminate the array */
3085 ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArray *src, gint32 start_index,
3086 gpointer dest, gint32 length)
3091 MONO_ARCH_SAVE_REGS;
3093 MONO_CHECK_ARG_NULL (src);
3094 MONO_CHECK_ARG_NULL (dest);
3096 g_assert (src->obj.vtable->klass->rank == 1);
3097 g_assert (start_index >= 0);
3098 g_assert (length >= 0);
3099 g_assert (start_index + length <= mono_array_length (src));
3101 element_size = mono_array_element_size (src->obj.vtable->klass);
3103 source_addr = mono_array_addr_with_size (src, element_size, start_index);
3105 memcpy (dest, source_addr, length * element_size);
3109 ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer src, gint32 start_index,
3110 MonoArray *dest, gint32 length)
3115 MONO_ARCH_SAVE_REGS;
3117 MONO_CHECK_ARG_NULL (src);
3118 MONO_CHECK_ARG_NULL (dest);
3120 g_assert (dest->obj.vtable->klass->rank == 1);
3121 g_assert (start_index >= 0);
3122 g_assert (length >= 0);
3123 g_assert (start_index + length <= mono_array_length (dest));
3125 element_size = mono_array_element_size (dest->obj.vtable->klass);
3127 dest_addr = mono_array_addr_with_size (dest, element_size, start_index);
3129 memcpy (dest_addr, src, length * element_size);
3133 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr, gint32 offset)
3137 MONO_ARCH_SAVE_REGS;
3139 return *(gpointer*)(p + offset);
3143 ves_icall_System_Runtime_InteropServices_Marshal_ReadByte (gpointer ptr, gint32 offset)
3147 MONO_ARCH_SAVE_REGS;
3149 return *(unsigned char*)(p + offset);
3153 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt16 (gpointer ptr, gint32 offset)
3157 MONO_ARCH_SAVE_REGS;
3159 return *(gint16*)(p + offset);
3163 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt32 (gpointer ptr, gint32 offset)
3167 MONO_ARCH_SAVE_REGS;
3169 return *(gint32*)(p + offset);
3173 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt64 (gpointer ptr, gint32 offset)
3177 MONO_ARCH_SAVE_REGS;
3179 return *(gint64*)(p + offset);
3183 ves_icall_System_Runtime_InteropServices_Marshal_WriteByte (gpointer ptr, gint32 offset, unsigned char val)
3187 MONO_ARCH_SAVE_REGS;
3189 *(unsigned char*)(p + offset) = val;
3193 ves_icall_System_Runtime_InteropServices_Marshal_WriteIntPtr (gpointer ptr, gint32 offset, gpointer val)
3197 MONO_ARCH_SAVE_REGS;
3199 *(gpointer*)(p + offset) = val;
3203 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt16 (gpointer ptr, gint32 offset, gint16 val)
3207 MONO_ARCH_SAVE_REGS;
3209 *(gint16*)(p + offset) = val;
3213 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt32 (gpointer ptr, gint32 offset, gint32 val)
3217 MONO_ARCH_SAVE_REGS;
3219 *(gint32*)(p + offset) = val;
3223 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt64 (gpointer ptr, gint32 offset, gint64 val)
3227 MONO_ARCH_SAVE_REGS;
3229 *(gint64*)(p + offset) = val;
3233 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (char *ptr)
3235 MONO_ARCH_SAVE_REGS;
3237 return mono_string_new (mono_domain_get (), ptr);
3241 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len (char *ptr, gint32 len)
3243 MONO_ARCH_SAVE_REGS;
3245 return mono_string_new_len (mono_domain_get (), ptr, len);
3249 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni (guint16 *ptr)
3251 MonoDomain *domain = mono_domain_get ();
3255 MONO_ARCH_SAVE_REGS;
3260 return mono_string_new_utf16 (domain, ptr, len);
3264 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len (guint16 *ptr, gint32 len)
3266 MonoDomain *domain = mono_domain_get ();
3268 MONO_ARCH_SAVE_REGS;
3270 return mono_string_new_utf16 (domain, ptr, len);
3274 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR (gpointer ptr)
3276 MONO_ARCH_SAVE_REGS;
3278 g_warning ("PtrToStringBSTR not implemented");
3279 g_assert_not_reached ();
3285 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
3287 MONO_ARCH_SAVE_REGS;
3289 return (GetLastError ());
3293 ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype)
3297 MONO_ARCH_SAVE_REGS;
3299 MONO_CHECK_ARG_NULL (rtype);
3301 klass = mono_class_from_mono_type (rtype->type);
3303 return mono_class_native_size (klass, NULL);
3307 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old)
3312 MONO_ARCH_SAVE_REGS;
3314 MONO_CHECK_ARG_NULL (obj);
3315 MONO_CHECK_ARG_NULL (dst);
3317 method = mono_marshal_get_struct_to_ptr (obj->vtable->klass);
3321 pa [2] = &delete_old;
3323 mono_runtime_invoke (method, NULL, pa, NULL);
3327 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, MonoObject *dst)
3332 MONO_ARCH_SAVE_REGS;
3334 MONO_CHECK_ARG_NULL (src);
3335 MONO_CHECK_ARG_NULL (dst);
3337 method = mono_marshal_get_ptr_to_struct (dst->vtable->klass);
3342 mono_runtime_invoke (method, NULL, pa, NULL);
3346 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer src, MonoReflectionType *type)
3348 MonoDomain *domain = mono_domain_get ();
3351 MONO_ARCH_SAVE_REGS;
3353 MONO_CHECK_ARG_NULL (src);
3354 MONO_CHECK_ARG_NULL (type);
3356 res = mono_object_new (domain, mono_class_from_mono_type (type->type));
3358 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (src, res);
3364 ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *type, MonoString *field_name)
3366 MonoMarshalType *info;
3371 MONO_ARCH_SAVE_REGS;
3373 MONO_CHECK_ARG_NULL (type);
3374 MONO_CHECK_ARG_NULL (field_name);
3376 fname = mono_string_to_utf8 (field_name);
3377 klass = mono_class_from_mono_type (type->type);
3379 info = mono_marshal_load_type_info (klass);
3381 for (i = 0; i < klass->field.count; ++i) {
3382 if (*fname == *klass->fields [i].name &&
3383 strcmp (fname, klass->fields [i].name) == 0)
3388 mono_assert (i < klass->field.count);
3390 return info->fields [i].offset;
3394 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString *string)
3396 MONO_ARCH_SAVE_REGS;
3398 return mono_string_to_utf8 (string);
3402 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni (MonoString *string)
3404 MONO_ARCH_SAVE_REGS;
3406 return g_memdup (mono_string_chars (string), mono_string_length (string)*2);
3410 mono_struct_delete_old (MonoClass *klass, char *ptr)
3412 MonoMarshalType *info;
3415 info = mono_marshal_load_type_info (klass);
3417 for (i = 0; i < info->num_fields; i++) {
3418 MonoMarshalNative ntype;
3419 MonoMarshalConv conv;
3420 MonoType *ftype = info->fields [i].field->type;
3423 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
3426 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE,
3427 klass->unicode, &conv);
3429 cpos = ptr + info->fields [i].offset;
3432 case MONO_MARSHAL_CONV_NONE:
3433 if (MONO_TYPE_ISSTRUCT (ftype)) {
3434 mono_struct_delete_old (ftype->data.klass, cpos);
3438 case MONO_MARSHAL_CONV_STR_LPWSTR:
3439 case MONO_MARSHAL_CONV_STR_LPSTR:
3440 case MONO_MARSHAL_CONV_STR_LPTSTR:
3441 case MONO_MARSHAL_CONV_STR_BSTR:
3442 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
3443 case MONO_MARSHAL_CONV_STR_TBSTR:
3444 g_free (*(gpointer *)cpos);
3453 ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure (gpointer src, MonoReflectionType *type)
3457 MONO_ARCH_SAVE_REGS;
3459 MONO_CHECK_ARG_NULL (src);
3460 MONO_CHECK_ARG_NULL (type);
3462 klass = mono_class_from_mono_type (type->type);
3464 mono_struct_delete_old (klass, (char *)src);