2 * marshal.c: Routines for marshaling complex types in P/Invoke methods.
5 * Paolo Molaro (lupus@ximian.com)
7 * (C) 2002 Ximian, Inc. http://www.ximian.com
14 #include "metadata/marshal.h"
15 #include "metadata/tabledefs.h"
16 #include "metadata/exception.h"
17 #include "metadata/appdomain.h"
18 #include "mono/metadata/debug-helpers.h"
19 #include "mono/metadata/threadpool.h"
20 #include "mono/metadata/threads.h"
21 #include "mono/metadata/monitor.h"
22 #include "mono/metadata/metadata-internals.h"
23 #include "mono/metadata/domain-internals.h"
24 #include "mono/metadata/gc-internal.h"
25 #include "mono/metadata/threads-types.h"
26 #include <mono/os/gc_wrapper.h>
30 /* #define DEBUG_RUNTIME_CODE */
32 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
36 #include "mono/cil/opcode.def"
41 struct _MonoMethodBuilder
{
45 guint32 code_size
, pos
;
50 delegate_hash_table_add (MonoDelegate
*d
);
53 emit_struct_conv (MonoMethodBuilder
*mb
, MonoClass
*klass
, gboolean to_object
);
55 #ifdef DEBUG_RUNTIME_CODE
57 indenter (MonoDisHelper
*dh
, MonoMethod
*method
, guint32 ip_offset
)
59 return g_strdup (" ");
62 static MonoDisHelper marshal_dh
= {
72 /* This mutex protects the various marshalling related caches in MonoImage */
73 static CRITICAL_SECTION marshal_mutex
;
75 /* Maps wrapper methods to the methods they wrap */
76 static MonoGHashTable
*wrapper_hash
;
78 static guint32 last_error_tls_id
;
80 static void mono_struct_delete_old (MonoClass
*klass
, char *ptr
);
81 void * mono_marshal_string_to_utf16 (MonoString
*s
);
83 static gpointer
mono_string_to_lpstr (MonoString
*string_obj
);
86 register_icall (gpointer func
, const char *name
, const char *sigstr
, gboolean save
)
88 MonoMethodSignature
*sig
= mono_create_icall_signature (sigstr
);
90 mono_register_jit_icall (func
, name
, sig
, save
);
94 mono_marshal_init (void)
96 static gboolean module_initialized
= FALSE
;
98 if (!module_initialized
) {
99 module_initialized
= TRUE
;
100 InitializeCriticalSection (&marshal_mutex
);
101 MONO_GC_REGISTER_ROOT (wrapper_hash
);
102 wrapper_hash
= mono_g_hash_table_new (NULL
, NULL
);
103 last_error_tls_id
= TlsAlloc ();
105 register_icall (mono_marshal_string_to_utf16
, "mono_marshal_string_to_utf16", "ptr obj", FALSE
);
106 register_icall (mono_string_to_utf16
, "mono_string_to_utf16", "ptr obj", FALSE
);
107 register_icall (mono_string_from_utf16
, "mono_string_from_utf16", "obj ptr", FALSE
);
108 register_icall (mono_string_new_wrapper
, "mono_string_new_wrapper", "obj ptr", FALSE
);
109 register_icall (mono_string_to_utf8
, "mono_string_to_utf8", "ptr obj", FALSE
);
110 register_icall (mono_string_to_lpstr
, "mono_string_to_lpstr", "ptr obj", FALSE
);
111 register_icall (mono_string_to_bstr
, "mono_string_to_bstr", "ptr obj", FALSE
);
112 register_icall (mono_string_to_ansibstr
, "mono_string_to_ansibstr", "ptr object", FALSE
);
113 register_icall (mono_string_builder_to_utf8
, "mono_string_builder_to_utf8", "ptr object", FALSE
);
114 register_icall (mono_string_builder_to_utf16
, "mono_string_builder_to_utf16", "ptr object", FALSE
);
115 register_icall (mono_array_to_savearray
, "mono_array_to_savearray", "ptr object", FALSE
);
116 register_icall (mono_array_to_lparray
, "mono_array_to_lparray", "ptr object", FALSE
);
117 register_icall (mono_delegate_to_ftnptr
, "mono_delegate_to_ftnptr", "ptr object", FALSE
);
118 register_icall (mono_ftnptr_to_delegate
, "mono_ftnptr_to_delegate", "object ptr ptr", FALSE
);
119 register_icall (mono_marshal_asany
, "mono_marshal_asany", "ptr object int32", FALSE
);
120 register_icall (mono_marshal_free_asany
, "mono_marshal_free_asany", "void object ptr int32", FALSE
);
121 register_icall (mono_marshal_alloc
, "mono_marshal_alloc", "ptr int32", FALSE
);
122 register_icall (mono_marshal_free
, "mono_marshal_free", "void ptr", FALSE
);
123 register_icall (mono_string_utf8_to_builder
, "mono_string_utf8_to_builder", "void ptr ptr", FALSE
);
124 register_icall (mono_string_utf16_to_builder
, "mono_string_utf16_to_builder", "void ptr ptr", FALSE
);
125 register_icall (mono_marshal_free_array
, "mono_marshal_free_array", "void ptr int32", FALSE
);
126 register_icall (mono_string_to_byvalstr
, "mono_string_to_byvalstr", "void ptr ptr int32", FALSE
);
127 register_icall (mono_string_to_byvalwstr
, "mono_string_to_byvalwstr", "void ptr ptr int32", FALSE
);
128 register_icall (g_free
, "g_free", "void ptr", FALSE
);
129 register_icall (mono_object_isinst
, "mono_object_isinst", "object object ptr", FALSE
);
130 register_icall (mono_struct_delete_old
, "mono_struct_delete_old", "void ptr ptr", FALSE
);
135 mono_delegate_to_ftnptr (MonoDelegate
*delegate
)
137 MonoMethod
*method
, *wrapper
, *invoke
;
138 MonoMarshalSpec
**mspecs
;
145 if (delegate
->delegate_trampoline
)
146 return delegate
->delegate_trampoline
;
148 klass
= ((MonoObject
*)delegate
)->vtable
->klass
;
149 g_assert (klass
->delegate
);
151 method
= delegate
->method_info
->method
;
152 invoke
= mono_find_method_by_name (klass
, "Invoke", method
->signature
->param_count
);
154 mspecs
= g_new (MonoMarshalSpec
*, invoke
->signature
->param_count
+ 1);
155 mono_method_get_marshal_info (invoke
, mspecs
);
157 wrapper
= mono_marshal_get_managed_wrapper (method
, delegate
->target
, mspecs
);
159 for (i
= invoke
->signature
->param_count
; i
>= 0; i
--)
161 mono_metadata_free_marshal_spec (mspecs
[i
]);
164 delegate
->delegate_trampoline
= mono_compile_method (wrapper
);
166 // Add the delegate to the delegate hash table
167 delegate_hash_table_add (delegate
);
169 return delegate
->delegate_trampoline
;
172 static GHashTable
*delegate_hash_table
;
175 delegate_hash_table_new (void) {
176 return g_hash_table_new (NULL
, NULL
);
180 delegate_hash_table_remove (MonoDelegate
*d
)
182 EnterCriticalSection (&marshal_mutex
);
183 if (delegate_hash_table
== NULL
)
184 delegate_hash_table
= delegate_hash_table_new ();
185 g_hash_table_remove (delegate_hash_table
, d
->delegate_trampoline
);
186 LeaveCriticalSection (&marshal_mutex
);
190 delegate_hash_table_add (MonoDelegate
*d
)
192 EnterCriticalSection (&marshal_mutex
);
193 if (delegate_hash_table
== NULL
)
194 delegate_hash_table
= delegate_hash_table_new ();
195 g_hash_table_insert (delegate_hash_table
, d
->delegate_trampoline
, d
);
196 LeaveCriticalSection (&marshal_mutex
);
200 mono_ftnptr_to_delegate (MonoClass
*klass
, gpointer ftn
)
204 EnterCriticalSection (&marshal_mutex
);
205 if (delegate_hash_table
== NULL
)
206 delegate_hash_table
= delegate_hash_table_new ();
208 d
= g_hash_table_lookup (delegate_hash_table
, ftn
);
209 LeaveCriticalSection (&marshal_mutex
);
211 mono_raise_exception (mono_get_exception_argument (NULL
, "Additional information: Function pointer was not created by a delegate."));
216 mono_delegate_free_ftnptr (MonoDelegate
*delegate
)
221 delegate_hash_table_remove (delegate
);
222 ptr2
= delegate
->delegate_trampoline
;
224 ptr
= InterlockedExchangePointer (&delegate
->delegate_trampoline
, NULL
);
225 ji
= mono_jit_info_table_find (mono_domain_get (), ptr
);
228 if (!delegate
->target
) {
229 /* The wrapper method is shared between delegates -> no need to free it */
233 mono_runtime_free_method (ji
->method
);
237 mono_array_to_savearray (MonoArray
*array
)
242 g_assert_not_reached ();
247 mono_array_to_lparray (MonoArray
*array
)
252 /* fixme: maybe we need to make a copy */
253 return array
->vector
;
257 mono_string_utf8_to_builder (MonoStringBuilder
*sb
, char *text
)
259 GError
*error
= NULL
;
269 ut
= g_utf8_to_utf16 (text
, l
, NULL
, &items_written
, &error
);
271 if (items_written
> mono_stringbuilder_capacity (sb
))
272 items_written
= mono_stringbuilder_capacity (sb
);
275 memcpy (mono_string_chars (sb
->str
), ut
, items_written
* 2);
276 sb
->length
= items_written
;
278 g_error_free (error
);
284 mono_string_utf16_to_builder (MonoStringBuilder
*sb
, gunichar2
*text
)
291 g_assert (mono_string_chars (sb
->str
) == text
);
293 for (len
= 0; text
[len
] != 0; ++len
)
300 mono_string_builder_to_utf8 (MonoStringBuilder
*sb
)
302 GError
*error
= NULL
;
309 res
= mono_marshal_alloc (mono_stringbuilder_capacity (sb
) + 1);
311 tmp
= g_utf16_to_utf8 (mono_string_chars (sb
->str
), sb
->length
, NULL
, res
, &error
);
313 g_error_free (error
);
314 mono_raise_exception (mono_get_exception_execution_engine ("Failed to convert StringBuilder from utf16 to utf8"));
317 memcpy (res
, tmp
, sb
->length
+ 1);
325 mono_string_builder_to_utf16 (MonoStringBuilder
*sb
)
330 return mono_string_chars (sb
->str
);
334 mono_string_to_lpstr (MonoString
*s
)
336 #ifdef PLATFORM_WIN32
339 GError
*error
= NULL
;
345 as
= CoTaskMemAlloc (1);
350 tmp
= g_utf16_to_utf8 (mono_string_chars (s
), s
->length
, NULL
, &len
, &error
);
352 g_warning (error
->message
);
353 g_error_free (error
);
357 as
= CoTaskMemAlloc (len
+ 1);
358 memcpy (as
, tmp
, len
+ 1);
362 return mono_string_to_utf8 (s
);
367 mono_string_to_ansibstr (MonoString
*string_obj
)
369 g_error ("implement me");
374 mono_string_to_bstr (MonoString
*string_obj
)
376 g_error ("implement me");
381 mono_string_to_byvalstr (gpointer dst
, MonoString
*src
, int size
)
386 g_assert (dst
!= NULL
);
389 memset (dst
, 0, size
);
394 s
= mono_string_to_utf8 (src
);
395 len
= MIN (size
, strlen (s
));
396 memcpy (dst
, s
, len
);
399 *((char *)dst
+ size
- 1) = 0;
403 mono_string_to_byvalwstr (gpointer dst
, MonoString
*src
, int size
)
407 g_assert (dst
!= NULL
);
411 memset (dst
, 0, size
);
415 len
= MIN (size
, (mono_string_length (src
) * 2));
416 memcpy (dst
, mono_string_chars (src
), len
);
418 *((char *)dst
+ size
- 1) = 0;
419 *((char *)dst
+ size
- 2) = 0;
423 mono_mb_free (MonoMethodBuilder
*mb
)
425 g_list_free (mb
->locals_list
);
430 mono_mb_new (MonoClass
*klass
, const char *name
, MonoWrapperType type
)
432 MonoMethodBuilder
*mb
;
435 g_assert (klass
!= NULL
);
436 g_assert (name
!= NULL
);
438 mb
= g_new0 (MonoMethodBuilder
, 1);
440 mb
->method
= m
= (MonoMethod
*)g_new0 (MonoMethodWrapper
, 1);
443 m
->name
= g_strdup (name
);
445 m
->inline_count
= -1;
446 m
->wrapper_type
= type
;
449 mb
->code
= g_malloc (mb
->code_size
);
455 mono_mb_add_local (MonoMethodBuilder
*mb
, MonoType
*type
)
457 int res
= mb
->locals
;
459 g_assert (mb
!= NULL
);
460 g_assert (type
!= NULL
);
462 mb
->locals_list
= g_list_append (mb
->locals_list
, type
);
469 mono_mb_create_method (MonoMethodBuilder
*mb
, MonoMethodSignature
*signature
, int max_stack
)
471 MonoMethodHeader
*header
;
475 g_assert (mb
!= NULL
);
477 ((MonoMethodNormal
*)mb
->method
)->header
= header
= (MonoMethodHeader
*)
478 g_malloc0 (sizeof (MonoMethodHeader
) + mb
->locals
* sizeof (MonoType
*));
483 header
->max_stack
= max_stack
;
485 for (i
= 0, l
= mb
->locals_list
; l
; l
= l
->next
, i
++) {
486 header
->locals
[i
] = (MonoType
*)l
->data
;
489 mb
->method
->signature
= signature
;
490 header
->code
= mb
->code
;
491 header
->code_size
= mb
->pos
;
492 header
->num_locals
= mb
->locals
;
494 #ifdef DEBUG_RUNTIME_CODE
495 printf ("RUNTIME CODE FOR %s\n", mono_method_full_name (mb
->method
, TRUE
));
496 printf ("%s\n", mono_disasm_code (&marshal_dh
, mb
->method
, mb
->code
, mb
->code
+ mb
->pos
));
503 mono_mb_add_data (MonoMethodBuilder
*mb
, gpointer data
)
505 MonoMethodWrapper
*mw
;
507 g_assert (mb
!= NULL
);
509 mw
= (MonoMethodWrapper
*)mb
->method
;
511 mw
->data
= g_list_append (mw
->data
, data
);
513 return g_list_length (mw
->data
);
517 mono_mb_patch_addr (MonoMethodBuilder
*mb
, int pos
, int value
)
519 mb
->code
[pos
] = value
& 0xff;
520 mb
->code
[pos
+ 1] = (value
>> 8) & 0xff;
521 mb
->code
[pos
+ 2] = (value
>> 16) & 0xff;
522 mb
->code
[pos
+ 3] = (value
>> 24) & 0xff;
526 mono_mb_patch_addr_s (MonoMethodBuilder
*mb
, int pos
, gint8 value
)
528 *((gint8
*)(&mb
->code
[pos
])) = value
;
532 mono_mb_emit_byte (MonoMethodBuilder
*mb
, guint8 op
)
534 if (mb
->pos
>= mb
->code_size
) {
536 mb
->code
= g_realloc (mb
->code
, mb
->code_size
);
539 mb
->code
[mb
->pos
++] = op
;
543 mono_mb_emit_ldflda (MonoMethodBuilder
*mb
, gint32 offset
)
545 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
546 mono_mb_emit_byte (mb
, CEE_MONO_OBJADDR
);
549 mono_mb_emit_icon (mb
, offset
);
550 mono_mb_emit_byte (mb
, CEE_ADD
);
555 mono_mb_emit_proxy_check (MonoMethodBuilder
*mb
, int branch_code
)
558 mono_mb_emit_ldflda (mb
, G_STRUCT_OFFSET (MonoObject
, vtable
));
559 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
560 mono_mb_emit_icon (mb
, G_STRUCT_OFFSET (MonoVTable
, klass
));
561 mono_mb_emit_byte (mb
, CEE_ADD
);
562 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
563 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
564 mono_mb_emit_byte (mb
, CEE_MONO_LDPTR
);
565 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, mono_defaults
.transparent_proxy_class
));
566 mono_mb_emit_byte (mb
, branch_code
);
568 mono_mb_emit_i4 (mb
, 0);
573 mono_mb_emit_i4 (MonoMethodBuilder
*mb
, gint32 data
)
575 if ((mb
->pos
+ 4) >= mb
->code_size
) {
577 mb
->code
= g_realloc (mb
->code
, mb
->code_size
);
580 mono_mb_patch_addr (mb
, mb
->pos
, data
);
585 mono_mb_emit_i2 (MonoMethodBuilder
*mb
, gint16 data
)
587 if ((mb
->pos
+ 2) >= mb
->code_size
) {
589 mb
->code
= g_realloc (mb
->code
, mb
->code_size
);
592 mb
->code
[mb
->pos
] = data
& 0xff;
593 mb
->code
[mb
->pos
+ 1] = (data
>> 8) & 0xff;
598 mono_mb_emit_ldstr (MonoMethodBuilder
*mb
, char *str
)
600 mono_mb_emit_byte (mb
, CEE_LDSTR
);
601 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, str
));
606 mono_mb_emit_ldarg (MonoMethodBuilder
*mb
, guint argnum
)
609 mono_mb_emit_byte (mb
, CEE_LDARG_0
+ argnum
);
610 } else if (argnum
< 256) {
611 mono_mb_emit_byte (mb
, CEE_LDARG_S
);
612 mono_mb_emit_byte (mb
, argnum
);
614 mono_mb_emit_byte (mb
, CEE_PREFIX1
);
615 mono_mb_emit_byte (mb
, CEE_LDARG
);
616 mono_mb_emit_i2 (mb
, argnum
);
621 mono_mb_emit_ldarg_addr (MonoMethodBuilder
*mb
, guint argnum
)
624 mono_mb_emit_byte (mb
, CEE_LDARGA_S
);
625 mono_mb_emit_byte (mb
, argnum
);
627 mono_mb_emit_byte (mb
, CEE_PREFIX1
);
628 mono_mb_emit_byte (mb
, CEE_LDARGA
);
629 mono_mb_emit_i2 (mb
, argnum
);
634 mono_mb_emit_ldloc_addr (MonoMethodBuilder
*mb
, guint locnum
)
637 mono_mb_emit_byte (mb
, CEE_LDLOCA_S
);
638 mono_mb_emit_byte (mb
, locnum
);
640 mono_mb_emit_byte (mb
, CEE_PREFIX1
);
641 mono_mb_emit_byte (mb
, CEE_LDLOCA
);
642 mono_mb_emit_i2 (mb
, locnum
);
647 mono_mb_emit_ldloc (MonoMethodBuilder
*mb
, guint num
)
650 mono_mb_emit_byte (mb
, CEE_LDLOC_0
+ num
);
651 } else if (num
< 256) {
652 mono_mb_emit_byte (mb
, CEE_LDLOC_S
);
653 mono_mb_emit_byte (mb
, num
);
655 mono_mb_emit_byte (mb
, CEE_PREFIX1
);
656 mono_mb_emit_byte (mb
, CEE_LDLOC
);
657 mono_mb_emit_i2 (mb
, num
);
662 mono_mb_emit_stloc (MonoMethodBuilder
*mb
, guint num
)
665 mono_mb_emit_byte (mb
, CEE_STLOC_0
+ num
);
666 } else if (num
< 256) {
667 mono_mb_emit_byte (mb
, CEE_STLOC_S
);
668 mono_mb_emit_byte (mb
, num
);
670 mono_mb_emit_byte (mb
, CEE_PREFIX1
);
671 mono_mb_emit_byte (mb
, CEE_STLOC
);
672 mono_mb_emit_i2 (mb
, num
);
677 mono_mb_emit_icon (MonoMethodBuilder
*mb
, gint32 value
)
679 if (value
>= -1 && value
< 8) {
680 mono_mb_emit_byte (mb
, CEE_LDC_I4_0
+ value
);
681 } else if (value
>= -128 && value
<= 127) {
682 mono_mb_emit_byte (mb
, CEE_LDC_I4_S
);
683 mono_mb_emit_byte (mb
, value
);
685 mono_mb_emit_byte (mb
, CEE_LDC_I4
);
686 mono_mb_emit_i4 (mb
, value
);
691 mono_mb_emit_branch (MonoMethodBuilder
*mb
, guint8 op
)
694 mono_mb_emit_byte (mb
, op
);
696 mono_mb_emit_i4 (mb
, 0);
701 mono_mb_emit_calli (MonoMethodBuilder
*mb
, MonoMethodSignature
*sig
)
703 mono_mb_emit_byte (mb
, CEE_CALLI
);
704 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, sig
));
708 mono_mb_emit_managed_call (MonoMethodBuilder
*mb
, MonoMethod
*method
, MonoMethodSignature
*opt_sig
)
710 mono_mb_emit_byte (mb
, CEE_PREFIX1
);
711 mono_mb_emit_byte (mb
, CEE_LDFTN
);
712 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, method
));
713 mono_mb_emit_calli (mb
, opt_sig
? opt_sig
: method
->signature
);
717 mono_mb_emit_native_call (MonoMethodBuilder
*mb
, MonoMethodSignature
*sig
, gpointer func
)
719 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
720 mono_mb_emit_byte (mb
, CEE_MONO_SAVE_LMF
);
721 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
722 mono_mb_emit_byte (mb
, CEE_MONO_LDPTR
);
723 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, func
));
724 mono_mb_emit_calli (mb
, sig
);
725 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
726 mono_mb_emit_byte (mb
, CEE_MONO_RESTORE_LMF
);
730 mono_mb_emit_icall (MonoMethodBuilder
*mb
, gpointer func
)
732 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
733 mono_mb_emit_byte (mb
, CEE_MONO_ICALL
);
734 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, func
));
738 mono_mb_emit_exception (MonoMethodBuilder
*mb
, const char *exc_name
, const char *msg
)
740 /* fixme: we need a better way to throw exception,
741 * supporting several exception types and messages */
742 MonoMethod
*ctor
= NULL
;
744 MonoClass
*mme
= mono_class_from_name (mono_defaults
.corlib
, "System", exc_name
);
746 mono_class_init (mme
);
747 for (i
= 0; i
< mme
->method
.count
; ++i
) {
748 if (strcmp (mme
->methods
[i
]->name
, ".ctor") == 0 && mme
->methods
[i
]->signature
->param_count
== 0) {
749 ctor
= mme
->methods
[i
];
754 mono_mb_emit_byte (mb
, CEE_NEWOBJ
);
755 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, ctor
));
757 mono_mb_emit_byte (mb
, CEE_DUP
);
758 mono_mb_emit_ldflda (mb
, G_STRUCT_OFFSET (MonoException
, message
));
759 mono_mb_emit_ldstr (mb
, (char*)msg
);
760 mono_mb_emit_byte (mb
, CEE_STIND_I
);
762 mono_mb_emit_byte (mb
, CEE_THROW
);
766 mono_mb_emit_add_to_local (MonoMethodBuilder
*mb
, guint16 local
, gint32 incr
)
768 mono_mb_emit_ldloc (mb
, local
);
769 mono_mb_emit_icon (mb
, incr
);
770 mono_mb_emit_byte (mb
, CEE_ADD
);
771 mono_mb_emit_stloc (mb
, local
);
775 emit_ptr_to_str_conv (MonoMethodBuilder
*mb
, MonoType
*type
, MonoMarshalConv conv
,
776 int usize
, int msize
, MonoMarshalSpec
*mspec
)
779 case MONO_MARSHAL_CONV_BOOL_I4
:
780 mono_mb_emit_byte (mb
, CEE_LDLOC_1
);
781 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
782 mono_mb_emit_byte (mb
, CEE_LDIND_I4
);
783 mono_mb_emit_byte (mb
, CEE_BRFALSE_S
);
784 mono_mb_emit_byte (mb
, 3);
785 mono_mb_emit_byte (mb
, CEE_LDC_I4_1
);
786 mono_mb_emit_byte (mb
, CEE_BR_S
);
787 mono_mb_emit_byte (mb
, 1);
788 mono_mb_emit_byte (mb
, CEE_LDC_I4_0
);
789 mono_mb_emit_byte (mb
, CEE_STIND_I1
);
791 case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL
:
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_I2
);
795 mono_mb_emit_byte (mb
, CEE_BRFALSE_S
);
796 mono_mb_emit_byte (mb
, 3);
797 mono_mb_emit_byte (mb
, CEE_LDC_I4_1
);
798 mono_mb_emit_byte (mb
, CEE_BR_S
);
799 mono_mb_emit_byte (mb
, 1);
800 mono_mb_emit_byte (mb
, CEE_LDC_I4_0
);
801 mono_mb_emit_byte (mb
, CEE_STIND_I1
);
803 case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY
: {
804 MonoClass
*eclass
= NULL
;
807 if (type
->type
== MONO_TYPE_SZARRAY
) {
808 eclass
= type
->data
.klass
;
810 g_assert_not_reached ();
813 if (eclass
->valuetype
)
814 esize
= mono_class_instance_size (eclass
) - sizeof (MonoObject
);
816 esize
= sizeof (gpointer
);
818 /* create a new array */
819 mono_mb_emit_byte (mb
, CEE_LDLOC_1
);
820 mono_mb_emit_icon (mb
, mspec
->data
.array_data
.num_elem
);
821 mono_mb_emit_byte (mb
, CEE_NEWARR
);
822 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, eclass
));
823 mono_mb_emit_byte (mb
, CEE_STIND_I
);
825 /* copy the elements */
826 mono_mb_emit_byte (mb
, CEE_LDLOC_1
);
827 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
828 mono_mb_emit_icon (mb
, G_STRUCT_OFFSET (MonoArray
, vector
));
829 mono_mb_emit_byte (mb
, CEE_ADD
);
830 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
831 mono_mb_emit_icon (mb
, mspec
->data
.array_data
.num_elem
* esize
);
832 mono_mb_emit_byte (mb
, CEE_PREFIX1
);
833 mono_mb_emit_byte (mb
, CEE_CPBLK
);
837 case MONO_MARSHAL_CONV_STR_BYVALSTR
:
838 mono_mb_emit_byte (mb
, CEE_LDLOC_1
);
839 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
840 mono_mb_emit_icall (mb
, mono_string_new_wrapper
);
841 mono_mb_emit_byte (mb
, CEE_STIND_I
);
843 case MONO_MARSHAL_CONV_STR_LPTSTR
:
844 case MONO_MARSHAL_CONV_STR_LPSTR
:
845 mono_mb_emit_byte (mb
, CEE_LDLOC_1
);
846 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
847 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
848 mono_mb_emit_icall (mb
, mono_string_new_wrapper
);
849 mono_mb_emit_byte (mb
, CEE_STIND_I
);
851 case MONO_MARSHAL_CONV_OBJECT_STRUCT
: {
852 MonoClass
*klass
= mono_class_from_mono_type (type
);
853 int src_var
, dst_var
;
855 src_var
= mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
856 dst_var
= mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
858 /* *dst = new object */
859 mono_mb_emit_byte (mb
, CEE_LDLOC_1
);
860 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
861 mono_mb_emit_byte (mb
, CEE_MONO_NEWOBJ
);
862 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, klass
));
863 mono_mb_emit_byte (mb
, CEE_STIND_I
);
865 /* save the old src pointer */
866 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
867 mono_mb_emit_stloc (mb
, src_var
);
868 /* save the old dst pointer */
869 mono_mb_emit_byte (mb
, CEE_LDLOC_1
);
870 mono_mb_emit_stloc (mb
, dst_var
);
872 /* dst = pointer to newly created object data */
873 mono_mb_emit_byte (mb
, CEE_LDLOC_1
);
874 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
875 mono_mb_emit_icon (mb
, sizeof (MonoObject
));
876 mono_mb_emit_byte (mb
, CEE_ADD
);
877 mono_mb_emit_byte (mb
, CEE_STLOC_1
);
879 emit_struct_conv (mb
, klass
, TRUE
);
881 /* restore the old src pointer */
882 mono_mb_emit_ldloc (mb
, src_var
);
883 mono_mb_emit_byte (mb
, CEE_STLOC_0
);
884 /* restore the old dst pointer */
885 mono_mb_emit_ldloc (mb
, dst_var
);
886 mono_mb_emit_byte (mb
, CEE_STLOC_1
);
889 case MONO_MARSHAL_CONV_DEL_FTN
: {
890 /* fixme: we never convert functions back to delegates, dont
891 // know if thats the correct behaviour
895 case MONO_MARSHAL_CONV_ARRAY_LPARRAY
:
896 g_error ("Structure field of type %s can't be marshalled as LPArray", mono_class_from_mono_type (type
)->name
);
898 case MONO_MARSHAL_CONV_STR_LPWSTR
:
899 case MONO_MARSHAL_CONV_STR_BSTR
:
900 case MONO_MARSHAL_CONV_STR_ANSIBSTR
:
901 case MONO_MARSHAL_CONV_STR_TBSTR
:
902 case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY
:
903 case MONO_MARSHAL_CONV_STR_BYVALWSTR
:
905 g_warning ("marshaling conversion %d not implemented", conv
);
906 g_assert_not_reached ();
911 conv_to_icall (MonoMarshalConv conv
)
914 case MONO_MARSHAL_CONV_STR_LPWSTR
:
915 return mono_marshal_string_to_utf16
;
916 case MONO_MARSHAL_CONV_LPWSTR_STR
:
917 return mono_string_from_utf16
;
918 case MONO_MARSHAL_CONV_LPSTR_STR
:
919 return mono_string_new_wrapper
;
920 case MONO_MARSHAL_CONV_STR_LPTSTR
:
921 case MONO_MARSHAL_CONV_STR_LPSTR
:
922 return mono_string_to_lpstr
;
923 case MONO_MARSHAL_CONV_STR_BSTR
:
924 return mono_string_to_bstr
;
925 case MONO_MARSHAL_CONV_STR_TBSTR
:
926 case MONO_MARSHAL_CONV_STR_ANSIBSTR
:
927 return mono_string_to_ansibstr
;
928 case MONO_MARSHAL_CONV_SB_LPSTR
:
929 case MONO_MARSHAL_CONV_SB_LPTSTR
:
930 return mono_string_builder_to_utf8
;
931 case MONO_MARSHAL_CONV_SB_LPWSTR
:
932 return mono_string_builder_to_utf16
;
933 case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY
:
934 return mono_array_to_savearray
;
935 case MONO_MARSHAL_CONV_ARRAY_LPARRAY
:
936 return mono_array_to_lparray
;
937 case MONO_MARSHAL_CONV_DEL_FTN
:
938 return mono_delegate_to_ftnptr
;
939 case MONO_MARSHAL_CONV_FTN_DEL
:
940 return mono_ftnptr_to_delegate
;
941 case MONO_MARSHAL_CONV_LPSTR_SB
:
942 case MONO_MARSHAL_CONV_LPTSTR_SB
:
943 return mono_string_utf8_to_builder
;
944 case MONO_MARSHAL_CONV_LPWSTR_SB
:
945 return mono_string_utf16_to_builder
;
946 case MONO_MARSHAL_FREE_ARRAY
:
947 return mono_marshal_free_array
;
948 case MONO_MARSHAL_CONV_STR_BYVALSTR
:
949 return mono_string_to_byvalstr
;
950 case MONO_MARSHAL_CONV_STR_BYVALWSTR
:
951 return mono_string_to_byvalwstr
;
953 g_assert_not_reached ();
960 emit_str_to_ptr_conv (MonoMethodBuilder
*mb
, MonoType
*type
, MonoMarshalConv conv
, int usize
, int msize
,
961 MonoMarshalSpec
*mspec
)
966 case MONO_MARSHAL_CONV_BOOL_I4
:
967 mono_mb_emit_byte (mb
, CEE_LDLOC_1
);
968 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
969 mono_mb_emit_byte (mb
, CEE_LDIND_U1
);
970 mono_mb_emit_byte (mb
, CEE_STIND_I4
);
972 case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL
:
973 mono_mb_emit_byte (mb
, CEE_LDLOC_1
);
974 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
975 mono_mb_emit_byte (mb
, CEE_LDIND_U1
);
976 mono_mb_emit_byte (mb
, CEE_NEG
);
977 mono_mb_emit_byte (mb
, CEE_STIND_I2
);
979 case MONO_MARSHAL_CONV_STR_LPWSTR
:
980 case MONO_MARSHAL_CONV_STR_LPSTR
:
981 case MONO_MARSHAL_CONV_STR_LPTSTR
:
982 case MONO_MARSHAL_CONV_STR_BSTR
:
983 case MONO_MARSHAL_CONV_STR_ANSIBSTR
:
984 case MONO_MARSHAL_CONV_STR_TBSTR
: {
987 /* free space if free == true */
988 mono_mb_emit_byte (mb
, CEE_LDLOC_2
);
989 mono_mb_emit_byte (mb
, CEE_BRFALSE_S
);
991 mono_mb_emit_byte (mb
, 0);
992 mono_mb_emit_byte (mb
, CEE_LDLOC_1
);
993 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
994 mono_mb_emit_icall (mb
, g_free
);
995 mono_mb_patch_addr_s (mb
, pos
, mb
->pos
- pos
- 1);
997 mono_mb_emit_byte (mb
, CEE_LDLOC_1
);
998 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
999 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
1000 mono_mb_emit_icall (mb
, conv_to_icall (conv
));
1001 mono_mb_emit_byte (mb
, CEE_STIND_I
);
1004 case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY
:
1005 case MONO_MARSHAL_CONV_ARRAY_LPARRAY
:
1006 case MONO_MARSHAL_CONV_DEL_FTN
:
1007 mono_mb_emit_byte (mb
, CEE_LDLOC_1
);
1008 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
1009 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
1010 mono_mb_emit_icall (mb
, conv_to_icall (conv
));
1011 mono_mb_emit_byte (mb
, CEE_STIND_I
);
1013 case MONO_MARSHAL_CONV_STR_BYVALSTR
:
1014 case MONO_MARSHAL_CONV_STR_BYVALWSTR
: {
1018 mono_mb_emit_byte (mb
, CEE_LDLOC_1
); /* dst */
1019 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
1020 mono_mb_emit_byte (mb
, CEE_LDIND_I
); /* src String */
1021 mono_mb_emit_icon (mb
, usize
);
1022 mono_mb_emit_icall (mb
, conv_to_icall (conv
));
1025 case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY
: {
1026 MonoClass
*eclass
= NULL
;
1029 if (type
->type
== MONO_TYPE_SZARRAY
) {
1030 eclass
= type
->data
.klass
;
1032 g_assert_not_reached ();
1035 if (eclass
->valuetype
)
1036 esize
= mono_class_native_size (eclass
, NULL
);
1038 esize
= sizeof (gpointer
);
1043 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
1044 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
1045 mono_mb_emit_byte (mb
, CEE_BRFALSE_S
);
1047 mono_mb_emit_byte (mb
, 0);
1049 mono_mb_emit_byte (mb
, CEE_LDLOC_1
);
1050 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
1051 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
1052 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
1053 mono_mb_emit_byte (mb
, CEE_MONO_OBJADDR
);
1054 mono_mb_emit_icon (mb
, G_STRUCT_OFFSET (MonoArray
, vector
));
1055 mono_mb_emit_byte (mb
, CEE_ADD
);
1056 mono_mb_emit_icon (mb
, mspec
->data
.array_data
.num_elem
* esize
);
1057 mono_mb_emit_byte (mb
, CEE_PREFIX1
);
1058 mono_mb_emit_byte (mb
, CEE_CPBLK
);
1059 mono_mb_patch_addr_s (mb
, pos
, mb
->pos
- pos
- 1);
1062 case MONO_MARSHAL_CONV_OBJECT_STRUCT
: {
1063 int src_var
, dst_var
;
1065 src_var
= mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
1066 dst_var
= mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
1068 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
1069 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
1070 mono_mb_emit_byte (mb
, CEE_BRFALSE_S
);
1072 mono_mb_emit_byte (mb
, 0);
1074 /* save the old src pointer */
1075 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
1076 mono_mb_emit_stloc (mb
, src_var
);
1077 /* save the old dst pointer */
1078 mono_mb_emit_byte (mb
, CEE_LDLOC_1
);
1079 mono_mb_emit_stloc (mb
, dst_var
);
1081 /* src = pointer to object data */
1082 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
1083 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
1084 mono_mb_emit_icon (mb
, sizeof (MonoObject
));
1085 mono_mb_emit_byte (mb
, CEE_ADD
);
1086 mono_mb_emit_byte (mb
, CEE_STLOC_0
);
1088 emit_struct_conv (mb
, mono_class_from_mono_type (type
), FALSE
);
1090 /* restore the old src pointer */
1091 mono_mb_emit_ldloc (mb
, src_var
);
1092 mono_mb_emit_byte (mb
, CEE_STLOC_0
);
1093 /* restore the old dst pointer */
1094 mono_mb_emit_ldloc (mb
, dst_var
);
1095 mono_mb_emit_byte (mb
, CEE_STLOC_1
);
1097 mono_mb_patch_addr_s (mb
, pos
, mb
->pos
- pos
- 1);
1101 char *msg
= g_strdup_printf ("marshalling conversion %d not implemented", conv
);
1102 MonoException
*exc
= mono_get_exception_not_implemented (msg
);
1105 mono_raise_exception (exc
);
1111 emit_struct_conv (MonoMethodBuilder
*mb
, MonoClass
*klass
, gboolean to_object
)
1113 MonoMarshalType
*info
;
1117 emit_struct_conv(mb
, klass
->parent
, to_object
);
1119 info
= mono_marshal_load_type_info (klass
);
1121 if (info
->native_size
== 0)
1124 if (klass
->blittable
) {
1125 int msize
= mono_class_value_size (klass
, NULL
);
1126 g_assert (msize
== info
->native_size
);
1127 mono_mb_emit_byte (mb
, CEE_LDLOC_1
);
1128 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
1129 mono_mb_emit_icon (mb
, msize
);
1130 mono_mb_emit_byte (mb
, CEE_PREFIX1
);
1131 mono_mb_emit_byte (mb
, CEE_CPBLK
);
1133 mono_mb_emit_add_to_local (mb
, 0, msize
);
1134 mono_mb_emit_add_to_local (mb
, 1, msize
);
1138 for (i
= 0; i
< info
->num_fields
; i
++) {
1139 MonoMarshalNative ntype
;
1140 MonoMarshalConv conv
;
1141 MonoType
*ftype
= info
->fields
[i
].field
->type
;
1144 gboolean last_field
= i
< (info
->num_fields
-1) ? 0 : 1;
1146 if (ftype
->attrs
& FIELD_ATTRIBUTE_STATIC
)
1149 ntype
= mono_type_to_unmanaged (ftype
, info
->fields
[i
].mspec
, TRUE
, klass
->unicode
, &conv
);
1152 msize
= klass
->instance_size
- info
->fields
[i
].field
->offset
;
1153 usize
= info
->native_size
- info
->fields
[i
].offset
;
1155 msize
= info
->fields
[i
+ 1].field
->offset
- info
->fields
[i
].field
->offset
;
1156 usize
= info
->fields
[i
+ 1].offset
- info
->fields
[i
].offset
;
1158 if ((msize
< 0) || (usize
< 0))
1159 /* This happens with GC aware auto layout */
1160 g_error ("Type %s which is passed to unmanaged code must have a StructLayout attribute", mono_type_full_name (&klass
->byval_arg
));
1162 g_assert ((msize
>= 0) && (usize
>= 0));
1165 case MONO_MARSHAL_CONV_NONE
: {
1168 if (ftype
->byref
|| ftype
->type
== MONO_TYPE_I
||
1169 ftype
->type
== MONO_TYPE_U
) {
1170 mono_mb_emit_byte (mb
, CEE_LDLOC_1
);
1171 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
1172 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
1173 mono_mb_emit_byte (mb
, CEE_STIND_I
);
1182 #if SIZEOF_VOID_P == 4
1185 mono_mb_emit_byte (mb
, CEE_LDLOC_1
);
1186 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
1187 mono_mb_emit_byte (mb
, CEE_LDIND_I4
);
1188 mono_mb_emit_byte (mb
, CEE_STIND_I4
);
1192 case MONO_TYPE_BOOLEAN
:
1193 mono_mb_emit_byte (mb
, CEE_LDLOC_1
);
1194 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
1195 mono_mb_emit_byte (mb
, CEE_LDIND_I1
);
1196 mono_mb_emit_byte (mb
, CEE_STIND_I1
);
1200 case MONO_TYPE_CHAR
:
1201 mono_mb_emit_byte (mb
, CEE_LDLOC_1
);
1202 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
1203 mono_mb_emit_byte (mb
, CEE_LDIND_I2
);
1204 mono_mb_emit_byte (mb
, CEE_STIND_I2
);
1208 #if SIZEOF_VOID_P == 8
1211 mono_mb_emit_byte (mb
, CEE_LDLOC_1
);
1212 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
1213 mono_mb_emit_byte (mb
, CEE_LDIND_I8
);
1214 mono_mb_emit_byte (mb
, CEE_STIND_I8
);
1217 mono_mb_emit_byte (mb
, CEE_LDLOC_1
);
1218 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
1219 mono_mb_emit_byte (mb
, CEE_LDIND_R4
);
1220 mono_mb_emit_byte (mb
, CEE_STIND_R4
);
1223 mono_mb_emit_byte (mb
, CEE_LDLOC_1
);
1224 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
1225 mono_mb_emit_byte (mb
, CEE_LDIND_R8
);
1226 mono_mb_emit_byte (mb
, CEE_STIND_R8
);
1228 case MONO_TYPE_VALUETYPE
:
1229 if (ftype
->data
.klass
->enumtype
) {
1230 t
= ftype
->data
.klass
->enum_basetype
->type
;
1233 emit_struct_conv (mb
, ftype
->data
.klass
, to_object
);
1236 g_warning ("marshaling type %02x not implemented", ftype
->type
);
1237 g_assert_not_reached ();
1243 emit_ptr_to_str_conv (mb
, ftype
, conv
, usize
, msize
, info
->fields
[i
].mspec
);
1245 emit_str_to_ptr_conv (mb
, ftype
, conv
, usize
, msize
, info
->fields
[i
].mspec
);
1249 mono_mb_emit_add_to_local (mb
, 0, usize
);
1250 mono_mb_emit_add_to_local (mb
, 1, msize
);
1252 mono_mb_emit_add_to_local (mb
, 0, msize
);
1253 mono_mb_emit_add_to_local (mb
, 1, usize
);
1259 emit_struct_free (MonoMethodBuilder
*mb
, MonoClass
*klass
, int struct_var
)
1261 /* Call DestroyStructure */
1262 /* FIXME: Only do this if needed */
1263 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
1264 mono_mb_emit_byte (mb
, CEE_MONO_LDPTR
);
1265 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, klass
));
1266 mono_mb_emit_ldloc (mb
, struct_var
);
1267 mono_mb_emit_icall (mb
, mono_struct_delete_old
);
1271 emit_thread_interrupt_checkpoint_call (MonoMethodBuilder
*mb
, gpointer checkpoint_func
)
1273 static MonoMethodSignature
*state_check_sig
= NULL
;
1276 if (!state_check_sig
) {
1277 state_check_sig
= mono_metadata_signature_alloc (mono_defaults
.corlib
, 0);
1278 state_check_sig
->ret
= &mono_defaults
.void_class
->byval_arg
;
1279 state_check_sig
->pinvoke
= 0;
1282 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
1283 mono_mb_emit_byte (mb
, CEE_MONO_LDPTR
);
1284 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, (gpointer
) mono_thread_interruption_request_flag ()));
1285 mono_mb_emit_byte (mb
, CEE_LDIND_I4
);
1286 pos_noabort
= mono_mb_emit_branch (mb
, CEE_BRFALSE
);
1288 mono_mb_emit_native_call (mb
, state_check_sig
, checkpoint_func
);
1290 mono_mb_patch_addr (mb
, pos_noabort
, mb
->pos
- (pos_noabort
+ 4));
1294 emit_thread_interrupt_checkpoint (MonoMethodBuilder
*mb
)
1296 emit_thread_interrupt_checkpoint_call (mb
, mono_thread_interruption_checkpoint
);
1300 emit_thread_force_interrupt_checkpoint (MonoMethodBuilder
*mb
)
1302 emit_thread_interrupt_checkpoint_call (mb
, mono_thread_force_interruption_checkpoint
);
1305 static MonoAsyncResult
*
1306 mono_delegate_begin_invoke (MonoDelegate
*delegate
, gpointer
*params
)
1308 MonoMethodMessage
*msg
;
1309 MonoDelegate
*async_callback
;
1313 MonoMethod
*method
= NULL
;
1316 g_assert (delegate
);
1318 if (delegate
->target
&& mono_object_class (delegate
->target
) == mono_defaults
.transparent_proxy_class
) {
1320 MonoTransparentProxy
* tp
= (MonoTransparentProxy
*)delegate
->target
;
1321 if (!tp
->remote_class
->proxy_class
->contextbound
|| tp
->rp
->context
!= (MonoObject
*) mono_context_get ()) {
1323 /* If the target is a proxy, make a direct call. Is proxy's work
1324 // to make the call asynchronous.
1326 MonoAsyncResult
*ares
;
1328 MonoArray
*out_args
;
1330 method
= delegate
->method_info
->method
;
1332 msg
= mono_method_call_message_new (mono_marshal_method_from_wrapper (method
), params
, NULL
, &async_callback
, &state
);
1333 handle
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
1334 ares
= mono_async_result_new (mono_domain_get (), handle
, state
, handle
);
1335 ares
->async_delegate
= (MonoObject
*)delegate
;
1336 ares
->async_callback
= (MonoObject
*)async_callback
;
1337 msg
->async_result
= ares
;
1338 msg
->call_type
= CallType_BeginInvoke
;
1340 mono_remoting_invoke ((MonoObject
*)tp
->rp
, msg
, &exc
, &out_args
);
1345 klass
= delegate
->object
.vtable
->klass
;
1347 method
= mono_get_delegate_invoke (klass
);
1348 for (i
= 0; i
< klass
->method
.count
; ++i
) {
1349 if (klass
->methods
[i
]->name
[0] == 'B' &&
1350 !strcmp ("BeginInvoke", klass
->methods
[i
]->name
)) {
1351 method
= klass
->methods
[i
];
1356 g_assert (method
!= NULL
);
1358 im
= mono_get_delegate_invoke (method
->klass
);
1359 msg
= mono_method_call_message_new (method
, params
, im
, &async_callback
, &state
);
1361 return mono_thread_pool_add ((MonoObject
*)delegate
, msg
, async_callback
, state
);
1365 mono_mb_emit_save_args (MonoMethodBuilder
*mb
, MonoMethodSignature
*sig
, gboolean save_this
)
1367 int i
, params_var
, tmp_var
;
1369 /* allocate local (pointer) *params[] */
1370 params_var
= mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
1371 /* allocate local (pointer) tmp */
1372 tmp_var
= mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
1374 /* alloate space on stack to store an array of pointers to the arguments */
1375 mono_mb_emit_icon (mb
, sizeof (gpointer
) * (sig
->param_count
+ 1));
1376 mono_mb_emit_byte (mb
, CEE_PREFIX1
);
1377 mono_mb_emit_byte (mb
, CEE_LOCALLOC
);
1378 mono_mb_emit_stloc (mb
, params_var
);
1381 mono_mb_emit_ldloc (mb
, params_var
);
1382 mono_mb_emit_stloc (mb
, tmp_var
);
1384 if (save_this
&& sig
->hasthis
) {
1385 mono_mb_emit_ldloc (mb
, tmp_var
);
1386 mono_mb_emit_ldarg_addr (mb
, 0);
1387 mono_mb_emit_byte (mb
, CEE_STIND_I
);
1388 /* tmp = tmp + sizeof (gpointer) */
1389 if (sig
->param_count
)
1390 mono_mb_emit_add_to_local (mb
, tmp_var
, sizeof (gpointer
));
1394 for (i
= 0; i
< sig
->param_count
; i
++) {
1395 mono_mb_emit_ldloc (mb
, tmp_var
);
1396 mono_mb_emit_ldarg_addr (mb
, i
+ sig
->hasthis
);
1397 mono_mb_emit_byte (mb
, CEE_STIND_I
);
1398 /* tmp = tmp + sizeof (gpointer) */
1399 if (i
< (sig
->param_count
- 1))
1400 mono_mb_emit_add_to_local (mb
, tmp_var
, sizeof (gpointer
));
1407 mono_signature_to_name (MonoMethodSignature
*sig
, const char *prefix
)
1411 GString
*res
= g_string_new ("");
1414 g_string_append (res
, prefix
);
1415 g_string_append_c (res
, '_');
1418 mono_type_get_desc (res
, sig
->ret
, FALSE
);
1420 for (i
= 0; i
< sig
->param_count
; ++i
) {
1421 g_string_append_c (res
, '_');
1422 mono_type_get_desc (res
, sig
->params
[i
], FALSE
);
1425 g_string_free (res
, FALSE
);
1430 * mono_marshal_get_string_encoding:
1432 * Return the string encoding which should be used for a given parameter.
1434 static MonoMarshalNative
1435 mono_marshal_get_string_encoding (MonoMethodPInvoke
*piinfo
, MonoMarshalSpec
*spec
)
1437 /* First try the parameter marshal info */
1439 if (spec
->native
== MONO_NATIVE_LPARRAY
) {
1440 if (spec
->data
.array_data
.elem_type
!= 0)
1441 return spec
->data
.array_data
.elem_type
;
1444 return spec
->native
;
1448 return MONO_NATIVE_LPSTR
;
1450 /* Then try the method level marshal info */
1451 switch (piinfo
->piflags
& PINVOKE_ATTRIBUTE_CHAR_SET_MASK
) {
1452 case PINVOKE_ATTRIBUTE_CHAR_SET_ANSI
:
1453 return MONO_NATIVE_LPSTR
;
1454 case PINVOKE_ATTRIBUTE_CHAR_SET_UNICODE
:
1455 return MONO_NATIVE_LPWSTR
;
1456 case PINVOKE_ATTRIBUTE_CHAR_SET_AUTO
:
1457 return MONO_NATIVE_LPTSTR
;
1459 return MONO_NATIVE_LPSTR
;
1463 static MonoMarshalConv
1464 mono_marshal_get_string_to_ptr_conv (MonoMethodPInvoke
*piinfo
, MonoMarshalSpec
*spec
)
1466 MonoMarshalNative encoding
= mono_marshal_get_string_encoding (piinfo
, spec
);
1469 case MONO_NATIVE_LPWSTR
:
1470 return MONO_MARSHAL_CONV_STR_LPWSTR
;
1471 case MONO_NATIVE_LPSTR
:
1472 return MONO_MARSHAL_CONV_STR_LPSTR
;
1473 case MONO_NATIVE_LPTSTR
:
1474 return MONO_MARSHAL_CONV_STR_LPTSTR
;
1480 static MonoMarshalConv
1481 mono_marshal_get_stringbuilder_to_ptr_conv (MonoMethodPInvoke
*piinfo
, MonoMarshalSpec
*spec
)
1483 MonoMarshalNative encoding
= mono_marshal_get_string_encoding (piinfo
, spec
);
1486 case MONO_NATIVE_LPWSTR
:
1487 return MONO_MARSHAL_CONV_SB_LPWSTR
;
1489 case MONO_NATIVE_LPSTR
:
1490 return MONO_MARSHAL_CONV_SB_LPSTR
;
1492 case MONO_NATIVE_LPTSTR
:
1493 return MONO_MARSHAL_CONV_SB_LPTSTR
;
1500 static MonoMarshalConv
1501 mono_marshal_get_ptr_to_stringbuilder_conv (MonoMethodPInvoke
*piinfo
, MonoMarshalSpec
*spec
, gboolean
*need_free
)
1503 MonoMarshalNative encoding
= mono_marshal_get_string_encoding (piinfo
, spec
);
1508 case MONO_NATIVE_LPWSTR
:
1510 * mono_string_builder_to_utf16 does not allocate a
1511 * new buffer, so no need to free it.
1514 return MONO_MARSHAL_CONV_LPWSTR_SB
;
1515 case MONO_NATIVE_LPSTR
:
1516 return MONO_MARSHAL_CONV_LPSTR_SB
;
1518 case MONO_NATIVE_LPTSTR
:
1519 return MONO_MARSHAL_CONV_LPTSTR_SB
;
1527 * Return whenever a field of a native structure or an array member needs to
1531 mono_marshal_need_free (MonoType
*t
, MonoMethodPInvoke
*piinfo
, MonoMarshalSpec
*spec
)
1533 MonoMarshalNative encoding
;
1534 MonoMarshalConv conv
;
1537 case MONO_TYPE_VALUETYPE
:
1538 /* FIXME: Optimize this */
1540 case MONO_TYPE_OBJECT
:
1541 case MONO_TYPE_CLASS
:
1542 if (t
->data
.klass
== mono_defaults
.stringbuilder_class
) {
1544 conv
= mono_marshal_get_ptr_to_stringbuilder_conv (piinfo
, spec
, &need_free
);
1548 case MONO_TYPE_STRING
:
1549 encoding
= mono_marshal_get_string_encoding (piinfo
, spec
);
1550 return (encoding
== MONO_NATIVE_LPWSTR
) ? FALSE
: TRUE
;
1556 static inline MonoMethod
*
1557 mono_marshal_find_in_cache (GHashTable
*cache
, gpointer key
)
1561 EnterCriticalSection (&marshal_mutex
);
1562 res
= g_hash_table_lookup (cache
, key
);
1563 LeaveCriticalSection (&marshal_mutex
);
1567 /* Create the method from the builder and place it in the cache */
1568 static inline MonoMethod
*
1569 mono_mb_create_and_cache (GHashTable
*cache
, gpointer key
,
1570 MonoMethodBuilder
*mb
, MonoMethodSignature
*sig
,
1575 EnterCriticalSection (&marshal_mutex
);
1576 res
= g_hash_table_lookup (cache
, key
);
1578 /* This does not acquire any locks */
1579 res
= mono_mb_create_method (mb
, sig
, max_stack
);
1580 g_hash_table_insert (cache
, key
, res
);
1581 mono_g_hash_table_insert (wrapper_hash
, res
, key
);
1584 /* Somebody created it before us */
1586 LeaveCriticalSection (&marshal_mutex
);
1592 mono_marshal_method_from_wrapper (MonoMethod
*wrapper
)
1596 if (wrapper
->wrapper_type
== MONO_WRAPPER_NONE
)
1599 EnterCriticalSection (&marshal_mutex
);
1600 res
= mono_g_hash_table_lookup (wrapper_hash
, wrapper
);
1601 LeaveCriticalSection (&marshal_mutex
);
1603 if (res
&& wrapper
->wrapper_type
== MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK
)
1604 /* See mono_marshal_get_remoting_invoke_with_check */
1605 return (MonoMethod
*)((char*)res
- 1);
1611 mono_marshal_get_delegate_begin_invoke (MonoMethod
*method
)
1613 MonoMethodSignature
*sig
;
1614 static MonoMethodSignature
*csig
= NULL
;
1615 MonoMethodBuilder
*mb
;
1621 g_assert (method
&& method
->klass
->parent
== mono_defaults
.multicastdelegate_class
&&
1622 !strcmp (method
->name
, "BeginInvoke"));
1624 sig
= method
->signature
;
1626 cache
= method
->klass
->image
->delegate_begin_invoke_cache
;
1627 if ((res
= mono_marshal_find_in_cache (cache
, sig
)))
1630 g_assert (sig
->hasthis
);
1633 csig
= mono_metadata_signature_alloc (method
->klass
->image
, 2);
1635 /* MonoAsyncResult * begin_invoke (MonoDelegate *delegate, gpointer params[]) */
1636 csig
->ret
= &mono_defaults
.object_class
->byval_arg
;
1637 csig
->params
[0] = &mono_defaults
.object_class
->byval_arg
;
1638 csig
->params
[1] = &mono_defaults
.int_class
->byval_arg
;
1641 name
= mono_signature_to_name (sig
, "begin_invoke");
1642 mb
= mono_mb_new (mono_defaults
.multicastdelegate_class
, name
, MONO_WRAPPER_DELEGATE_BEGIN_INVOKE
);
1645 mb
->method
->save_lmf
= 1;
1647 params_var
= mono_mb_emit_save_args (mb
, sig
, FALSE
);
1649 mono_mb_emit_ldarg (mb
, 0);
1650 mono_mb_emit_ldloc (mb
, params_var
);
1651 mono_mb_emit_native_call (mb
, csig
, mono_delegate_begin_invoke
);
1652 emit_thread_interrupt_checkpoint (mb
);
1653 mono_mb_emit_byte (mb
, CEE_RET
);
1655 res
= mono_mb_create_and_cache (cache
, sig
, mb
, sig
, sig
->param_count
+ 16);
1661 mono_delegate_end_invoke (MonoDelegate
*delegate
, gpointer
*params
)
1663 MonoDomain
*domain
= mono_domain_get ();
1664 MonoAsyncResult
*ares
;
1665 MonoMethod
*method
= NULL
;
1666 MonoMethodSignature
*sig
;
1667 MonoMethodMessage
*msg
;
1668 MonoObject
*res
, *exc
;
1669 MonoArray
*out_args
;
1673 g_assert (delegate
);
1675 if (!delegate
->method_info
|| !delegate
->method_info
->method
)
1676 g_assert_not_reached ();
1678 klass
= delegate
->object
.vtable
->klass
;
1680 for (i
= 0; i
< klass
->method
.count
; ++i
) {
1681 if (klass
->methods
[i
]->name
[0] == 'E' &&
1682 !strcmp ("EndInvoke", klass
->methods
[i
]->name
)) {
1683 method
= klass
->methods
[i
];
1688 g_assert (method
!= NULL
);
1690 sig
= method
->signature
;
1692 msg
= mono_method_call_message_new (method
, params
, NULL
, NULL
, NULL
);
1694 ares
= mono_array_get (msg
->args
, gpointer
, sig
->param_count
- 1);
1697 if (delegate
->target
&& mono_object_class (delegate
->target
) == mono_defaults
.transparent_proxy_class
) {
1698 MonoTransparentProxy
* tp
= (MonoTransparentProxy
*)delegate
->target
;
1699 msg
= (MonoMethodMessage
*)mono_object_new (domain
, mono_defaults
.mono_method_message_class
);
1700 mono_message_init (domain
, msg
, delegate
->method_info
, NULL
);
1701 msg
->call_type
= CallType_EndInvoke
;
1702 msg
->async_result
= ares
;
1703 res
= mono_remoting_invoke ((MonoObject
*)tp
->rp
, msg
, &exc
, &out_args
);
1706 res
= mono_thread_pool_finish (ares
, &out_args
, &exc
);
1709 if (((MonoException
*)exc
)->stack_trace
) {
1710 char *strace
= mono_string_to_utf8 (((MonoException
*)exc
)->stack_trace
);
1712 tmp
= g_strdup_printf ("%s\nException Rethrown at:\n", strace
);
1714 ((MonoException
*)exc
)->stack_trace
= mono_string_new (domain
, tmp
);
1717 mono_raise_exception ((MonoException
*)exc
);
1720 mono_method_return_message_restore (method
, params
, out_args
);
1725 mono_mb_emit_restore_result (MonoMethodBuilder
*mb
, MonoType
*return_type
)
1727 if (return_type
->byref
)
1728 return_type
= &mono_defaults
.int_class
->byval_arg
;
1729 else if (return_type
->type
== MONO_TYPE_VALUETYPE
&& return_type
->data
.klass
->enumtype
)
1730 return_type
= return_type
->data
.klass
->enum_basetype
;
1732 switch (return_type
->type
) {
1733 case MONO_TYPE_VOID
:
1734 g_assert_not_reached ();
1737 case MONO_TYPE_STRING
:
1738 case MONO_TYPE_CLASS
:
1739 case MONO_TYPE_OBJECT
:
1740 case MONO_TYPE_ARRAY
:
1741 case MONO_TYPE_SZARRAY
:
1745 case MONO_TYPE_BOOLEAN
:
1746 mono_mb_emit_byte (mb
, CEE_UNBOX
);
1747 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, mono_class_from_mono_type (return_type
)));
1748 mono_mb_emit_byte (mb
, CEE_LDIND_U1
);
1751 mono_mb_emit_byte (mb
, CEE_UNBOX
);
1752 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, mono_class_from_mono_type (return_type
)));
1753 mono_mb_emit_byte (mb
, CEE_LDIND_I1
);
1756 case MONO_TYPE_CHAR
:
1757 mono_mb_emit_byte (mb
, CEE_UNBOX
);
1758 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, mono_class_from_mono_type (return_type
)));
1759 mono_mb_emit_byte (mb
, CEE_LDIND_U2
);
1762 mono_mb_emit_byte (mb
, CEE_UNBOX
);
1763 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, mono_class_from_mono_type (return_type
)));
1764 mono_mb_emit_byte (mb
, CEE_LDIND_I2
);
1768 mono_mb_emit_byte (mb
, CEE_UNBOX
);
1769 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, mono_class_from_mono_type (return_type
)));
1770 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
1773 mono_mb_emit_byte (mb
, CEE_UNBOX
);
1774 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, mono_class_from_mono_type (return_type
)));
1775 mono_mb_emit_byte (mb
, CEE_LDIND_I4
);
1778 mono_mb_emit_byte (mb
, CEE_UNBOX
);
1779 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, mono_class_from_mono_type (return_type
)));
1780 mono_mb_emit_byte (mb
, CEE_LDIND_U4
);
1784 mono_mb_emit_byte (mb
, CEE_UNBOX
);
1785 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, mono_class_from_mono_type (return_type
)));
1786 mono_mb_emit_byte (mb
, CEE_LDIND_I8
);
1789 mono_mb_emit_byte (mb
, CEE_UNBOX
);
1790 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, mono_class_from_mono_type (return_type
)));
1791 mono_mb_emit_byte (mb
, CEE_LDIND_R4
);
1794 mono_mb_emit_byte (mb
, CEE_UNBOX
);
1795 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, mono_class_from_mono_type (return_type
)));
1796 mono_mb_emit_byte (mb
, CEE_LDIND_R8
);
1798 case MONO_TYPE_VALUETYPE
: {
1800 mono_mb_emit_byte (mb
, CEE_UNBOX
);
1801 class = mono_mb_add_data (mb
, mono_class_from_mono_type (return_type
));
1802 mono_mb_emit_i4 (mb
, class);
1803 mono_mb_emit_byte (mb
, CEE_LDOBJ
);
1804 mono_mb_emit_i4 (mb
, class);
1808 g_warning ("type 0x%x not handled", return_type
->type
);
1809 g_assert_not_reached ();
1812 mono_mb_emit_byte (mb
, CEE_RET
);
1816 mono_marshal_get_delegate_end_invoke (MonoMethod
*method
)
1818 MonoMethodSignature
*sig
;
1819 static MonoMethodSignature
*csig
= NULL
;
1820 MonoMethodBuilder
*mb
;
1826 g_assert (method
&& method
->klass
->parent
== mono_defaults
.multicastdelegate_class
&&
1827 !strcmp (method
->name
, "EndInvoke"));
1829 sig
= method
->signature
;
1831 cache
= method
->klass
->image
->delegate_end_invoke_cache
;
1832 if ((res
= mono_marshal_find_in_cache (cache
, sig
)))
1835 g_assert (sig
->hasthis
);
1838 csig
= mono_metadata_signature_alloc (method
->klass
->image
, 2);
1840 /* MonoObject *end_invoke (MonoDelegate *delegate, gpointer params[]) */
1841 csig
->ret
= &mono_defaults
.object_class
->byval_arg
;
1842 csig
->params
[0] = &mono_defaults
.object_class
->byval_arg
;
1843 csig
->params
[1] = &mono_defaults
.int_class
->byval_arg
;
1846 name
= mono_signature_to_name (sig
, "end_invoke");
1847 mb
= mono_mb_new (mono_defaults
.multicastdelegate_class
, name
, MONO_WRAPPER_DELEGATE_END_INVOKE
);
1850 mb
->method
->save_lmf
= 1;
1852 params_var
= mono_mb_emit_save_args (mb
, sig
, FALSE
);
1854 mono_mb_emit_ldarg (mb
, 0);
1855 mono_mb_emit_ldloc (mb
, params_var
);
1856 mono_mb_emit_native_call (mb
, csig
, mono_delegate_end_invoke
);
1857 emit_thread_interrupt_checkpoint (mb
);
1859 if (sig
->ret
->type
== MONO_TYPE_VOID
) {
1860 mono_mb_emit_byte (mb
, CEE_POP
);
1861 mono_mb_emit_byte (mb
, CEE_RET
);
1863 mono_mb_emit_restore_result (mb
, sig
->ret
);
1865 res
= mono_mb_create_and_cache (cache
, sig
,
1866 mb
, sig
, sig
->param_count
+ 16);
1873 mono_remoting_wrapper (MonoMethod
*method
, gpointer
*params
)
1875 MonoMethodMessage
*msg
;
1876 MonoTransparentProxy
*this;
1877 MonoObject
*res
, *exc
;
1878 MonoArray
*out_args
;
1880 this = *((MonoTransparentProxy
**)params
[0]);
1883 g_assert (((MonoObject
*)this)->vtable
->klass
== mono_defaults
.transparent_proxy_class
);
1885 /* skip the this pointer */
1888 if (this->remote_class
->proxy_class
->contextbound
&& this->rp
->context
== (MonoObject
*) mono_context_get ())
1891 MonoMethodSignature
*sig
= method
->signature
;
1892 int count
= sig
->param_count
;
1893 gpointer
* mparams
= (gpointer
*) alloca(count
*sizeof(gpointer
));
1895 for (i
=0; i
<count
; i
++) {
1896 MonoClass
*class = mono_class_from_mono_type (sig
->params
[i
]);
1897 if (class->valuetype
) {
1898 if (sig
->params
[i
]->byref
)
1899 mparams
[i
] = *((gpointer
*)params
[i
]);
1901 mparams
[i
] = params
[i
];
1903 mparams
[i
] = *((gpointer
**)params
[i
]);
1907 return mono_runtime_invoke (method
, method
->klass
->valuetype
? mono_object_unbox ((MonoObject
*)this): this, mparams
, NULL
);
1910 msg
= mono_method_call_message_new (method
, params
, NULL
, NULL
, NULL
);
1912 res
= mono_remoting_invoke ((MonoObject
*)this->rp
, msg
, &exc
, &out_args
);
1915 mono_raise_exception ((MonoException
*)exc
);
1917 mono_method_return_message_restore (method
, params
, out_args
);
1923 mono_marshal_get_remoting_invoke (MonoMethod
*method
)
1925 MonoMethodSignature
*sig
;
1926 static MonoMethodSignature
*csig
= NULL
;
1927 MonoMethodBuilder
*mb
;
1934 if (method
->wrapper_type
== MONO_WRAPPER_REMOTING_INVOKE
)
1937 sig
= method
->signature
;
1939 /* we cant remote methods without this pointer */
1943 cache
= method
->klass
->image
->remoting_invoke_cache
;
1944 if ((res
= mono_marshal_find_in_cache (cache
, method
)))
1948 csig
= mono_metadata_signature_alloc (mono_defaults
.corlib
, 2);
1949 csig
->params
[0] = &mono_defaults
.int_class
->byval_arg
;
1950 csig
->params
[1] = &mono_defaults
.int_class
->byval_arg
;
1951 csig
->ret
= &mono_defaults
.object_class
->byval_arg
;
1955 mb
= mono_mb_new (method
->klass
, method
->name
, MONO_WRAPPER_REMOTING_INVOKE
);
1956 mb
->method
->save_lmf
= 1;
1958 params_var
= mono_mb_emit_save_args (mb
, sig
, TRUE
);
1960 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
1961 mono_mb_emit_byte (mb
, CEE_MONO_LDPTR
);
1962 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, method
));
1963 mono_mb_emit_ldloc (mb
, params_var
);
1964 mono_mb_emit_native_call (mb
, csig
, mono_remoting_wrapper
);
1965 emit_thread_interrupt_checkpoint (mb
);
1967 if (sig
->ret
->type
== MONO_TYPE_VOID
) {
1968 mono_mb_emit_byte (mb
, CEE_POP
);
1969 mono_mb_emit_byte (mb
, CEE_RET
);
1971 mono_mb_emit_restore_result (mb
, sig
->ret
);
1974 res
= mono_mb_create_and_cache (cache
, method
, mb
, sig
, sig
->param_count
+ 16);
1981 mono_marshal_get_remoting_invoke_with_check (MonoMethod
*method
)
1983 MonoMethodSignature
*sig
;
1984 MonoMethodBuilder
*mb
;
1985 MonoMethod
*res
, *native
;
1991 if (method
->wrapper_type
== MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK
)
1994 sig
= method
->signature
;
1996 /* we cant remote methods without this pointer */
1997 g_assert (sig
->hasthis
);
1999 cache
= method
->klass
->image
->remoting_invoke_cache
;
2000 if ((res
= mono_marshal_find_in_cache (cache
, (char *)method
+ 1)))
2003 mb
= mono_mb_new (method
->klass
, method
->name
, MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK
);
2005 mono_mb_emit_ldarg (mb
, 0);
2006 pos
= mono_mb_emit_proxy_check (mb
, CEE_BNE_UN
);
2008 native
= mono_marshal_get_remoting_invoke (method
);
2010 for (i
= 0; i
<= sig
->param_count
; i
++)
2011 mono_mb_emit_ldarg (mb
, i
);
2013 mono_mb_emit_managed_call (mb
, native
, native
->signature
);
2014 mono_mb_emit_byte (mb
, CEE_RET
);
2016 mono_mb_patch_addr (mb
, pos
, mb
->pos
- (pos
+ 4));
2018 for (i
= 0; i
<= sig
->param_count
; i
++)
2019 mono_mb_emit_ldarg (mb
, i
);
2021 mono_mb_emit_managed_call (mb
, method
, method
->signature
);
2022 mono_mb_emit_byte (mb
, CEE_RET
);
2024 res
= mono_mb_create_and_cache (cache
, (char*)method
+ 1,
2025 mb
, sig
, sig
->param_count
+ 16);
2032 * the returned method invokes all methods in a multicast delegate
2035 mono_marshal_get_delegate_invoke (MonoMethod
*method
)
2037 MonoMethodSignature
*sig
, *static_sig
;
2039 MonoMethodBuilder
*mb
;
2045 g_assert (method
&& method
->klass
->parent
== mono_defaults
.multicastdelegate_class
&&
2046 !strcmp (method
->name
, "Invoke"));
2048 sig
= method
->signature
;
2050 cache
= method
->klass
->image
->delegate_invoke_cache
;
2051 if ((res
= mono_marshal_find_in_cache (cache
, sig
)))
2054 static_sig
= mono_metadata_signature_dup (sig
);
2055 static_sig
->hasthis
= 0;
2057 name
= mono_signature_to_name (sig
, "invoke");
2058 mb
= mono_mb_new (mono_defaults
.multicastdelegate_class
, name
, MONO_WRAPPER_DELEGATE_INVOKE
);
2061 /* allocate local 0 (object) */
2062 mono_mb_add_local (mb
, &mono_defaults
.object_class
->byval_arg
);
2064 g_assert (sig
->hasthis
);
2068 * prev.Invoke( args .. );
2069 * return this.<target>( args .. );
2072 /* this wrapper can be used in unmanaged-managed transitions */
2073 emit_thread_interrupt_checkpoint (mb
);
2075 /* get this->prev */
2076 mono_mb_emit_ldarg (mb
, 0);
2077 mono_mb_emit_ldflda (mb
, G_STRUCT_OFFSET (MonoMulticastDelegate
, prev
));
2078 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
2079 mono_mb_emit_stloc (mb
, 0);
2081 /* if prev != null */
2082 mono_mb_emit_ldloc (mb
, 0);
2083 mono_mb_emit_byte (mb
, CEE_BRFALSE
);
2086 mono_mb_emit_i4 (mb
, 0);
2089 mono_mb_emit_ldloc (mb
, 0);
2090 for (i
= 0; i
< sig
->param_count
; i
++)
2091 mono_mb_emit_ldarg (mb
, i
+ 1);
2092 mono_mb_emit_managed_call (mb
, method
, method
->signature
);
2093 if (sig
->ret
->type
!= MONO_TYPE_VOID
)
2094 mono_mb_emit_byte (mb
, CEE_POP
);
2096 /* continued or prev == null */
2097 mono_mb_patch_addr (mb
, pos0
, mb
->pos
- (pos0
+ 4));
2099 /* get this->target */
2100 mono_mb_emit_ldarg (mb
, 0);
2101 mono_mb_emit_ldflda (mb
, G_STRUCT_OFFSET (MonoDelegate
, target
));
2102 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
2103 mono_mb_emit_stloc (mb
, 0);
2105 /* if target != null */
2106 mono_mb_emit_ldloc (mb
, 0);
2107 mono_mb_emit_byte (mb
, CEE_BRFALSE
);
2109 mono_mb_emit_i4 (mb
, 0);
2111 /* then call this->method_ptr nonstatic */
2112 mono_mb_emit_ldloc (mb
, 0);
2113 for (i
= 0; i
< sig
->param_count
; ++i
)
2114 mono_mb_emit_ldarg (mb
, i
+ 1);
2115 mono_mb_emit_ldarg (mb
, 0);
2116 mono_mb_emit_ldflda (mb
, G_STRUCT_OFFSET (MonoDelegate
, method_ptr
));
2117 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
2118 mono_mb_emit_byte (mb
, CEE_CALLI
);
2119 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, sig
));
2121 mono_mb_emit_byte (mb
, CEE_BR
);
2123 mono_mb_emit_i4 (mb
, 0);
2125 /* else [target == null] call this->method_ptr static */
2126 mono_mb_patch_addr (mb
, pos0
, mb
->pos
- (pos0
+ 4));
2128 for (i
= 0; i
< sig
->param_count
; ++i
)
2129 mono_mb_emit_ldarg (mb
, i
+ 1);
2130 mono_mb_emit_ldarg (mb
, 0);
2131 mono_mb_emit_ldflda (mb
, G_STRUCT_OFFSET (MonoDelegate
, method_ptr
));
2132 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
2133 mono_mb_emit_byte (mb
, CEE_CALLI
);
2134 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, static_sig
));
2137 mono_mb_patch_addr (mb
, pos1
, mb
->pos
- (pos1
+ 4));
2138 mono_mb_emit_byte (mb
, CEE_RET
);
2140 res
= mono_mb_create_and_cache (cache
, sig
,
2141 mb
, sig
, sig
->param_count
+ 16);
2148 * signature_dup_add_this:
2150 * Make a copy of @sig, adding an explicit this argument.
2152 static MonoMethodSignature
*
2153 signature_dup_add_this (MonoMethodSignature
*sig
, MonoClass
*klass
)
2155 MonoMethodSignature
*res
;
2158 res
= mono_metadata_signature_alloc (klass
->image
, sig
->param_count
+ 1);
2159 memcpy (res
, sig
, sizeof (MonoMethodSignature
));
2160 res
->param_count
= sig
->param_count
+ 1;
2161 res
->hasthis
= FALSE
;
2162 for (i
= sig
->param_count
- 1; i
>= 0; i
--)
2163 res
->params
[i
+ 1] = sig
->params
[i
];
2164 res
->params
[0] = &mono_ptr_class_get (&klass
->byval_arg
)->byval_arg
;
2171 MonoMethodSignature
*sig
;
2177 * generates IL code for the runtime invoke function
2178 * MonoObject *runtime_invoke (MonoObject *this, void **params, MonoObject **exc, void* method)
2180 * we also catch exceptions if exc != null
2183 mono_marshal_get_runtime_invoke (MonoMethod
*method
)
2185 MonoMethodSignature
*sig
, *csig
, *callsig
;
2186 MonoExceptionClause
*clause
;
2187 MonoMethodHeader
*header
;
2188 MonoMethodBuilder
*mb
;
2189 GHashTable
*cache
= NULL
;
2190 MonoClass
*target_klass
;
2191 MonoMethod
*res
= NULL
;
2193 static MonoString
*string_dummy
= NULL
;
2194 static MonoMethodSignature
*dealy_abort_sig
= NULL
;
2200 target_klass
= method
->klass
;
2202 EnterCriticalSection (&marshal_mutex
);
2204 if (method
->string_ctor
) {
2205 static GSList
*strsig_list
= NULL
;
2209 for (item
= strsig_list
; item
; item
= item
->next
) {
2211 if (mono_metadata_signature_equal (method
->signature
, cs
->ctor
->signature
)) {
2217 callsig
= mono_metadata_signature_dup (method
->signature
);
2218 callsig
->ret
= &mono_defaults
.string_class
->byval_arg
;
2219 cs
= g_new (CtorSigPair
, 1);
2222 strsig_list
= g_slist_prepend (strsig_list
, cs
);
2225 if (method
->klass
->valuetype
&& method
->signature
->hasthis
) {
2227 * Valuetype methods receive a managed pointer as the this argument.
2228 * Create a new signature to reflect this.
2230 callsig
= signature_dup_add_this (method
->signature
, method
->klass
);
2233 callsig
= method
->signature
;
2236 cache
= method
->klass
->image
->runtime_invoke_cache
;
2238 /* from mono_marshal_find_in_cache */
2239 res
= g_hash_table_lookup (cache
, callsig
);
2240 LeaveCriticalSection (&marshal_mutex
);
2246 if (!dealy_abort_sig
) {
2247 dealy_abort_sig
= mono_metadata_signature_alloc (mono_defaults
.corlib
, 0);
2248 dealy_abort_sig
->ret
= &mono_defaults
.void_class
->byval_arg
;
2249 dealy_abort_sig
->pinvoke
= 0;
2252 target_klass
= mono_defaults
.object_class
;
2254 /* to make it work with our special string constructors */
2255 if (!string_dummy
) {
2256 MONO_GC_REGISTER_ROOT (string_dummy
);
2257 string_dummy
= mono_string_new_wrapper ("dummy");
2260 sig
= method
->signature
;
2262 csig
= mono_metadata_signature_alloc (method
->klass
->image
, 4);
2264 csig
->ret
= &mono_defaults
.object_class
->byval_arg
;
2265 if (method
->klass
->valuetype
&& method
->signature
->hasthis
)
2266 csig
->params
[0] = callsig
->params
[0];
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] = &mono_defaults
.int_class
->byval_arg
;
2273 name
= mono_signature_to_name (callsig
, "runtime_invoke");
2274 mb
= mono_mb_new (target_klass
, name
, MONO_WRAPPER_RUNTIME_INVOKE
);
2277 /* allocate local 0 (object) tmp */
2278 mono_mb_add_local (mb
, &mono_defaults
.object_class
->byval_arg
);
2279 /* allocate local 1 (object) exc */
2280 mono_mb_add_local (mb
, &mono_defaults
.object_class
->byval_arg
);
2282 /* cond set *exc to null */
2283 mono_mb_emit_byte (mb
, CEE_LDARG_2
);
2284 mono_mb_emit_byte (mb
, CEE_BRFALSE_S
);
2285 mono_mb_emit_byte (mb
, 3);
2286 mono_mb_emit_byte (mb
, CEE_LDARG_2
);
2287 mono_mb_emit_byte (mb
, CEE_LDNULL
);
2288 mono_mb_emit_byte (mb
, CEE_STIND_I
);
2291 if (method
->string_ctor
) {
2292 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
2293 mono_mb_emit_byte (mb
, CEE_MONO_LDPTR
);
2294 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, string_dummy
));
2296 mono_mb_emit_ldarg (mb
, 0);
2300 for (i
= 0; i
< sig
->param_count
; i
++) {
2301 MonoType
*t
= sig
->params
[i
];
2304 mono_mb_emit_ldarg (mb
, 1);
2306 mono_mb_emit_icon (mb
, sizeof (gpointer
) * i
);
2307 mono_mb_emit_byte (mb
, CEE_ADD
);
2309 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
2314 type
= sig
->params
[i
]->type
;
2318 mono_mb_emit_byte (mb
, CEE_LDIND_I1
);
2320 case MONO_TYPE_BOOLEAN
:
2322 mono_mb_emit_byte (mb
, CEE_LDIND_U1
);
2325 mono_mb_emit_byte (mb
, CEE_LDIND_I2
);
2328 case MONO_TYPE_CHAR
:
2329 mono_mb_emit_byte (mb
, CEE_LDIND_U2
);
2333 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
2336 mono_mb_emit_byte (mb
, CEE_LDIND_I4
);
2339 mono_mb_emit_byte (mb
, CEE_LDIND_U4
);
2342 mono_mb_emit_byte (mb
, CEE_LDIND_R4
);
2345 mono_mb_emit_byte (mb
, CEE_LDIND_R8
);
2349 mono_mb_emit_byte (mb
, CEE_LDIND_I8
);
2351 case MONO_TYPE_STRING
:
2352 case MONO_TYPE_CLASS
:
2353 case MONO_TYPE_ARRAY
:
2355 case MONO_TYPE_SZARRAY
:
2356 case MONO_TYPE_OBJECT
:
2359 case MONO_TYPE_VALUETYPE
:
2360 if (t
->data
.klass
->enumtype
) {
2361 type
= t
->data
.klass
->enum_basetype
->type
;
2364 mono_mb_emit_byte (mb
, CEE_LDOBJ
);
2365 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, t
->data
.klass
));
2368 g_assert_not_reached ();
2372 mono_mb_emit_ldarg (mb
, 3);
2373 emit_thread_force_interrupt_checkpoint (mb
);
2374 mono_mb_emit_calli (mb
, callsig
);
2376 if (sig
->ret
->byref
) {
2378 g_assert_not_reached ();
2382 switch (sig
->ret
->type
) {
2383 case MONO_TYPE_VOID
:
2384 if (!method
->string_ctor
)
2385 mono_mb_emit_byte (mb
, CEE_LDNULL
);
2387 case MONO_TYPE_BOOLEAN
:
2388 case MONO_TYPE_CHAR
:
2401 case MONO_TYPE_VALUETYPE
:
2402 /* box value types */
2403 mono_mb_emit_byte (mb
, CEE_BOX
);
2404 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, mono_class_from_mono_type (sig
->ret
)));
2406 case MONO_TYPE_STRING
:
2407 case MONO_TYPE_CLASS
:
2408 case MONO_TYPE_ARRAY
:
2409 case MONO_TYPE_SZARRAY
:
2410 case MONO_TYPE_OBJECT
:
2415 g_assert_not_reached ();
2418 mono_mb_emit_stloc (mb
, 0);
2420 mono_mb_emit_byte (mb
, CEE_LEAVE
);
2422 mono_mb_emit_i4 (mb
, 0);
2424 clause
= g_new0 (MonoExceptionClause
, 1);
2425 clause
->flags
= MONO_EXCEPTION_CLAUSE_FILTER
;
2426 clause
->try_len
= mb
->pos
;
2429 clause
->token_or_filter
= mb
->pos
;
2431 mono_mb_emit_byte (mb
, CEE_POP
);
2432 mono_mb_emit_byte (mb
, CEE_LDARG_2
);
2433 mono_mb_emit_byte (mb
, CEE_LDC_I4_0
);
2434 mono_mb_emit_byte (mb
, CEE_PREFIX1
);
2435 mono_mb_emit_byte (mb
, CEE_CGT_UN
);
2436 mono_mb_emit_byte (mb
, CEE_PREFIX1
);
2437 mono_mb_emit_byte (mb
, CEE_ENDFILTER
);
2439 clause
->handler_offset
= mb
->pos
;
2442 /* store exception */
2443 mono_mb_emit_stloc (mb
, 1);
2445 mono_mb_emit_byte (mb
, CEE_LDARG_2
);
2446 mono_mb_emit_ldloc (mb
, 1);
2447 mono_mb_emit_byte (mb
, CEE_STIND_I
);
2449 mono_mb_emit_byte (mb
, CEE_LDC_I4_0
);
2450 mono_mb_emit_stloc (mb
, 0);
2452 /* Check for the abort exception */
2453 mono_mb_emit_ldloc (mb
, 1);
2454 mono_mb_emit_byte (mb
, CEE_ISINST
);
2455 mono_mb_emit_i4 (mb
, mono_defaults
.threadabortexception_class
->type_token
);
2456 mono_mb_emit_byte (mb
, CEE_BRFALSE_S
);
2458 mono_mb_emit_byte (mb
, 0);
2460 /* Delay the abort exception */
2461 mono_mb_emit_native_call (mb
, dealy_abort_sig
, ves_icall_System_Threading_Thread_ResetAbort
);
2463 mono_mb_patch_addr_s (mb
, posna
, mb
->pos
- posna
- 1);
2464 mono_mb_emit_byte (mb
, CEE_LEAVE
);
2465 mono_mb_emit_i4 (mb
, 0);
2467 clause
->handler_len
= mb
->pos
- clause
->handler_offset
;
2470 mono_mb_patch_addr (mb
, pos
, mb
->pos
- (pos
+ 4));
2471 mono_mb_emit_ldloc (mb
, 0);
2472 mono_mb_emit_byte (mb
, CEE_RET
);
2474 /* taken from mono_mb_create_and_cache */
2475 EnterCriticalSection (&marshal_mutex
);
2477 res
= g_hash_table_lookup (cache
, callsig
);
2478 /* Somebody may have created it before us */
2480 res
= mono_mb_create_method (mb
, csig
, sig
->param_count
+ 16);
2481 g_hash_table_insert (cache
, callsig
, res
);
2482 mono_g_hash_table_insert (wrapper_hash
, res
, callsig
);
2485 LeaveCriticalSection (&marshal_mutex
);
2486 /* end mono_mb_create_and_cache */
2490 header
= ((MonoMethodNormal
*)res
)->header
;
2491 header
->num_clauses
= 1;
2492 header
->clauses
= clause
;
2498 raise_auto_layout_exception (MonoClass
*klass
)
2500 char *msg
= g_strdup_printf ("The type `%s.%s' layout needs to be Sequential or Explicit",
2501 klass
->name_space
, klass
->name
);
2503 MonoException
*e
= mono_exception_from_name_msg (
2504 mono_get_corlib (), "System.Runtime.InteropServices",
2505 "MarshalDirectiveException", msg
);
2507 mono_raise_exception (e
);
2511 * generates IL code to call managed methods from unmanaged code
2514 mono_marshal_get_managed_wrapper (MonoMethod
*method
, MonoObject
*this, MonoMarshalSpec
**mspecs
)
2516 MonoMethodSignature
*sig
, *csig
;
2517 MonoMethodBuilder
*mb
;
2518 MonoClass
*klass
= NULL
;
2521 int i
, pos
= 0, *tmp_locals
;
2522 static MonoMethodSignature
*alloc_sig
= NULL
;
2525 g_assert (method
!= NULL
);
2526 g_assert (!method
->signature
->pinvoke
);
2528 cache
= method
->klass
->image
->managed_wrapper_cache
;
2529 if (!this && (res
= mono_marshal_find_in_cache (cache
, method
)))
2532 /* Under MS, the allocation should be done using CoTaskMemAlloc */
2534 alloc_sig
= mono_metadata_signature_alloc (mono_defaults
.corlib
, 1);
2535 alloc_sig
->params
[0] = &mono_defaults
.int_class
->byval_arg
;
2536 alloc_sig
->ret
= &mono_defaults
.int_class
->byval_arg
;
2537 alloc_sig
->pinvoke
= 1;
2540 sig
= method
->signature
;
2542 mb
= mono_mb_new (method
->klass
, method
->name
, MONO_WRAPPER_NATIVE_TO_MANAGED
);
2544 /* allocate local 0 (pointer) src_ptr */
2545 mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
2546 /* allocate local 1 (pointer) dst_ptr */
2547 mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
2548 /* allocate local 2 (boolean) delete_old */
2549 mono_mb_add_local (mb
, &mono_defaults
.boolean_class
->byval_arg
);
2551 if (!MONO_TYPE_IS_VOID(sig
->ret
)) {
2552 /* allocate local 3 to store the return value */
2553 mono_mb_add_local (mb
, sig
->ret
);
2556 mono_mb_emit_icon (mb
, 0);
2557 mono_mb_emit_byte (mb
, CEE_STLOC_2
);
2559 /* we copy the signature, so that we can modify it */
2560 csig
= mono_metadata_signature_dup (sig
);
2564 #ifdef PLATFORM_WIN32
2566 * Under windows, delegates passed to native code must use the STDCALL
2567 * calling convention.
2569 csig
->call_convention
= MONO_CALL_STDCALL
;
2572 /* fixme: howto handle this ? */
2576 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
2577 mono_mb_emit_byte (mb
, CEE_MONO_LDPTR
);
2578 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, this));
2583 g_assert_not_reached ();
2588 /* we first do all conversions */
2589 tmp_locals
= alloca (sizeof (int) * sig
->param_count
);
2590 for (i
= 0; i
< sig
->param_count
; i
++) {
2591 MonoType
*t
= sig
->params
[i
];
2592 MonoMarshalSpec
*spec
= mspecs
[i
+ 1];
2596 /* Ensure that we have marshalling info for this param */
2597 mono_marshal_load_type_info (mono_class_from_mono_type (t
));
2599 if (spec
&& spec
->native
== MONO_NATIVE_CUSTOM
) {
2602 MonoMethod
*marshal_native_to_managed
;
2603 MonoMethod
*get_instance
;
2605 mtype
= mono_reflection_type_from_name (spec
->data
.custom_data
.custom_name
, method
->klass
->image
);
2606 g_assert (mtype
!= NULL
);
2607 mklass
= mono_class_from_mono_type (mtype
);
2608 g_assert (mklass
!= NULL
);
2610 marshal_native_to_managed
= mono_find_method_by_name (mklass
, "MarshalNativeToManaged", 1);
2611 g_assert (marshal_native_to_managed
);
2612 get_instance
= mono_find_method_by_name (mklass
, "GetInstance", 1);
2613 g_assert (get_instance
);
2616 case MONO_TYPE_CLASS
:
2617 case MONO_TYPE_OBJECT
:
2618 case MONO_TYPE_STRING
:
2619 case MONO_TYPE_ARRAY
:
2620 case MONO_TYPE_SZARRAY
:
2624 tmp_locals
[i
] = mono_mb_add_local (mb
, &mono_defaults
.object_class
->byval_arg
);
2626 mono_mb_emit_ldstr (mb
, g_strdup (spec
->data
.custom_data
.cookie
));
2628 mono_mb_emit_byte (mb
, CEE_CALL
);
2629 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, get_instance
));
2631 mono_mb_emit_ldarg (mb
, i
);
2633 mono_mb_emit_byte (mb
, CEE_CALLVIRT
);
2634 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, marshal_native_to_managed
));
2636 mono_mb_emit_stloc (mb
, tmp_locals
[i
]);
2639 g_warning ("custom marshalling of type %x is currently not supported", t
->type
);
2640 g_assert_not_reached ();
2647 case MONO_TYPE_CLASS
: {
2648 klass
= t
->data
.klass
;
2650 tmp_locals
[i
] = mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
2652 if (klass
->delegate
) {
2653 g_assert (!t
->byref
);
2654 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
2655 mono_mb_emit_byte (mb
, CEE_MONO_LDPTR
);
2656 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, klass
));
2657 mono_mb_emit_ldarg (mb
, i
);
2658 mono_mb_emit_icall (mb
, conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL
));
2659 mono_mb_emit_stloc (mb
, tmp_locals
[i
]);
2663 /* The class can not have an automatic layout */
2664 if ((klass
->flags
& TYPE_ATTRIBUTE_LAYOUT_MASK
) == TYPE_ATTRIBUTE_AUTO_LAYOUT
)
2665 raise_auto_layout_exception (klass
);
2667 if (t
->attrs
& PARAM_ATTRIBUTE_OUT
) {
2668 mono_mb_emit_byte (mb
, CEE_LDNULL
);
2669 mono_mb_emit_stloc (mb
, tmp_locals
[i
]);
2674 mono_mb_emit_ldarg (mb
, i
);
2678 /* Check for NULL and raise an exception */
2679 mono_mb_emit_byte (mb
, CEE_BRTRUE
);
2681 mono_mb_emit_i4 (mb
, 0);
2683 mono_mb_emit_exception (mb
, "ArgumentNullException", NULL
);
2685 mono_mb_patch_addr (mb
, pos2
, mb
->pos
- (pos2
+ 4));
2686 mono_mb_emit_ldarg (mb
, i
);
2687 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
2690 mono_mb_emit_byte (mb
, CEE_STLOC_0
);
2692 mono_mb_emit_byte (mb
, CEE_LDC_I4_0
);
2693 mono_mb_emit_stloc (mb
, tmp_locals
[i
]);
2695 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
2696 mono_mb_emit_byte (mb
, CEE_BRFALSE
);
2698 mono_mb_emit_i4 (mb
, 0);
2700 /* Create and set dst */
2701 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
2702 mono_mb_emit_byte (mb
, CEE_MONO_NEWOBJ
);
2703 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, klass
));
2704 mono_mb_emit_stloc (mb
, tmp_locals
[i
]);
2705 mono_mb_emit_ldloc (mb
, tmp_locals
[i
]);
2706 mono_mb_emit_icon (mb
, sizeof (MonoObject
));
2707 mono_mb_emit_byte (mb
, CEE_ADD
);
2708 mono_mb_emit_byte (mb
, CEE_STLOC_1
);
2710 /* emit valuetype conversion code */
2711 emit_struct_conv (mb
, klass
, TRUE
);
2713 mono_mb_patch_addr (mb
, pos
, mb
->pos
- (pos
+ 4));
2716 case MONO_TYPE_VALUETYPE
:
2718 klass
= sig
->params
[i
]->data
.klass
;
2719 if (((klass
->flags
& TYPE_ATTRIBUTE_LAYOUT_MASK
) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT
) ||
2720 klass
->blittable
|| klass
->enumtype
)
2723 tmp_locals
[i
] = mono_mb_add_local (mb
, &klass
->byval_arg
);
2725 if (t
->attrs
& PARAM_ATTRIBUTE_OUT
)
2729 mono_mb_emit_ldarg (mb
, i
);
2731 mono_mb_emit_ldarg_addr (mb
, i
);
2732 mono_mb_emit_byte (mb
, CEE_STLOC_0
);
2735 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
2736 mono_mb_emit_byte (mb
, CEE_BRFALSE
);
2738 mono_mb_emit_i4 (mb
, 0);
2741 mono_mb_emit_ldloc_addr (mb
, tmp_locals
[i
]);
2742 mono_mb_emit_byte (mb
, CEE_STLOC_1
);
2744 /* emit valuetype conversion code */
2745 emit_struct_conv (mb
, klass
, TRUE
);
2748 mono_mb_patch_addr (mb
, pos
, mb
->pos
- (pos
+ 4));
2750 case MONO_TYPE_STRING
: {
2751 MonoMarshalNative encoding
= mono_marshal_get_string_encoding (NULL
, spec
);
2756 tmp_locals
[i
] = mono_mb_add_local (mb
, &mono_defaults
.object_class
->byval_arg
);
2757 csig
->params
[i
] = &mono_defaults
.int_class
->byval_arg
;
2759 mono_mb_emit_ldarg (mb
, i
);
2762 case MONO_NATIVE_LPWSTR
:
2763 mono_mb_emit_icall (mb
, conv_to_icall (MONO_MARSHAL_CONV_LPWSTR_STR
));
2765 case MONO_NATIVE_LPSTR
:
2766 mono_mb_emit_icall (mb
, conv_to_icall (MONO_MARSHAL_CONV_LPSTR_STR
));
2769 char *msg
= g_strdup_printf ("string marshalling conversion %d not implemented", encoding
);
2770 MonoException
*exc
= mono_get_exception_not_implemented (msg
);
2773 mono_raise_exception (exc
);
2777 mono_mb_emit_stloc (mb
, tmp_locals
[i
]);
2780 case MONO_TYPE_ARRAY
:
2781 case MONO_TYPE_SZARRAY
:
2785 klass
= mono_class_from_mono_type (t
);
2787 tmp_locals
[i
] = mono_mb_add_local (mb
, &mono_defaults
.object_class
->byval_arg
);
2788 csig
->params
[i
] = &mono_defaults
.int_class
->byval_arg
;
2790 g_warning ("array marshaling not implemented");
2791 g_assert_not_reached ();
2796 for (i
= 0; i
< sig
->param_count
; i
++) {
2797 MonoType
*t
= sig
->params
[i
];
2800 case MONO_TYPE_BOOLEAN
:
2814 mono_mb_emit_ldarg (mb
, i
);
2816 case MONO_TYPE_STRING
:
2818 mono_mb_emit_ldarg (mb
, i
);
2820 g_assert (tmp_locals
[i
]);
2821 mono_mb_emit_ldloc (mb
, tmp_locals
[i
]);
2824 case MONO_TYPE_CLASS
:
2826 mono_mb_emit_ldloc_addr (mb
, tmp_locals
[i
]);
2828 mono_mb_emit_ldloc (mb
, tmp_locals
[i
]);
2830 case MONO_TYPE_ARRAY
:
2831 case MONO_TYPE_SZARRAY
:
2832 case MONO_TYPE_OBJECT
:
2834 mono_mb_emit_ldloc (mb
, tmp_locals
[i
]);
2836 mono_mb_emit_ldarg (mb
, i
);
2838 case MONO_TYPE_VALUETYPE
:
2839 klass
= sig
->params
[i
]->data
.klass
;
2840 if (((klass
->flags
& TYPE_ATTRIBUTE_LAYOUT_MASK
) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT
) ||
2841 klass
->blittable
|| klass
->enumtype
) {
2842 mono_mb_emit_ldarg (mb
, i
);
2846 g_assert (tmp_locals
[i
]);
2848 mono_mb_emit_ldloc_addr (mb
, tmp_locals
[i
]);
2850 mono_mb_emit_ldloc (mb
, tmp_locals
[i
]);
2853 g_warning ("type 0x%02x unknown", t
->type
);
2854 g_assert_not_reached ();
2858 emit_thread_interrupt_checkpoint (mb
);
2859 mono_mb_emit_managed_call (mb
, method
, NULL
);
2861 /* Ensure that we have marshalling info for the return */
2862 mono_marshal_load_type_info (mono_class_from_mono_type (sig
->ret
));
2864 if (mspecs
[0] && mspecs
[0]->native
== MONO_NATIVE_CUSTOM
) {
2865 MonoMarshalSpec
*spec
= mspecs
[0];
2870 g_assert (!sig
->ret
->byref
);
2872 mtype
= mono_reflection_type_from_name (spec
->data
.custom_data
.custom_name
, method
->klass
->image
);
2874 mklass
= mono_class_from_mono_type (mtype
);
2877 loc1
= mono_mb_add_local (mb
, &mono_defaults
.object_class
->byval_arg
);
2879 switch (sig
->ret
->type
) {
2880 case MONO_TYPE_CLASS
:
2881 case MONO_TYPE_OBJECT
:
2882 case MONO_TYPE_STRING
:
2883 case MONO_TYPE_ARRAY
:
2884 case MONO_TYPE_SZARRAY
:
2885 mono_mb_emit_byte (mb
, CEE_STLOC_3
);
2887 mono_mb_emit_byte (mb
, CEE_LDLOC_3
);
2888 mono_mb_emit_stloc (mb
, loc1
);
2890 mono_mb_emit_ldstr (mb
, g_strdup (spec
->data
.custom_data
.cookie
));
2891 mono_mb_emit_byte (mb
, CEE_CALL
);
2892 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, mono_find_method_by_name (mklass
, "GetInstance", 1)));
2893 mono_mb_emit_byte (mb
, CEE_DUP
);
2895 mono_mb_emit_byte (mb
, CEE_LDLOC_3
);
2896 mono_mb_emit_byte (mb
, CEE_CALLVIRT
);
2897 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, mono_find_method_by_name (mklass
, "MarshalManagedToNative", 1)));
2898 mono_mb_emit_byte (mb
, CEE_STLOC_3
);
2900 mono_mb_emit_ldloc (mb
, loc1
);
2901 mono_mb_emit_byte (mb
, CEE_CALLVIRT
);
2902 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, mono_find_method_by_name (mklass
, "CleanUpManagedData", 1)));
2906 g_warning ("custom marshalling of type %x is currently not supported", sig
->ret
->type
);
2907 g_assert_not_reached ();
2912 if (!sig
->ret
->byref
) {
2913 switch (sig
->ret
->type
) {
2914 case MONO_TYPE_VOID
:
2916 case MONO_TYPE_BOOLEAN
:
2930 case MONO_TYPE_OBJECT
:
2931 mono_mb_emit_byte (mb
, CEE_STLOC_3
);
2933 case MONO_TYPE_STRING
:
2934 csig
->ret
= &mono_defaults
.int_class
->byval_arg
;
2936 mono_mb_emit_icall (mb
, conv_to_icall (MONO_MARSHAL_CONV_STR_LPSTR
));
2937 mono_mb_emit_byte (mb
, CEE_STLOC_3
);
2939 case MONO_TYPE_VALUETYPE
:
2940 klass
= sig
->ret
->data
.klass
;
2941 if (((klass
->flags
& TYPE_ATTRIBUTE_LAYOUT_MASK
) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT
) ||
2942 klass
->blittable
|| klass
->enumtype
)
2945 /* load pointer to returned value type */
2946 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
2947 mono_mb_emit_byte (mb
, CEE_MONO_VTADDR
);
2949 /* store the address of the source into local variable 0 */
2950 mono_mb_emit_byte (mb
, CEE_STLOC_0
);
2951 /* allocate space for the native struct and
2952 * store the address into dst_ptr */
2953 retobj_var
= mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
2954 g_assert (retobj_var
);
2955 mono_mb_emit_icon (mb
, mono_class_native_size (klass
, NULL
));
2956 mono_mb_emit_byte (mb
, CEE_CONV_I
);
2957 mono_mb_emit_native_call (mb
, alloc_sig
, mono_marshal_alloc
);
2958 emit_thread_interrupt_checkpoint (mb
);
2959 mono_mb_emit_byte (mb
, CEE_STLOC_1
);
2960 mono_mb_emit_byte (mb
, CEE_LDLOC_1
);
2961 mono_mb_emit_stloc (mb
, retobj_var
);
2963 /* emit valuetype conversion code */
2964 emit_struct_conv (mb
, klass
, FALSE
);
2966 case MONO_TYPE_CLASS
: {
2969 klass
= sig
->ret
->data
.klass
;
2971 if (klass
->delegate
) {
2972 mono_mb_emit_icall (mb
, conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN
));
2973 mono_mb_emit_byte (mb
, CEE_STLOC_3
);
2977 /* The class can not have an automatic layout */
2978 if ((klass
->flags
& TYPE_ATTRIBUTE_LAYOUT_MASK
) == TYPE_ATTRIBUTE_AUTO_LAYOUT
)
2979 raise_auto_layout_exception (klass
);
2981 mono_mb_emit_byte (mb
, CEE_STLOC_0
);
2982 /* Check for null */
2983 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
2984 pos
= mono_mb_emit_branch (mb
, CEE_BRTRUE
);
2985 mono_mb_emit_byte (mb
, CEE_LDNULL
);
2986 mono_mb_emit_byte (mb
, CEE_STLOC_3
);
2987 pos2
= mono_mb_emit_branch (mb
, CEE_BR
);
2989 mono_mb_patch_addr (mb
, pos
, mb
->pos
- (pos
+ 4));
2992 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
2993 mono_mb_emit_icon (mb
, sizeof (MonoObject
));
2994 mono_mb_emit_byte (mb
, CEE_ADD
);
2995 mono_mb_emit_byte (mb
, CEE_STLOC_0
);
2997 /* Allocate and set dest */
2998 mono_mb_emit_icon (mb
, mono_class_native_size (klass
, NULL
));
2999 mono_mb_emit_byte (mb
, CEE_CONV_I
);
3000 mono_mb_emit_native_call (mb
, alloc_sig
, mono_marshal_alloc
);
3001 emit_thread_interrupt_checkpoint (mb
);
3002 mono_mb_emit_byte (mb
, CEE_DUP
);
3003 mono_mb_emit_byte (mb
, CEE_STLOC_1
);
3004 mono_mb_emit_byte (mb
, CEE_STLOC_3
);
3006 emit_struct_conv (mb
, klass
, FALSE
);
3008 mono_mb_patch_addr (mb
, pos2
, mb
->pos
- (pos2
+ 4));
3012 g_warning ("return type 0x%02x unknown", sig
->ret
->type
);
3013 g_assert_not_reached ();
3016 mono_mb_emit_byte (mb
, CEE_STLOC_3
);
3019 /* Convert byref arguments back */
3020 for (i
= 0; i
< sig
->param_count
; i
++) {
3021 MonoType
*t
= sig
->params
[i
];
3022 MonoMarshalSpec
*spec
= mspecs
[i
+ 1];
3024 if (spec
&& spec
->native
== MONO_NATIVE_CUSTOM
) {
3027 MonoMethod
*cleanup_managed
;
3028 MonoMethod
*get_instance
;
3030 mtype
= mono_reflection_type_from_name (spec
->data
.custom_data
.custom_name
, method
->klass
->image
);
3031 g_assert (mtype
!= NULL
);
3032 mklass
= mono_class_from_mono_type (mtype
);
3033 g_assert (mklass
!= NULL
);
3035 get_instance
= mono_find_method_by_name (mklass
, "GetInstance", 1);
3036 g_assert (get_instance
);
3037 cleanup_managed
= mono_find_method_by_name (mklass
, "CleanUpManagedData", 1);
3038 g_assert (cleanup_managed
);
3041 case MONO_TYPE_CLASS
:
3042 case MONO_TYPE_OBJECT
:
3043 case MONO_TYPE_STRING
:
3044 case MONO_TYPE_ARRAY
:
3045 case MONO_TYPE_SZARRAY
:
3047 g_assert_not_reached ();
3049 /* Call CleanUpManagedData */
3051 mono_mb_emit_ldstr (mb
, g_strdup (spec
->data
.custom_data
.cookie
));
3053 mono_mb_emit_byte (mb
, CEE_CALL
);
3054 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, get_instance
));
3056 mono_mb_emit_ldloc (mb
, tmp_locals
[i
]);
3057 mono_mb_emit_byte (mb
, CEE_CALLVIRT
);
3058 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, cleanup_managed
));
3062 g_warning ("custom marshalling of type %x is currently not supported", t
->type
);
3063 g_assert_not_reached ();
3073 case MONO_TYPE_CLASS
: {
3076 klass
= t
->data
.klass
;
3078 /* Check for null */
3079 mono_mb_emit_ldloc (mb
, tmp_locals
[i
]);
3080 pos
= mono_mb_emit_branch (mb
, CEE_BRTRUE
);
3081 mono_mb_emit_ldarg (mb
, i
);
3082 mono_mb_emit_byte (mb
, CEE_LDC_I4_0
);
3083 mono_mb_emit_byte (mb
, CEE_STIND_I
);
3084 pos2
= mono_mb_emit_branch (mb
, CEE_BR
);
3086 mono_mb_patch_addr (mb
, pos
, mb
->pos
- (pos
+ 4));
3089 mono_mb_emit_ldloc (mb
, tmp_locals
[i
]);
3090 mono_mb_emit_icon (mb
, sizeof (MonoObject
));
3091 mono_mb_emit_byte (mb
, CEE_ADD
);
3092 mono_mb_emit_byte (mb
, CEE_STLOC_0
);
3094 /* Allocate and set dest */
3095 mono_mb_emit_icon (mb
, mono_class_native_size (klass
, NULL
));
3096 mono_mb_emit_byte (mb
, CEE_CONV_I
);
3097 mono_mb_emit_native_call (mb
, alloc_sig
, mono_marshal_alloc
);
3098 emit_thread_interrupt_checkpoint (mb
);
3099 mono_mb_emit_byte (mb
, CEE_STLOC_1
);
3101 /* Update argument pointer */
3102 mono_mb_emit_ldarg (mb
, i
);
3103 mono_mb_emit_byte (mb
, CEE_LDLOC_1
);
3104 mono_mb_emit_byte (mb
, CEE_STIND_I
);
3106 /* emit valuetype conversion code */
3107 emit_struct_conv (mb
, klass
, FALSE
);
3109 mono_mb_patch_addr (mb
, pos2
, mb
->pos
- (pos2
+ 4));
3112 case MONO_TYPE_VALUETYPE
: {
3115 klass
= t
->data
.klass
;
3117 if (((klass
->flags
& TYPE_ATTRIBUTE_LAYOUT_MASK
) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT
) ||
3118 klass
->blittable
|| klass
->enumtype
) {
3122 /* Check for null */
3123 mono_mb_emit_ldarg (mb
, i
);
3124 pos2
= mono_mb_emit_branch (mb
, CEE_BRFALSE
);
3127 mono_mb_emit_ldloc_addr (mb
, tmp_locals
[i
]);
3128 mono_mb_emit_byte (mb
, CEE_STLOC_0
);
3131 mono_mb_emit_ldarg (mb
, i
);
3132 mono_mb_emit_byte (mb
, CEE_STLOC_1
);
3134 /* emit valuetype conversion code */
3135 emit_struct_conv (mb
, klass
, FALSE
);
3137 mono_mb_patch_addr (mb
, pos2
, mb
->pos
- (pos2
+ 4));
3144 mono_mb_emit_ldloc (mb
, retobj_var
);
3145 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
3146 mono_mb_emit_byte (mb
, CEE_MONO_RETOBJ
);
3147 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, klass
));
3150 if (!MONO_TYPE_IS_VOID(sig
->ret
))
3151 mono_mb_emit_byte (mb
, CEE_LDLOC_3
);
3152 mono_mb_emit_byte (mb
, CEE_RET
);
3156 res
= mono_mb_create_and_cache (cache
, method
,
3157 mb
, csig
, sig
->param_count
+ 16);
3159 res
= mono_mb_create_method (mb
, csig
, sig
->param_count
+ 16);
3164 /* printf ("CODE FOR %s: \n%s.\n", mono_method_full_name (res, TRUE), mono_disasm_code (0, res, ((MonoMethodNormal*)res)->header->code, ((MonoMethodNormal*)res)->header->code + ((MonoMethodNormal*)res)->header->code_size)); */
3170 * mono_marshal_get_ldfld_wrapper:
3171 * @type: the type of the field
3173 * This method generates a function which can be use to load a field with type
3174 * @type from an object. The generated function has the following signature:
3175 * <@type> ldfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset)
3178 mono_marshal_get_ldfld_wrapper (MonoType
*type
)
3180 MonoMethodSignature
*sig
, *csig
;
3181 MonoMethodBuilder
*mb
;
3184 static GHashTable
*ldfld_hash
= NULL
;
3186 int t
, pos0
, pos1
= 0;
3191 if (type
->type
== MONO_TYPE_SZARRAY
) {
3192 klass
= mono_defaults
.array_class
;
3193 } else if (type
->type
== MONO_TYPE_VALUETYPE
) {
3194 klass
= type
->data
.klass
;
3195 if (klass
->enumtype
) {
3196 t
= klass
->enum_basetype
->type
;
3197 klass
= mono_class_from_mono_type (klass
->enum_basetype
);
3199 } else if (t
== MONO_TYPE_OBJECT
|| t
== MONO_TYPE_CLASS
|| t
== MONO_TYPE_STRING
||
3200 t
== MONO_TYPE_CLASS
) {
3201 klass
= mono_defaults
.object_class
;
3202 } else if (t
== MONO_TYPE_PTR
|| t
== MONO_TYPE_FNPTR
) {
3203 klass
= mono_defaults
.int_class
;
3205 klass
= mono_class_from_mono_type (type
);
3208 klass
= mono_defaults
.int_class
;
3211 EnterCriticalSection (&marshal_mutex
);
3213 ldfld_hash
= g_hash_table_new (NULL
, NULL
);
3214 res
= g_hash_table_lookup (ldfld_hash
, klass
);
3215 LeaveCriticalSection (&marshal_mutex
);
3219 name
= g_strdup_printf ("__ldfld_wrapper_%s.%s", klass
->name_space
, klass
->name
);
3220 mb
= mono_mb_new (mono_defaults
.object_class
, name
, MONO_WRAPPER_LDFLD
);
3223 mb
->method
->save_lmf
= 1;
3225 sig
= mono_metadata_signature_alloc (mono_defaults
.corlib
, 4);
3226 sig
->params
[0] = &mono_defaults
.object_class
->byval_arg
;
3227 sig
->params
[1] = &mono_defaults
.int_class
->byval_arg
;
3228 sig
->params
[2] = &mono_defaults
.int_class
->byval_arg
;
3229 sig
->params
[3] = &mono_defaults
.int_class
->byval_arg
;
3230 sig
->ret
= &klass
->byval_arg
;
3232 mono_mb_emit_ldarg (mb
, 0);
3233 pos0
= mono_mb_emit_proxy_check (mb
, CEE_BNE_UN
);
3235 mono_mb_emit_ldarg (mb
, 0);
3236 mono_mb_emit_ldarg (mb
, 1);
3237 mono_mb_emit_ldarg (mb
, 2);
3239 csig
= mono_metadata_signature_alloc (mono_defaults
.corlib
, 3);
3240 csig
->params
[0] = &mono_defaults
.object_class
->byval_arg
;
3241 csig
->params
[1] = &mono_defaults
.int_class
->byval_arg
;
3242 csig
->params
[2] = &mono_defaults
.int_class
->byval_arg
;
3243 csig
->ret
= &klass
->this_arg
;
3246 mono_mb_emit_native_call (mb
, csig
, mono_load_remote_field_new
);
3247 emit_thread_interrupt_checkpoint (mb
);
3249 if (klass
->valuetype
) {
3250 mono_mb_emit_byte (mb
, CEE_UNBOX
);
3251 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, klass
));
3252 mono_mb_emit_byte (mb
, CEE_BR
);
3254 mono_mb_emit_i4 (mb
, 0);
3256 mono_mb_emit_byte (mb
, CEE_RET
);
3260 mono_mb_patch_addr (mb
, pos0
, mb
->pos
- (pos0
+ 4));
3262 mono_mb_emit_ldarg (mb
, 0);
3263 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
3264 mono_mb_emit_byte (mb
, CEE_MONO_OBJADDR
);
3265 mono_mb_emit_ldarg (mb
, 3);
3266 mono_mb_emit_byte (mb
, CEE_ADD
);
3268 if (klass
->valuetype
)
3269 mono_mb_patch_addr (mb
, pos1
, mb
->pos
- (pos1
+ 4));
3274 case MONO_TYPE_BOOLEAN
:
3275 mono_mb_emit_byte (mb
, CEE_LDIND_I1
);
3277 case MONO_TYPE_CHAR
:
3280 mono_mb_emit_byte (mb
, CEE_LDIND_I2
);
3284 mono_mb_emit_byte (mb
, CEE_LDIND_I4
);
3288 mono_mb_emit_byte (mb
, CEE_LDIND_I8
);
3291 mono_mb_emit_byte (mb
, CEE_LDIND_R4
);
3294 mono_mb_emit_byte (mb
, CEE_LDIND_R8
);
3296 case MONO_TYPE_ARRAY
:
3298 case MONO_TYPE_FNPTR
:
3299 case MONO_TYPE_SZARRAY
:
3300 case MONO_TYPE_OBJECT
:
3301 case MONO_TYPE_CLASS
:
3302 case MONO_TYPE_STRING
:
3305 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
3307 case MONO_TYPE_VALUETYPE
:
3308 g_assert (!klass
->enumtype
);
3309 mono_mb_emit_byte (mb
, CEE_LDOBJ
);
3310 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, klass
));
3313 g_warning ("type %x not implemented", type
->type
);
3314 g_assert_not_reached ();
3317 mono_mb_emit_byte (mb
, CEE_RET
);
3319 res
= mono_mb_create_and_cache (ldfld_hash
, klass
,
3320 mb
, sig
, sig
->param_count
+ 16);
3327 * mono_marshal_get_stfld_wrapper:
3328 * @type: the type of the field
3330 * This method generates a function which can be use to store a field with type
3331 * @type. The generated function has the following signature:
3332 * void stfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset, <@type> val)
3335 mono_marshal_get_stfld_wrapper (MonoType
*type
)
3337 MonoMethodSignature
*sig
, *csig
;
3338 MonoMethodBuilder
*mb
;
3341 static GHashTable
*stfld_hash
= NULL
;
3348 if (type
->type
== MONO_TYPE_SZARRAY
) {
3349 klass
= mono_defaults
.array_class
;
3350 } else if (type
->type
== MONO_TYPE_VALUETYPE
) {
3351 klass
= type
->data
.klass
;
3352 if (klass
->enumtype
) {
3353 t
= klass
->enum_basetype
->type
;
3354 klass
= mono_class_from_mono_type (klass
->enum_basetype
);
3356 } else if (t
== MONO_TYPE_OBJECT
|| t
== MONO_TYPE_CLASS
|| t
== MONO_TYPE_STRING
||
3357 t
== MONO_TYPE_CLASS
) {
3358 klass
= mono_defaults
.object_class
;
3359 } else if (t
== MONO_TYPE_PTR
|| t
== MONO_TYPE_FNPTR
) {
3360 klass
= mono_defaults
.int_class
;
3362 klass
= mono_class_from_mono_type (type
);
3365 klass
= mono_defaults
.int_class
;
3368 EnterCriticalSection (&marshal_mutex
);
3370 stfld_hash
= g_hash_table_new (NULL
, NULL
);
3371 res
= g_hash_table_lookup (stfld_hash
, klass
);
3372 LeaveCriticalSection (&marshal_mutex
);
3376 name
= g_strdup_printf ("__stfld_wrapper_%s.%s", klass
->name_space
, klass
->name
);
3377 mb
= mono_mb_new (mono_defaults
.object_class
, name
, MONO_WRAPPER_STFLD
);
3380 mb
->method
->save_lmf
= 1;
3382 sig
= mono_metadata_signature_alloc (mono_defaults
.corlib
, 5);
3383 sig
->params
[0] = &mono_defaults
.object_class
->byval_arg
;
3384 sig
->params
[1] = &mono_defaults
.int_class
->byval_arg
;
3385 sig
->params
[2] = &mono_defaults
.int_class
->byval_arg
;
3386 sig
->params
[3] = &mono_defaults
.int_class
->byval_arg
;
3387 sig
->params
[4] = &klass
->byval_arg
;
3388 sig
->ret
= &mono_defaults
.void_class
->byval_arg
;
3390 mono_mb_emit_ldarg (mb
, 0);
3391 pos
= mono_mb_emit_proxy_check (mb
, CEE_BNE_UN
);
3393 mono_mb_emit_ldarg (mb
, 0);
3394 mono_mb_emit_ldarg (mb
, 1);
3395 mono_mb_emit_ldarg (mb
, 2);
3396 mono_mb_emit_ldarg (mb
, 4);
3398 if (klass
->valuetype
) {
3399 mono_mb_emit_byte (mb
, CEE_BOX
);
3400 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, klass
));
3403 csig
= mono_metadata_signature_alloc (mono_defaults
.corlib
, 4);
3404 csig
->params
[0] = &mono_defaults
.object_class
->byval_arg
;
3405 csig
->params
[1] = &mono_defaults
.int_class
->byval_arg
;
3406 csig
->params
[2] = &mono_defaults
.int_class
->byval_arg
;
3407 csig
->params
[3] = &klass
->this_arg
;
3408 csig
->ret
= &mono_defaults
.void_class
->byval_arg
;
3411 mono_mb_emit_native_call (mb
, csig
, mono_store_remote_field_new
);
3412 emit_thread_interrupt_checkpoint (mb
);
3414 mono_mb_emit_byte (mb
, CEE_RET
);
3416 mono_mb_patch_addr (mb
, pos
, mb
->pos
- (pos
+ 4));
3418 mono_mb_emit_ldarg (mb
, 0);
3419 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
3420 mono_mb_emit_byte (mb
, CEE_MONO_OBJADDR
);
3421 mono_mb_emit_ldarg (mb
, 3);
3422 mono_mb_emit_byte (mb
, CEE_ADD
);
3423 mono_mb_emit_ldarg (mb
, 4);
3428 case MONO_TYPE_BOOLEAN
:
3429 mono_mb_emit_byte (mb
, CEE_STIND_I1
);
3431 case MONO_TYPE_CHAR
:
3434 mono_mb_emit_byte (mb
, CEE_STIND_I2
);
3438 mono_mb_emit_byte (mb
, CEE_STIND_I4
);
3442 mono_mb_emit_byte (mb
, CEE_STIND_I8
);
3445 mono_mb_emit_byte (mb
, CEE_STIND_R4
);
3448 mono_mb_emit_byte (mb
, CEE_STIND_R8
);
3450 case MONO_TYPE_ARRAY
:
3452 case MONO_TYPE_FNPTR
:
3453 case MONO_TYPE_SZARRAY
:
3454 case MONO_TYPE_OBJECT
:
3455 case MONO_TYPE_CLASS
:
3456 case MONO_TYPE_STRING
:
3459 mono_mb_emit_byte (mb
, CEE_STIND_I
);
3461 case MONO_TYPE_VALUETYPE
:
3462 g_assert (!klass
->enumtype
);
3463 mono_mb_emit_byte (mb
, CEE_STOBJ
);
3464 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, klass
));
3467 g_warning ("type %x not implemented", type
->type
);
3468 g_assert_not_reached ();
3471 mono_mb_emit_byte (mb
, CEE_RET
);
3473 res
= mono_mb_create_and_cache (stfld_hash
, klass
,
3474 mb
, sig
, sig
->param_count
+ 16);
3481 * generates IL code for the icall wrapper (the generated method
3482 * calls the unmanaged code in func)
3485 mono_marshal_get_icall_wrapper (MonoMethodSignature
*sig
, const char *name
, gconstpointer func
)
3487 MonoMethodSignature
*csig
;
3488 MonoMethodBuilder
*mb
;
3492 g_assert (sig
->pinvoke
);
3494 mb
= mono_mb_new (mono_defaults
.object_class
, name
, MONO_WRAPPER_MANAGED_TO_NATIVE
);
3496 mb
->method
->save_lmf
= 1;
3498 /* we copy the signature, so that we can modify it */
3501 mono_mb_emit_byte (mb
, CEE_LDARG_0
);
3503 for (i
= 0; i
< sig
->param_count
; i
++)
3504 mono_mb_emit_ldarg (mb
, i
+ sig
->hasthis
);
3506 mono_mb_emit_native_call (mb
, sig
, (gpointer
) func
);
3507 emit_thread_interrupt_checkpoint (mb
);
3508 mono_mb_emit_byte (mb
, CEE_RET
);
3510 csig
= mono_metadata_signature_dup (sig
);
3512 if (csig
->call_convention
== MONO_CALL_VARARG
)
3513 csig
->call_convention
= 0;
3515 res
= mono_mb_create_method (mb
, csig
, csig
->param_count
+ 16);
3522 MonoMethodBuilder
*mb
;
3523 MonoMethodPInvoke
*piinfo
;
3524 int *orig_conv_args
; /* Locals containing the original values of byref args */
3525 } EmitMarshalContext
;
3528 MARSHAL_ACTION_CONV_IN
,
3529 MARSHAL_ACTION_PUSH
,
3530 MARSHAL_ACTION_CONV_OUT
,
3531 MARSHAL_ACTION_CONV_RESULT
3535 emit_marshal_custom (EmitMarshalContext
*m
, int argnum
, MonoType
*t
,
3536 MonoMarshalSpec
*spec
,
3537 int conv_arg
, MonoType
**conv_arg_type
,
3538 MarshalAction action
)
3542 MonoMethod
*get_instance
, *cleanup_native
;
3543 MonoMethod
*marshal_managed_to_native
, *marshal_native_to_managed
;
3544 MonoMethodBuilder
*mb
= m
->mb
;
3547 mtype
= mono_reflection_type_from_name (spec
->data
.custom_data
.custom_name
, mb
->method
->klass
->image
);
3548 g_assert (mtype
!= NULL
);
3549 mklass
= mono_class_from_mono_type (mtype
);
3550 g_assert (mklass
!= NULL
);
3552 get_instance
= mono_find_method_by_name (mklass
, "GetInstance", 1);
3553 g_assert (get_instance
);
3554 cleanup_native
= mono_find_method_by_name (mklass
, "CleanUpNativeData", 1);
3555 g_assert (cleanup_native
);
3556 marshal_managed_to_native
= mono_find_method_by_name (mklass
, "MarshalManagedToNative", 1);
3557 g_assert (marshal_managed_to_native
);
3558 marshal_native_to_managed
= mono_find_method_by_name (mklass
, "MarshalNativeToManaged", 1);
3559 g_assert (marshal_native_to_managed
);
3562 case MARSHAL_ACTION_CONV_IN
:
3564 case MONO_TYPE_CLASS
:
3565 case MONO_TYPE_OBJECT
:
3566 case MONO_TYPE_STRING
:
3567 case MONO_TYPE_ARRAY
:
3568 case MONO_TYPE_SZARRAY
:
3569 case MONO_TYPE_VALUETYPE
:
3573 conv_arg
= mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
3575 mono_mb_emit_ldstr (mb
, g_strdup (spec
->data
.custom_data
.cookie
));
3577 mono_mb_emit_byte (mb
, CEE_CALL
);
3578 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, get_instance
));
3580 mono_mb_emit_ldarg (mb
, argnum
);
3582 if (t
->type
== MONO_TYPE_VALUETYPE
) {
3584 * Since we can't determine the type of the argument, we
3585 * will assume the unmanaged function takes a pointer.
3587 *conv_arg_type
= &mono_defaults
.int_class
->byval_arg
;
3589 mono_mb_emit_byte (mb
, CEE_BOX
);
3590 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, mono_class_from_mono_type (t
)));
3593 mono_mb_emit_byte (mb
, CEE_CALLVIRT
);
3594 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, marshal_managed_to_native
));
3595 mono_mb_emit_stloc (mb
, conv_arg
);
3599 g_warning ("custom marshalling of type %x is currently not supported", t
->type
);
3600 g_assert_not_reached ();
3606 case MARSHAL_ACTION_CONV_OUT
:
3608 case MONO_TYPE_CLASS
:
3609 case MONO_TYPE_OBJECT
:
3610 case MONO_TYPE_STRING
:
3611 case MONO_TYPE_ARRAY
:
3612 case MONO_TYPE_SZARRAY
:
3613 case MONO_TYPE_VALUETYPE
:
3614 mono_mb_emit_ldstr (mb
, g_strdup (spec
->data
.custom_data
.cookie
));
3616 mono_mb_emit_byte (mb
, CEE_CALL
);
3617 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, get_instance
));
3619 mono_mb_emit_ldloc (mb
, conv_arg
);
3621 mono_mb_emit_byte (mb
, CEE_CALLVIRT
);
3622 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, cleanup_native
));
3627 g_warning ("custom marshalling of type %x is currently not supported", t
->type
);
3628 g_assert_not_reached ();
3633 case MARSHAL_ACTION_PUSH
:
3634 mono_mb_emit_ldloc (mb
, conv_arg
);
3637 case MARSHAL_ACTION_CONV_RESULT
:
3638 loc1
= mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
3641 case MONO_TYPE_CLASS
:
3642 case MONO_TYPE_OBJECT
:
3643 case MONO_TYPE_STRING
:
3644 case MONO_TYPE_ARRAY
:
3645 case MONO_TYPE_SZARRAY
:
3646 mono_mb_emit_byte (mb
, CEE_STLOC_3
);
3648 mono_mb_emit_byte (mb
, CEE_LDLOC_3
);
3649 mono_mb_emit_stloc (mb
, loc1
);
3651 mono_mb_emit_ldstr (mb
, g_strdup (spec
->data
.custom_data
.cookie
));
3653 mono_mb_emit_byte (mb
, CEE_CALL
);
3654 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, get_instance
));
3655 mono_mb_emit_byte (mb
, CEE_DUP
);
3657 mono_mb_emit_byte (mb
, CEE_LDLOC_3
);
3658 mono_mb_emit_byte (mb
, CEE_CALLVIRT
);
3659 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, marshal_native_to_managed
));
3660 mono_mb_emit_byte (mb
, CEE_STLOC_3
);
3662 mono_mb_emit_ldloc (mb
, loc1
);
3663 mono_mb_emit_byte (mb
, CEE_CALLVIRT
);
3664 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, cleanup_native
));
3668 g_assert_not_reached ();
3674 g_assert_not_reached ();
3681 emit_marshal_asany (EmitMarshalContext
*m
, int argnum
, MonoType
*t
,
3682 MonoMarshalSpec
*spec
,
3683 int conv_arg
, MonoType
**conv_arg_type
,
3684 MarshalAction action
)
3686 MonoMethodBuilder
*mb
= m
->mb
;
3689 case MARSHAL_ACTION_CONV_IN
: {
3690 MonoMarshalNative encoding
= mono_marshal_get_string_encoding (m
->piinfo
, NULL
);
3692 g_assert (t
->type
== MONO_TYPE_OBJECT
);
3693 g_assert (!t
->byref
);
3695 conv_arg
= mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
3696 mono_mb_emit_ldarg (mb
, argnum
);
3697 mono_mb_emit_icon (mb
, encoding
);
3698 mono_mb_emit_icall (mb
, mono_marshal_asany
);
3699 mono_mb_emit_stloc (mb
, conv_arg
);
3703 case MARSHAL_ACTION_PUSH
:
3704 mono_mb_emit_ldloc (mb
, conv_arg
);
3707 case MARSHAL_ACTION_CONV_OUT
: {
3708 MonoMarshalNative encoding
= mono_marshal_get_string_encoding (m
->piinfo
, NULL
);
3710 mono_mb_emit_ldarg (mb
, argnum
);
3711 mono_mb_emit_ldloc (mb
, conv_arg
);
3712 mono_mb_emit_icon (mb
, encoding
);
3713 mono_mb_emit_icall (mb
, mono_marshal_free_asany
);
3718 g_assert_not_reached ();
3725 emit_marshal_vtype (EmitMarshalContext
*m
, int argnum
, MonoType
*t
,
3726 MonoMarshalSpec
*spec
,
3727 int conv_arg
, MonoType
**conv_arg_type
,
3728 MarshalAction action
)
3730 MonoMethodBuilder
*mb
= m
->mb
;
3734 klass
= t
->data
.klass
;
3737 case MARSHAL_ACTION_CONV_IN
:
3738 if (((klass
->flags
& TYPE_ATTRIBUTE_LAYOUT_MASK
) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT
) ||
3739 klass
->blittable
|| klass
->enumtype
)
3742 conv_arg
= mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
3744 /* store the address of the source into local variable 0 */
3746 mono_mb_emit_ldarg (mb
, argnum
);
3748 mono_mb_emit_ldarg_addr (mb
, argnum
);
3750 mono_mb_emit_byte (mb
, CEE_STLOC_0
);
3752 /* allocate space for the native struct and
3753 * store the address into local variable 1 (dest) */
3754 mono_mb_emit_icon (mb
, mono_class_native_size (klass
, NULL
));
3755 mono_mb_emit_byte (mb
, CEE_PREFIX1
);
3756 mono_mb_emit_byte (mb
, CEE_LOCALLOC
);
3757 mono_mb_emit_stloc (mb
, conv_arg
);
3760 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
3761 mono_mb_emit_byte (mb
, CEE_BRFALSE
);
3763 mono_mb_emit_i4 (mb
, 0);
3767 mono_mb_emit_ldloc (mb
, conv_arg
);
3768 mono_mb_emit_byte (mb
, CEE_STLOC_1
);
3770 /* emit valuetype conversion code */
3771 emit_struct_conv (mb
, klass
, FALSE
);
3774 mono_mb_patch_addr (mb
, pos
, mb
->pos
- (pos
+ 4));
3777 case MARSHAL_ACTION_PUSH
:
3778 if (((klass
->flags
& TYPE_ATTRIBUTE_LAYOUT_MASK
) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT
) ||
3779 klass
->blittable
|| klass
->enumtype
) {
3780 mono_mb_emit_ldarg (mb
, argnum
);
3783 mono_mb_emit_ldloc (mb
, conv_arg
);
3785 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
3786 mono_mb_emit_byte (mb
, CEE_MONO_LDNATIVEOBJ
);
3787 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, klass
));
3791 case MARSHAL_ACTION_CONV_OUT
:
3792 if (((klass
->flags
& TYPE_ATTRIBUTE_LAYOUT_MASK
) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT
) ||
3793 klass
->blittable
|| klass
->enumtype
)
3797 /* dst = argument */
3798 mono_mb_emit_ldarg (mb
, argnum
);
3799 mono_mb_emit_byte (mb
, CEE_STLOC_1
);
3801 mono_mb_emit_byte (mb
, CEE_LDLOC_1
);
3802 mono_mb_emit_byte (mb
, CEE_BRFALSE
);
3804 mono_mb_emit_i4 (mb
, 0);
3806 /* src = tmp_locals [i] */
3807 mono_mb_emit_ldloc (mb
, conv_arg
);
3808 mono_mb_emit_byte (mb
, CEE_STLOC_0
);
3810 /* emit valuetype conversion code */
3811 emit_struct_conv (mb
, klass
, TRUE
);
3814 emit_struct_free (mb
, klass
, conv_arg
);
3817 mono_mb_patch_addr (mb
, pos
, mb
->pos
- (pos
+ 4));
3820 case MARSHAL_ACTION_CONV_RESULT
:
3821 if (((klass
->flags
& TYPE_ATTRIBUTE_LAYOUT_MASK
) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT
) ||
3823 mono_mb_emit_byte (mb
, CEE_STLOC_3
);
3826 /* load pointer to returned value type */
3827 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
3828 mono_mb_emit_byte (mb
, CEE_MONO_VTADDR
);
3829 /* store the address of the source into local variable 0 */
3830 mono_mb_emit_byte (mb
, CEE_STLOC_0
);
3832 mono_mb_emit_ldloc_addr (mb
, 3);
3833 mono_mb_emit_byte (mb
, CEE_STLOC_1
);
3835 /* emit valuetype conversion code */
3836 emit_struct_conv (mb
, klass
, TRUE
);
3840 g_assert_not_reached ();
3847 emit_marshal_string (EmitMarshalContext
*m
, int argnum
, MonoType
*t
,
3848 MonoMarshalSpec
*spec
,
3849 int conv_arg
, MonoType
**conv_arg_type
,
3850 MarshalAction action
)
3852 MonoMethodBuilder
*mb
= m
->mb
;
3853 MonoMarshalNative encoding
= mono_marshal_get_string_encoding (m
->piinfo
, spec
);
3854 MonoMarshalConv conv
= mono_marshal_get_string_to_ptr_conv (m
->piinfo
, spec
);
3857 case MARSHAL_ACTION_CONV_IN
:
3858 *conv_arg_type
= &mono_defaults
.int_class
->byval_arg
;
3859 conv_arg
= mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
3862 if (t
->attrs
& PARAM_ATTRIBUTE_OUT
)
3865 mono_mb_emit_ldarg (mb
, argnum
);
3866 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
3868 mono_mb_emit_ldarg (mb
, argnum
);
3872 char *msg
= g_strdup_printf ("string marshalling conversion %d not implemented", encoding
);
3873 MonoException
*exc
= mono_get_exception_not_implemented (msg
);
3876 mono_raise_exception (exc
);
3879 mono_mb_emit_icall (mb
, conv_to_icall (conv
));
3881 mono_mb_emit_stloc (mb
, conv_arg
);
3884 case MARSHAL_ACTION_CONV_OUT
:
3885 if (t
->byref
&& (t
->attrs
& PARAM_ATTRIBUTE_OUT
)) {
3886 mono_mb_emit_ldarg (mb
, argnum
);
3887 mono_mb_emit_ldloc (mb
, conv_arg
);
3888 mono_mb_emit_icall (mb
, conv_to_icall (MONO_MARSHAL_CONV_LPSTR_STR
));
3889 mono_mb_emit_byte (mb
, CEE_STIND_I
);
3891 if (mono_marshal_need_free (t
, m
->piinfo
, spec
)) {
3892 mono_mb_emit_ldloc (mb
, conv_arg
);
3893 mono_mb_emit_icall (mb
, mono_marshal_free
);
3898 case MARSHAL_ACTION_CONV_RESULT
:
3899 mono_mb_emit_byte (mb
, CEE_STLOC_0
);
3900 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
3903 switch (spec
->native
) {
3904 case MONO_NATIVE_LPWSTR
:
3905 mono_mb_emit_icall (mb
, conv_to_icall (MONO_MARSHAL_CONV_LPWSTR_STR
));
3908 g_warning ("marshalling conversion not implemented");
3909 g_assert_not_reached ();
3912 mono_mb_emit_icall (mb
, conv_to_icall (MONO_MARSHAL_CONV_LPSTR_STR
));
3914 mono_mb_emit_byte (mb
, CEE_STLOC_3
);
3916 /* free the string */
3917 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
3918 mono_mb_emit_icall (mb
, g_free
);
3922 g_assert_not_reached ();
3929 emit_marshal_object (EmitMarshalContext
*m
, int argnum
, MonoType
*t
,
3930 MonoMarshalSpec
*spec
,
3931 int conv_arg
, MonoType
**conv_arg_type
,
3932 MarshalAction action
)
3934 MonoMethodBuilder
*mb
= m
->mb
;
3935 MonoClass
*klass
= t
->data
.klass
;
3939 case MARSHAL_ACTION_CONV_IN
:
3940 *conv_arg_type
= &mono_defaults
.int_class
->byval_arg
;
3941 conv_arg
= mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
3943 m
->orig_conv_args
[argnum
] = 0;
3945 if (klass
->delegate
) {
3946 g_assert (!t
->byref
);
3947 mono_mb_emit_ldarg (mb
, argnum
);
3948 mono_mb_emit_icall (mb
, conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN
));
3949 mono_mb_emit_stloc (mb
, conv_arg
);
3950 } else if (klass
== mono_defaults
.stringbuilder_class
) {
3951 MonoMarshalNative encoding
= mono_marshal_get_string_encoding (m
->piinfo
, spec
);
3952 MonoMarshalConv conv
= mono_marshal_get_stringbuilder_to_ptr_conv (m
->piinfo
, spec
);
3954 g_assert (!t
->byref
);
3955 mono_mb_emit_ldarg (mb
, argnum
);
3958 mono_mb_emit_icall (mb
, conv_to_icall (conv
));
3960 char *msg
= g_strdup_printf ("stringbuilder marshalling conversion %d not implemented", encoding
);
3961 MonoException
*exc
= mono_get_exception_not_implemented (msg
);
3964 mono_raise_exception (exc
);
3967 mono_mb_emit_stloc (mb
, conv_arg
);
3968 } else if (klass
->blittable
) {
3969 mono_mb_emit_ldarg (mb
, argnum
);
3970 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
3971 mono_mb_emit_byte (mb
, CEE_MONO_OBJADDR
);
3972 mono_mb_emit_icon (mb
, sizeof (MonoObject
));
3973 mono_mb_emit_byte (mb
, CEE_ADD
);
3974 mono_mb_emit_stloc (mb
, conv_arg
);
3977 mono_mb_emit_byte (mb
, CEE_LDNULL
);
3978 mono_mb_emit_stloc (mb
, conv_arg
);
3981 /* we dont need any conversions for out parameters */
3982 if (t
->attrs
& PARAM_ATTRIBUTE_OUT
)
3985 mono_mb_emit_ldarg (mb
, argnum
);
3986 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
3989 mono_mb_emit_ldarg (mb
, argnum
);
3990 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
3991 mono_mb_emit_byte (mb
, CEE_MONO_OBJADDR
);
3994 /* store the address of the source into local variable 0 */
3995 mono_mb_emit_byte (mb
, CEE_STLOC_0
);
3996 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
3997 mono_mb_emit_byte (mb
, CEE_BRFALSE
);
3999 mono_mb_emit_i4 (mb
, 0);
4001 /* allocate space for the native struct and store the address */
4002 mono_mb_emit_icon (mb
, mono_class_native_size (klass
, NULL
));
4003 mono_mb_emit_byte (mb
, CEE_PREFIX1
);
4004 mono_mb_emit_byte (mb
, CEE_LOCALLOC
);
4005 mono_mb_emit_stloc (mb
, conv_arg
);
4008 /* Need to store the original buffer so we can free it later */
4009 m
->orig_conv_args
[argnum
] = mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
4010 mono_mb_emit_ldloc (mb
, conv_arg
);
4011 mono_mb_emit_stloc (mb
, m
->orig_conv_args
[argnum
]);
4014 /* set the src_ptr */
4015 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
4016 mono_mb_emit_icon (mb
, sizeof (MonoObject
));
4017 mono_mb_emit_byte (mb
, CEE_ADD
);
4018 mono_mb_emit_byte (mb
, CEE_STLOC_0
);
4021 mono_mb_emit_ldloc (mb
, conv_arg
);
4022 mono_mb_emit_byte (mb
, CEE_STLOC_1
);
4024 /* emit valuetype conversion code */
4025 emit_struct_conv (mb
, klass
, FALSE
);
4027 mono_mb_patch_addr (mb
, pos
, mb
->pos
- (pos
+ 4));
4031 case MARSHAL_ACTION_CONV_OUT
:
4032 if (klass
== mono_defaults
.stringbuilder_class
) {
4034 MonoMarshalNative encoding
;
4035 MonoMarshalConv conv
;
4037 encoding
= mono_marshal_get_string_encoding (m
->piinfo
, spec
);
4038 conv
= mono_marshal_get_ptr_to_stringbuilder_conv (m
->piinfo
, spec
, &need_free
);
4040 g_assert (!t
->byref
);
4041 g_assert (encoding
!= -1);
4043 mono_mb_emit_ldarg (mb
, argnum
);
4044 mono_mb_emit_ldloc (mb
, conv_arg
);
4046 mono_mb_emit_icall (mb
, conv_to_icall (conv
));
4049 mono_mb_emit_ldloc (mb
, conv_arg
);
4050 mono_mb_emit_icall (mb
, mono_marshal_free
);
4055 if (klass
->delegate
)
4058 if (t
->byref
&& (t
->attrs
& PARAM_ATTRIBUTE_OUT
)) {
4059 /* allocate a new object */
4060 mono_mb_emit_ldarg (mb
, argnum
);
4061 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
4062 mono_mb_emit_byte (mb
, CEE_MONO_NEWOBJ
);
4063 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, t
->data
.klass
));
4064 mono_mb_emit_byte (mb
, CEE_STIND_I
);
4067 /* dst = *argument */
4068 mono_mb_emit_ldarg (mb
, argnum
);
4071 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
4073 mono_mb_emit_byte (mb
, CEE_STLOC_1
);
4075 mono_mb_emit_byte (mb
, CEE_LDLOC_1
);
4076 mono_mb_emit_byte (mb
, CEE_BRFALSE
);
4078 mono_mb_emit_i4 (mb
, 0);
4080 if (t
->byref
|| (t
->attrs
& PARAM_ATTRIBUTE_OUT
)) {
4081 mono_mb_emit_byte (mb
, CEE_LDLOC_1
);
4082 mono_mb_emit_icon (mb
, sizeof (MonoObject
));
4083 mono_mb_emit_byte (mb
, CEE_ADD
);
4084 mono_mb_emit_byte (mb
, CEE_STLOC_1
);
4086 /* src = tmp_locals [i] */
4087 mono_mb_emit_ldloc (mb
, conv_arg
);
4088 mono_mb_emit_byte (mb
, CEE_STLOC_0
);
4090 /* emit valuetype conversion code */
4091 emit_struct_conv (mb
, t
->data
.klass
, TRUE
);
4093 /* Free the structure returned by the native code */
4094 emit_struct_free (mb
, klass
, conv_arg
);
4096 if (m
->orig_conv_args
[argnum
]) {
4098 * If the native function changed the pointer, then free
4099 * the original structure plus the new pointer.
4101 mono_mb_emit_ldloc (mb
, m
->orig_conv_args
[argnum
]);
4102 mono_mb_emit_ldloc (mb
, conv_arg
);
4103 mono_mb_emit_byte (mb
, CEE_BEQ
);
4105 mono_mb_emit_i4 (mb
, 0);
4107 if (!(t
->attrs
& PARAM_ATTRIBUTE_OUT
)) {
4108 g_assert (m
->orig_conv_args
[argnum
]);
4110 emit_struct_free (mb
, klass
, m
->orig_conv_args
[argnum
]);
4113 mono_mb_emit_ldloc (mb
, conv_arg
);
4114 mono_mb_emit_icall (mb
, g_free
);
4116 mono_mb_patch_addr (mb
, pos2
, mb
->pos
- (pos2
+ 4));
4120 /* Free the original structure passed to native code */
4121 emit_struct_free (mb
, klass
, conv_arg
);
4123 mono_mb_patch_addr (mb
, pos
, mb
->pos
- (pos
+ 4));
4126 case MARSHAL_ACTION_CONV_RESULT
:
4127 if (klass
->delegate
) {
4128 g_assert (!t
->byref
);
4129 mono_mb_emit_byte (mb
, CEE_STLOC_0
);
4130 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
4131 mono_mb_emit_byte (mb
, CEE_MONO_LDPTR
);
4132 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, klass
));
4133 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
4134 mono_mb_emit_icall (mb
, conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL
));
4135 mono_mb_emit_byte (mb
, CEE_STLOC_3
);
4138 mono_mb_emit_byte (mb
, CEE_STLOC_0
);
4140 /* Make a copy since emit_conv modifies local 0 */
4141 loc
= mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
4142 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
4143 mono_mb_emit_stloc (mb
, loc
);
4145 mono_mb_emit_byte (mb
, CEE_LDNULL
);
4146 mono_mb_emit_byte (mb
, CEE_STLOC_3
);
4148 mono_mb_emit_byte (mb
, CEE_LDLOC_0
);
4149 mono_mb_emit_byte (mb
, CEE_BRFALSE
);
4151 mono_mb_emit_i4 (mb
, 0);
4153 /* allocate result object */
4155 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
4156 mono_mb_emit_byte (mb
, CEE_MONO_NEWOBJ
);
4157 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, klass
));
4158 mono_mb_emit_byte (mb
, CEE_STLOC_3
);
4162 mono_mb_emit_byte (mb
, CEE_LDLOC_3
);
4163 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
4164 mono_mb_emit_byte (mb
, CEE_MONO_OBJADDR
);
4165 mono_mb_emit_icon (mb
, sizeof (MonoObject
));
4166 mono_mb_emit_byte (mb
, CEE_ADD
);
4167 mono_mb_emit_byte (mb
, CEE_STLOC_1
);
4169 /* emit conversion code */
4170 emit_struct_conv (mb
, klass
, TRUE
);
4172 emit_struct_free (mb
, klass
, loc
);
4174 /* Free the pointer allocated by unmanaged code */
4175 mono_mb_emit_ldloc (mb
, loc
);
4176 mono_mb_emit_icall (mb
, g_free
);
4177 mono_mb_patch_addr (mb
, pos
, mb
->pos
- (pos
+ 4));
4182 g_assert_not_reached ();
4189 emit_marshal_array (EmitMarshalContext
*m
, int argnum
, MonoType
*t
,
4190 MonoMarshalSpec
*spec
,
4191 int conv_arg
, MonoType
**conv_arg_type
,
4192 MarshalAction action
)
4194 MonoMethodBuilder
*mb
= m
->mb
;
4195 MonoClass
*klass
= mono_class_from_mono_type (t
);
4196 gboolean need_convert
, need_free
;
4199 case MARSHAL_ACTION_CONV_IN
:
4200 *conv_arg_type
= &mono_defaults
.int_class
->byval_arg
;
4201 conv_arg
= mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
4203 if (klass
->element_class
->blittable
) {
4204 mono_mb_emit_ldarg (mb
, argnum
);
4206 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
4207 mono_mb_emit_icall (mb
, conv_to_icall (MONO_MARSHAL_CONV_ARRAY_LPARRAY
));
4208 mono_mb_emit_stloc (mb
, conv_arg
);
4212 guint32 label1
, label2
, label3
;
4213 int index_var
, src_var
, dest_ptr
, esize
;
4214 MonoMarshalNative encoding
;
4215 MonoMarshalConv conv
;
4216 gboolean is_string
= FALSE
;
4218 dest_ptr
= mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
4220 eklass
= klass
->element_class
;
4222 encoding
= mono_marshal_get_string_encoding (m
->piinfo
, spec
);
4223 if (eklass
== mono_defaults
.string_class
) {
4225 conv
= mono_marshal_get_string_to_ptr_conv (m
->piinfo
, spec
);
4227 else if (eklass
== mono_defaults
.stringbuilder_class
) {
4229 conv
= mono_marshal_get_stringbuilder_to_ptr_conv (m
->piinfo
, spec
);
4234 src_var
= mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
4235 mono_mb_emit_ldarg (mb
, argnum
);
4237 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
4238 mono_mb_emit_stloc (mb
, src_var
);
4241 mono_mb_emit_ldloc (mb
, src_var
);
4242 mono_mb_emit_stloc (mb
, conv_arg
);
4243 mono_mb_emit_ldloc (mb
, src_var
);
4244 mono_mb_emit_byte (mb
, CEE_BRFALSE
);
4246 mono_mb_emit_i4 (mb
, 0);
4250 char *msg
= g_strdup_printf ("string/stringbuilder marshalling conversion %d not implemented", encoding
);
4251 MonoException
*exc
= mono_get_exception_not_implemented (msg
);
4254 mono_raise_exception (exc
);
4259 esize
= sizeof (gpointer
);
4261 esize
= mono_class_native_size (eklass
, NULL
);
4263 /* allocate space for the native struct and store the address */
4264 mono_mb_emit_icon (mb
, esize
);
4265 mono_mb_emit_ldloc (mb
, src_var
);
4266 mono_mb_emit_byte (mb
, CEE_LDLEN
);
4268 if (eklass
== mono_defaults
.string_class
) {
4269 /* Make the array bigger for the terminating null */
4270 mono_mb_emit_byte (mb
, CEE_LDC_I4_1
);
4271 mono_mb_emit_byte (mb
, CEE_ADD
);
4273 mono_mb_emit_byte (mb
, CEE_MUL
);
4274 mono_mb_emit_byte (mb
, CEE_PREFIX1
);
4275 mono_mb_emit_byte (mb
, CEE_LOCALLOC
);
4276 mono_mb_emit_stloc (mb
, conv_arg
);
4278 mono_mb_emit_ldloc (mb
, conv_arg
);
4279 mono_mb_emit_stloc (mb
, dest_ptr
);
4281 /* Emit marshalling loop */
4282 index_var
= mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
4283 mono_mb_emit_byte (mb
, CEE_LDC_I4_0
);
4284 mono_mb_emit_stloc (mb
, index_var
);
4286 mono_mb_emit_ldloc (mb
, index_var
);
4287 mono_mb_emit_ldloc (mb
, src_var
);
4288 mono_mb_emit_byte (mb
, CEE_LDLEN
);
4289 mono_mb_emit_byte (mb
, CEE_BGE
);
4291 mono_mb_emit_i4 (mb
, 0);
4293 /* Emit marshalling code */
4296 mono_mb_emit_ldloc (mb
, dest_ptr
);
4297 mono_mb_emit_ldloc (mb
, src_var
);
4298 mono_mb_emit_ldloc (mb
, index_var
);
4299 mono_mb_emit_byte (mb
, CEE_LDELEM_REF
);
4300 mono_mb_emit_icall (mb
, conv_to_icall (conv
));
4301 mono_mb_emit_byte (mb
, CEE_STIND_I
);
4304 /* set the src_ptr */
4305 mono_mb_emit_ldloc (mb
, src_var
);
4306 mono_mb_emit_ldloc (mb
, index_var
);
4307 mono_mb_emit_byte (mb
, CEE_LDELEMA
);
4308 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, eklass
));
4309 mono_mb_emit_byte (mb
, CEE_STLOC_0
);
4312 mono_mb_emit_ldloc (mb
, dest_ptr
);
4313 mono_mb_emit_byte (mb
, CEE_STLOC_1
);
4315 /* emit valuetype conversion code */
4316 emit_struct_conv (mb
, eklass
, FALSE
);
4319 mono_mb_emit_add_to_local (mb
, index_var
, 1);
4320 mono_mb_emit_add_to_local (mb
, dest_ptr
, esize
);
4322 mono_mb_emit_byte (mb
, CEE_BR
);
4323 mono_mb_emit_i4 (mb
, label2
- (mb
->pos
+ 4));
4325 mono_mb_patch_addr (mb
, label3
, mb
->pos
- (label3
+ 4));
4327 if (eklass
== mono_defaults
.string_class
) {
4328 /* Null terminate */
4329 mono_mb_emit_ldloc (mb
, dest_ptr
);
4330 mono_mb_emit_byte (mb
, CEE_LDC_I4_0
);
4331 mono_mb_emit_byte (mb
, CEE_STIND_REF
);
4334 mono_mb_patch_addr (mb
, label1
, mb
->pos
- (label1
+ 4));
4339 case MARSHAL_ACTION_CONV_OUT
:
4340 /* Character arrays are implicitly marshalled as [Out] */
4341 need_convert
= (klass
->element_class
== mono_defaults
.char_class
) || (klass
->element_class
== mono_defaults
.stringbuilder_class
) || (t
->attrs
& PARAM_ATTRIBUTE_OUT
);
4342 need_free
= mono_marshal_need_free (&klass
->element_class
->byval_arg
,
4345 if (need_convert
|| need_free
) {
4346 /* FIXME: Optimize blittable case */
4348 guint32 label1
, label2
, label3
;
4349 int index_var
, src_ptr
, loc
, esize
;
4351 eklass
= klass
->element_class
;
4352 if ((eklass
== mono_defaults
.stringbuilder_class
) || (eklass
== mono_defaults
.string_class
))
4353 esize
= sizeof (gpointer
);
4355 esize
= mono_class_native_size (eklass
, NULL
);
4356 src_ptr
= mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
4357 loc
= mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
4360 mono_mb_emit_ldarg (mb
, argnum
);
4362 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
4363 mono_mb_emit_byte (mb
, CEE_BRFALSE
);
4365 mono_mb_emit_i4 (mb
, 0);
4367 mono_mb_emit_ldloc (mb
, conv_arg
);
4368 mono_mb_emit_stloc (mb
, src_ptr
);
4370 /* Emit marshalling loop */
4371 index_var
= mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
4372 mono_mb_emit_byte (mb
, CEE_LDC_I4_0
);
4373 mono_mb_emit_stloc (mb
, index_var
);
4375 mono_mb_emit_ldloc (mb
, index_var
);
4376 mono_mb_emit_ldarg (mb
, argnum
);
4378 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
4379 mono_mb_emit_byte (mb
, CEE_LDLEN
);
4380 mono_mb_emit_byte (mb
, CEE_BGE
);
4382 mono_mb_emit_i4 (mb
, 0);
4384 /* Emit marshalling code */
4386 if (eklass
== mono_defaults
.stringbuilder_class
) {
4387 gboolean need_free2
;
4388 MonoMarshalConv conv
= mono_marshal_get_ptr_to_stringbuilder_conv (m
->piinfo
, spec
, &need_free2
);
4390 g_assert (conv
!= -1);
4393 mono_mb_emit_ldarg (mb
, argnum
);
4395 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
4396 mono_mb_emit_ldloc (mb
, index_var
);
4397 mono_mb_emit_byte (mb
, CEE_LDELEM_REF
);
4400 mono_mb_emit_ldloc (mb
, src_ptr
);
4401 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
4403 mono_mb_emit_icall (mb
, conv_to_icall (conv
));
4407 mono_mb_emit_ldloc (mb
, src_ptr
);
4408 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
4410 mono_mb_emit_icall (mb
, mono_marshal_free
);
4413 else if (eklass
== mono_defaults
.string_class
) {
4416 mono_mb_emit_ldloc (mb
, src_ptr
);
4417 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
4419 mono_mb_emit_icall (mb
, mono_marshal_free
);
4424 /* set the src_ptr */
4425 mono_mb_emit_ldloc (mb
, src_ptr
);
4426 mono_mb_emit_byte (mb
, CEE_STLOC_0
);
4429 mono_mb_emit_ldarg (mb
, argnum
);
4431 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
4432 mono_mb_emit_ldloc (mb
, index_var
);
4433 mono_mb_emit_byte (mb
, CEE_LDELEMA
);
4434 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, eklass
));
4435 mono_mb_emit_byte (mb
, CEE_STLOC_1
);
4437 /* emit valuetype conversion code */
4438 emit_struct_conv (mb
, eklass
, TRUE
);
4442 mono_mb_emit_ldloc (mb
, src_ptr
);
4443 mono_mb_emit_stloc (mb
, loc
);
4444 mono_mb_emit_ldloc (mb
, loc
);
4446 emit_struct_free (mb
, eklass
, loc
);
4450 mono_mb_emit_add_to_local (mb
, index_var
, 1);
4451 mono_mb_emit_add_to_local (mb
, src_ptr
, esize
);
4453 mono_mb_emit_byte (mb
, CEE_BR
);
4454 mono_mb_emit_i4 (mb
, label2
- (mb
->pos
+ 4));
4456 mono_mb_patch_addr (mb
, label1
, mb
->pos
- (label1
+ 4));
4457 mono_mb_patch_addr (mb
, label3
, mb
->pos
- (label3
+ 4));
4461 case MARSHAL_ACTION_CONV_RESULT
:
4462 /* fixme: we need conversions here */
4463 mono_mb_emit_byte (mb
, CEE_STLOC_3
);
4466 g_assert_not_reached ();
4473 emit_marshal_boolean (EmitMarshalContext
*m
, int argnum
, MonoType
*t
,
4474 MonoMarshalSpec
*spec
,
4475 int conv_arg
, MonoType
**conv_arg_type
,
4476 MarshalAction action
)
4478 MonoMethodBuilder
*mb
= m
->mb
;
4481 case MARSHAL_ACTION_CONV_IN
: {
4482 MonoType
*local_type
;
4483 int variant_bool
= 0;
4487 local_type
= &mono_defaults
.int32_class
->byval_arg
;
4489 switch (spec
->native
) {
4490 case MONO_NATIVE_I1
:
4491 local_type
= &mono_defaults
.byte_class
->byval_arg
;
4493 case MONO_NATIVE_VARIANTBOOL
:
4494 local_type
= &mono_defaults
.int16_class
->byval_arg
;
4498 g_warning ("marshalling bool as native type %x is currently not supported", spec
->native
);
4499 local_type
= &mono_defaults
.int32_class
->byval_arg
;
4503 *conv_arg_type
= &mono_defaults
.int_class
->byval_arg
;
4504 conv_arg
= mono_mb_add_local (mb
, local_type
);
4505 mono_mb_emit_ldarg (mb
, argnum
);
4506 mono_mb_emit_byte (mb
, CEE_LDIND_I1
);
4508 mono_mb_emit_byte (mb
, CEE_NEG
);
4509 mono_mb_emit_stloc (mb
, conv_arg
);
4513 case MARSHAL_ACTION_CONV_RESULT
:
4514 /* maybe we need to make sure that it fits within 8 bits */
4515 mono_mb_emit_byte (mb
, CEE_STLOC_3
);
4519 g_assert_not_reached ();
4526 emit_marshal (EmitMarshalContext
*m
, int argnum
, MonoType
*t
,
4527 MonoMarshalSpec
*spec
, int conv_arg
,
4528 MonoType
**conv_arg_type
, MarshalAction action
)
4530 /* Ensure that we have marshalling info for this param */
4531 mono_marshal_load_type_info (mono_class_from_mono_type (t
));
4533 if (spec
&& spec
->native
== MONO_NATIVE_CUSTOM
)
4534 return emit_marshal_custom (m
, argnum
, t
, spec
, conv_arg
, conv_arg_type
, action
);
4536 if (spec
&& spec
->native
== MONO_NATIVE_ASANY
)
4537 return emit_marshal_asany (m
, argnum
, t
, spec
, conv_arg
, conv_arg_type
, action
);
4540 case MONO_TYPE_VALUETYPE
:
4541 return emit_marshal_vtype (m
, argnum
, t
, spec
, conv_arg
, conv_arg_type
, action
);
4542 case MONO_TYPE_STRING
:
4543 return emit_marshal_string (m
, argnum
, t
, spec
, conv_arg
, conv_arg_type
, action
);
4544 case MONO_TYPE_CLASS
:
4545 case MONO_TYPE_OBJECT
:
4546 return emit_marshal_object (m
, argnum
, t
, spec
, conv_arg
, conv_arg_type
, action
);
4547 case MONO_TYPE_ARRAY
:
4548 case MONO_TYPE_SZARRAY
:
4549 return emit_marshal_array (m
, argnum
, t
, spec
, conv_arg
, conv_arg_type
, action
);
4550 case MONO_TYPE_BOOLEAN
:
4551 return emit_marshal_boolean (m
, argnum
, t
, spec
, conv_arg
, conv_arg_type
, action
);
4558 * mono_marshal_get_native_wrapper:
4559 * @method: The MonoMethod to wrap.
4561 * generates IL code for the pinvoke wrapper (the generated method
4562 * calls the unmanaged code in method->addr)
4565 mono_marshal_get_native_wrapper (MonoMethod
*method
)
4567 EmitMarshalContext m
;
4568 MonoMethodSignature
*sig
, *csig
;
4569 MonoMethodPInvoke
*piinfo
;
4570 MonoMethodBuilder
*mb
;
4571 MonoMarshalSpec
**mspecs
;
4575 gboolean pinvoke
= FALSE
;
4576 int i
, argnum
, *tmp_locals
;
4578 const char *exc_class
= "MissingMethodException";
4579 const char *exc_arg
= NULL
;
4581 g_assert (method
!= NULL
);
4582 g_assert (method
->signature
->pinvoke
);
4584 cache
= method
->klass
->image
->native_wrapper_cache
;
4585 if ((res
= mono_marshal_find_in_cache (cache
, method
)))
4588 sig
= method
->signature
;
4590 if (!(method
->iflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
) &&
4591 (method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
))
4594 if (!method
->addr
) {
4596 mono_lookup_pinvoke_call (method
, &exc_class
, &exc_arg
);
4598 method
->addr
= mono_lookup_internal_call (method
);
4601 mb
= mono_mb_new (method
->klass
, method
->name
, MONO_WRAPPER_MANAGED_TO_NATIVE
);
4603 mb
->method
->save_lmf
= 1;
4605 piinfo
= (MonoMethodPInvoke
*)method
;
4607 if (!method
->addr
) {
4608 mono_mb_emit_exception (mb
, exc_class
, exc_arg
);
4609 csig
= mono_metadata_signature_dup (sig
);
4611 res
= mono_mb_create_and_cache (cache
, method
,
4612 mb
, csig
, csig
->param_count
+ 16);
4620 /* internal calls: we simply push all arguments and call the method (no conversions) */
4621 if (method
->iflags
& (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
| METHOD_IMPL_ATTRIBUTE_RUNTIME
)) {
4623 /* hack - string constructors returns a value */
4624 if (method
->string_ctor
) {
4625 csig
= mono_metadata_signature_dup (sig
);
4626 csig
->ret
= &mono_defaults
.string_class
->byval_arg
;
4631 mono_mb_emit_byte (mb
, CEE_LDARG_0
);
4633 for (i
= 0; i
< sig
->param_count
; i
++)
4634 mono_mb_emit_ldarg (mb
, i
+ sig
->hasthis
);
4636 g_assert (method
->addr
);
4637 mono_mb_emit_native_call (mb
, csig
, method
->addr
);
4638 emit_thread_interrupt_checkpoint (mb
);
4639 mono_mb_emit_byte (mb
, CEE_RET
);
4641 csig
= mono_metadata_signature_dup (csig
);
4643 res
= mono_mb_create_and_cache (cache
, method
,
4644 mb
, csig
, csig
->param_count
+ 16);
4651 mspecs
= g_new (MonoMarshalSpec
*, sig
->param_count
+ 1);
4652 mono_method_get_marshal_info (method
, mspecs
);
4654 /* pinvoke: we need to convert the arguments if necessary */
4656 /* we copy the signature, so that we can set pinvoke to 0 */
4657 csig
= mono_metadata_signature_dup (sig
);
4660 /* we allocate local for use with emit_struct_conv() */
4661 /* allocate local 0 (pointer) src_ptr */
4662 mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
4663 /* allocate local 1 (pointer) dst_ptr */
4664 mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
4665 /* allocate local 2 (boolean) delete_old */
4666 mono_mb_add_local (mb
, &mono_defaults
.boolean_class
->byval_arg
);
4668 /* delete_old = FALSE */
4669 mono_mb_emit_icon (mb
, 0);
4670 mono_mb_emit_byte (mb
, CEE_STLOC_2
);
4672 if (!MONO_TYPE_IS_VOID(sig
->ret
)) {
4673 /* allocate local 3 to store the return value */
4674 mono_mb_add_local (mb
, sig
->ret
);
4677 if (mspecs
[0] && mspecs
[0]->native
== MONO_NATIVE_CUSTOM
) {
4678 /* Return type custom marshaling */
4680 * Since we can't determine the return type of the unmanaged function,
4681 * we assume it returns a pointer, and pass that pointer to
4682 * MarshalNativeToManaged.
4684 csig
->ret
= &mono_defaults
.int_class
->byval_arg
;
4687 /* we first do all conversions */
4688 tmp_locals
= alloca (sizeof (int) * sig
->param_count
);
4689 m
.orig_conv_args
= alloca (sizeof (int) * (sig
->param_count
+ 1));
4691 for (i
= 0; i
< sig
->param_count
; i
++) {
4692 tmp_locals
[i
] = emit_marshal (&m
, i
+ sig
->hasthis
, sig
->params
[i
], mspecs
[i
+ 1], 0, &csig
->params
[i
], MARSHAL_ACTION_CONV_IN
);
4695 /* push all arguments */
4698 mono_mb_emit_byte (mb
, CEE_LDARG_0
);
4700 for (i
= 0; i
< sig
->param_count
; i
++) {
4701 MonoType
*t
= sig
->params
[i
];
4702 MonoMarshalSpec
*spec
= mspecs
[i
+ 1];
4704 if (spec
&& ((spec
->native
== MONO_NATIVE_CUSTOM
) || (spec
->native
== MONO_NATIVE_ASANY
)))
4705 emit_marshal (&m
, i
+ sig
->hasthis
, t
, spec
, tmp_locals
[i
], NULL
, MARSHAL_ACTION_PUSH
);
4707 argnum
= i
+ sig
->hasthis
;
4710 case MONO_TYPE_BOOLEAN
:
4712 g_assert (tmp_locals
[i
]);
4713 mono_mb_emit_ldloc_addr (mb
, tmp_locals
[i
]);
4715 mono_mb_emit_ldarg (mb
, argnum
);
4730 mono_mb_emit_ldarg (mb
, argnum
);
4732 case MONO_TYPE_VALUETYPE
:
4733 emit_marshal (&m
, i
+ sig
->hasthis
, t
, spec
, tmp_locals
[i
], NULL
, MARSHAL_ACTION_PUSH
);
4735 case MONO_TYPE_STRING
:
4736 case MONO_TYPE_CLASS
:
4737 case MONO_TYPE_OBJECT
:
4738 case MONO_TYPE_ARRAY
:
4739 case MONO_TYPE_SZARRAY
:
4740 g_assert (tmp_locals
[i
]);
4742 mono_mb_emit_ldloc_addr (mb
, tmp_locals
[i
]);
4744 mono_mb_emit_ldloc (mb
, tmp_locals
[i
]);
4746 case MONO_TYPE_CHAR
:
4747 /* fixme: dont know how to marshal that. We cant simply
4748 * convert it to a one byte UTF8 character, because an
4749 * unicode character may need more that one byte in UTF8 */
4750 mono_mb_emit_ldarg (mb
, argnum
);
4752 case MONO_TYPE_TYPEDBYREF
:
4753 case MONO_TYPE_FNPTR
:
4755 g_warning ("type 0x%02x unknown", t
->type
);
4756 g_assert_not_reached ();
4761 /* call the native method */
4762 mono_mb_emit_native_call (mb
, csig
, method
->addr
);
4764 /* Set LastError if needed */
4765 if (piinfo
->piflags
& PINVOKE_ATTRIBUTE_SUPPORTS_LAST_ERROR
) {
4766 MonoMethodSignature
*lasterr_sig
;
4768 lasterr_sig
= mono_metadata_signature_alloc (mono_defaults
.corlib
, 0);
4769 lasterr_sig
->ret
= &mono_defaults
.void_class
->byval_arg
;
4770 lasterr_sig
->pinvoke
= 1;
4772 mono_mb_emit_native_call (mb
, lasterr_sig
, mono_marshal_set_last_error
);
4775 /* convert the result */
4776 if (!sig
->ret
->byref
) {
4777 MonoMarshalSpec
*spec
= mspecs
[0];
4778 type
= sig
->ret
->type
;
4780 if (spec
&& spec
->native
== MONO_NATIVE_CUSTOM
) {
4781 emit_marshal (&m
, 0, sig
->ret
, spec
, 0, NULL
, MARSHAL_ACTION_CONV_RESULT
);
4786 case MONO_TYPE_VOID
:
4801 /* no conversions necessary */
4802 mono_mb_emit_byte (mb
, CEE_STLOC_3
);
4804 case MONO_TYPE_VALUETYPE
:
4805 klass
= sig
->ret
->data
.klass
;
4806 if (klass
->enumtype
) {
4807 type
= sig
->ret
->data
.klass
->enum_basetype
->type
;
4810 emit_marshal (&m
, 0, sig
->ret
, spec
, 0, NULL
, MARSHAL_ACTION_CONV_RESULT
);
4812 case MONO_TYPE_STRING
:
4813 case MONO_TYPE_CLASS
:
4814 case MONO_TYPE_OBJECT
:
4815 case MONO_TYPE_BOOLEAN
:
4816 case MONO_TYPE_ARRAY
:
4817 case MONO_TYPE_SZARRAY
:
4818 emit_marshal (&m
, 0, sig
->ret
, spec
, 0, NULL
, MARSHAL_ACTION_CONV_RESULT
);
4820 case MONO_TYPE_CHAR
:
4821 /* fixme: we need conversions here */
4822 mono_mb_emit_byte (mb
, CEE_STLOC_3
);
4824 case MONO_TYPE_TYPEDBYREF
:
4825 case MONO_TYPE_FNPTR
:
4827 g_warning ("return type 0x%02x unknown", sig
->ret
->type
);
4828 g_assert_not_reached ();
4832 mono_mb_emit_byte (mb
, CEE_STLOC_3
);
4836 * Need to call this after converting the result since MONO_VTADDR needs
4837 * to be adjacent to the call instruction.
4839 emit_thread_interrupt_checkpoint (mb
);
4841 /* we need to convert byref arguments back and free string arrays */
4842 for (i
= 0; i
< sig
->param_count
; i
++) {
4843 MonoType
*t
= sig
->params
[i
];
4844 MonoMarshalSpec
*spec
= mspecs
[i
+ 1];
4846 argnum
= i
+ sig
->hasthis
;
4848 if (spec
&& ((spec
->native
== MONO_NATIVE_CUSTOM
) || (spec
->native
== MONO_NATIVE_ASANY
))) {
4849 emit_marshal (&m
, argnum
, t
, spec
, tmp_locals
[i
], NULL
, MARSHAL_ACTION_CONV_OUT
);
4854 case MONO_TYPE_STRING
:
4855 case MONO_TYPE_VALUETYPE
:
4856 case MONO_TYPE_CLASS
:
4857 case MONO_TYPE_OBJECT
:
4858 case MONO_TYPE_SZARRAY
:
4859 emit_marshal (&m
, argnum
, t
, spec
, tmp_locals
[i
], NULL
, MARSHAL_ACTION_CONV_OUT
);
4861 case MONO_TYPE_BOOLEAN
:
4864 mono_mb_emit_ldarg (mb
, argnum
);
4865 mono_mb_emit_ldloc (mb
, tmp_locals
[i
]);
4866 if (mspecs
[i
+ 1] != NULL
&& mspecs
[i
+ 1]->native
== MONO_NATIVE_VARIANTBOOL
)
4867 mono_mb_emit_byte (mb
, CEE_NEG
);
4868 mono_mb_emit_byte (mb
, CEE_STIND_I1
);
4872 if (!MONO_TYPE_IS_VOID(sig
->ret
))
4873 mono_mb_emit_byte (mb
, CEE_LDLOC_3
);
4875 mono_mb_emit_byte (mb
, CEE_RET
);
4877 csig
= mono_metadata_signature_dup (sig
);
4879 res
= mono_mb_create_and_cache (cache
, method
,
4880 mb
, csig
, csig
->param_count
+ 16);
4883 for (i
= sig
->param_count
; i
>= 0; i
--)
4884 g_free (mspecs
[i
]);
4887 /* printf ("CODE FOR %s: \n%s.\n", mono_method_full_name (res, TRUE), mono_disasm_code (0, res, ((MonoMethodNormal*)res)->header->code, ((MonoMethodNormal*)res)->header->code + ((MonoMethodNormal*)res)->header->code_size)); */
4893 mono_upgrade_remote_class_wrapper (MonoReflectionType
*rtype
, MonoTransparentProxy
*tproxy
);
4895 static MonoReflectionType
*
4896 type_from_handle (MonoType
*handle
)
4898 MonoDomain
*domain
= mono_domain_get ();
4899 MonoClass
*klass
= mono_class_from_mono_type (handle
);
4901 MONO_ARCH_SAVE_REGS
;
4903 mono_class_init (klass
);
4904 return mono_type_get_object (domain
, handle
);
4908 * mono_marshal_get_isinst:
4909 * @klass: the type of the field
4911 * This method generates a function which can be used to check if an object is
4912 * an instance of the given type, icluding the case where the object is a proxy.
4913 * The generated function has the following signature:
4914 * MonoObject* __isinst_wrapper_ (MonoObject *obj)
4917 mono_marshal_get_isinst (MonoClass
*klass
)
4919 static MonoMethodSignature
*isint_sig
= NULL
;
4920 static GHashTable
*isinst_hash
= NULL
;
4922 int pos_was_ok
, pos_failed
, pos_end
, pos_end2
;
4924 MonoMethodBuilder
*mb
;
4926 EnterCriticalSection (&marshal_mutex
);
4928 isinst_hash
= g_hash_table_new (NULL
, NULL
);
4930 res
= g_hash_table_lookup (isinst_hash
, klass
);
4931 LeaveCriticalSection (&marshal_mutex
);
4936 isint_sig
= mono_metadata_signature_alloc (mono_defaults
.corlib
, 1);
4937 isint_sig
->params
[0] = &mono_defaults
.object_class
->byval_arg
;
4938 isint_sig
->ret
= &mono_defaults
.object_class
->byval_arg
;
4939 isint_sig
->pinvoke
= 0;
4942 name
= g_strdup_printf ("__isinst_wrapper_%s", klass
->name
);
4943 mb
= mono_mb_new (mono_defaults
.object_class
, name
, MONO_WRAPPER_ISINST
);
4946 mb
->method
->save_lmf
= 1;
4948 /* check if the object is a proxy that needs special cast */
4949 mono_mb_emit_ldarg (mb
, 0);
4950 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
4951 mono_mb_emit_byte (mb
, CEE_MONO_CISINST
);
4952 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, klass
));
4954 /* The result of MONO_ISINST can be:
4955 0) the type check succeeded
4956 1) the type check did not succeed
4957 2) a CanCastTo call is needed */
4959 mono_mb_emit_byte (mb
, CEE_DUP
);
4960 pos_was_ok
= mono_mb_emit_branch (mb
, CEE_BRFALSE
);
4962 mono_mb_emit_byte (mb
, CEE_LDC_I4_2
);
4963 pos_failed
= mono_mb_emit_branch (mb
, CEE_BNE_UN
);
4965 /* get the real proxy from the transparent proxy*/
4967 mono_mb_emit_ldarg (mb
, 0);
4968 mono_mb_emit_managed_call (mb
, mono_marshal_get_proxy_cancast (klass
), NULL
);
4969 pos_end
= mono_mb_emit_branch (mb
, CEE_BR
);
4973 mono_mb_patch_addr (mb
, pos_failed
, mb
->pos
- (pos_failed
+ 4));
4974 mono_mb_emit_byte (mb
, CEE_LDNULL
);
4975 pos_end2
= mono_mb_emit_branch (mb
, CEE_BR
);
4979 mono_mb_patch_addr (mb
, pos_was_ok
, mb
->pos
- (pos_was_ok
+ 4));
4980 mono_mb_emit_byte (mb
, CEE_POP
);
4981 mono_mb_emit_ldarg (mb
, 0);
4985 mono_mb_patch_addr (mb
, pos_end
, mb
->pos
- (pos_end
+ 4));
4986 mono_mb_patch_addr (mb
, pos_end2
, mb
->pos
- (pos_end2
+ 4));
4987 mono_mb_emit_byte (mb
, CEE_RET
);
4989 res
= mono_mb_create_and_cache (isinst_hash
, klass
, mb
, isint_sig
, isint_sig
->param_count
+ 16);
4996 * mono_marshal_get_castclass:
4997 * @klass: the type of the field
4999 * This method generates a function which can be used to cast an object to
5000 * an instance of the given type, icluding the case where the object is a proxy.
5001 * The generated function has the following signature:
5002 * MonoObject* __castclass_wrapper_ (MonoObject *obj)
5005 mono_marshal_get_castclass (MonoClass
*klass
)
5007 static MonoMethodSignature
*castclass_sig
= NULL
;
5008 static GHashTable
*castclass_hash
= NULL
;
5010 int pos_was_ok
, pos_was_ok2
;
5012 MonoMethodBuilder
*mb
;
5014 EnterCriticalSection (&marshal_mutex
);
5015 if (!castclass_hash
)
5016 castclass_hash
= g_hash_table_new (NULL
, NULL
);
5018 res
= g_hash_table_lookup (castclass_hash
, klass
);
5019 LeaveCriticalSection (&marshal_mutex
);
5023 if (!castclass_sig
) {
5024 castclass_sig
= mono_metadata_signature_alloc (mono_defaults
.corlib
, 1);
5025 castclass_sig
->params
[0] = &mono_defaults
.object_class
->byval_arg
;
5026 castclass_sig
->ret
= &mono_defaults
.object_class
->byval_arg
;
5027 castclass_sig
->pinvoke
= 0;
5030 name
= g_strdup_printf ("__castclass_wrapper_%s", klass
->name
);
5031 mb
= mono_mb_new (mono_defaults
.object_class
, name
, MONO_WRAPPER_CASTCLASS
);
5034 mb
->method
->save_lmf
= 1;
5036 /* check if the object is a proxy that needs special cast */
5037 mono_mb_emit_ldarg (mb
, 0);
5038 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
5039 mono_mb_emit_byte (mb
, CEE_MONO_CCASTCLASS
);
5040 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, klass
));
5042 /* The result of MONO_ISINST can be:
5043 0) the cast is valid
5044 1) cast of unknown proxy type
5045 or an exception if the cast is is invalid
5048 pos_was_ok
= mono_mb_emit_branch (mb
, CEE_BRFALSE
);
5050 /* get the real proxy from the transparent proxy*/
5052 mono_mb_emit_ldarg (mb
, 0);
5053 mono_mb_emit_managed_call (mb
, mono_marshal_get_proxy_cancast (klass
), NULL
);
5054 pos_was_ok2
= mono_mb_emit_branch (mb
, CEE_BRTRUE
);
5057 mono_mb_emit_exception (mb
, "InvalidCastException", NULL
);
5060 mono_mb_patch_addr (mb
, pos_was_ok
, mb
->pos
- (pos_was_ok
+ 4));
5061 mono_mb_patch_addr (mb
, pos_was_ok2
, mb
->pos
- (pos_was_ok2
+ 4));
5062 mono_mb_emit_ldarg (mb
, 0);
5065 mono_mb_emit_byte (mb
, CEE_RET
);
5067 res
= mono_mb_create_and_cache (castclass_hash
, klass
, mb
, castclass_sig
, castclass_sig
->param_count
+ 16);
5074 mono_marshal_get_proxy_cancast (MonoClass
*klass
)
5076 static MonoMethodSignature
*from_handle_sig
= NULL
;
5077 static MonoMethodSignature
*upgrade_proxy_sig
= NULL
;
5078 static MonoMethodSignature
*isint_sig
= NULL
;
5079 static GHashTable
*proxy_isinst_hash
= NULL
;
5081 int pos_failed
, pos_end
;
5083 MonoMethod
*can_cast_to
;
5084 MonoMethodDesc
*desc
;
5085 MonoMethodBuilder
*mb
;
5087 EnterCriticalSection (&marshal_mutex
);
5088 if (!proxy_isinst_hash
)
5089 proxy_isinst_hash
= g_hash_table_new (NULL
, NULL
);
5091 res
= g_hash_table_lookup (proxy_isinst_hash
, klass
);
5092 LeaveCriticalSection (&marshal_mutex
);
5097 upgrade_proxy_sig
= mono_metadata_signature_alloc (mono_defaults
.corlib
, 2);
5098 upgrade_proxy_sig
->params
[0] = &mono_defaults
.object_class
->byval_arg
;
5099 upgrade_proxy_sig
->params
[1] = &mono_defaults
.object_class
->byval_arg
;
5100 upgrade_proxy_sig
->ret
= &mono_defaults
.void_class
->byval_arg
;
5101 upgrade_proxy_sig
->pinvoke
= 1;
5103 from_handle_sig
= mono_metadata_signature_alloc (mono_defaults
.corlib
, 1);
5104 from_handle_sig
->params
[0] = &mono_defaults
.object_class
->byval_arg
;
5105 from_handle_sig
->ret
= &mono_defaults
.object_class
->byval_arg
;
5107 isint_sig
= mono_metadata_signature_alloc (mono_defaults
.corlib
, 1);
5108 isint_sig
->params
[0] = &mono_defaults
.object_class
->byval_arg
;
5109 isint_sig
->ret
= &mono_defaults
.object_class
->byval_arg
;
5110 isint_sig
->pinvoke
= 0;
5113 name
= g_strdup_printf ("__proxy_isinst_wrapper_%s", klass
->name
);
5114 mb
= mono_mb_new (mono_defaults
.object_class
, name
, MONO_WRAPPER_PROXY_ISINST
);
5117 mb
->method
->save_lmf
= 1;
5119 /* get the real proxy from the transparent proxy*/
5120 mono_mb_emit_ldarg (mb
, 0);
5121 mono_mb_emit_ldflda (mb
, G_STRUCT_OFFSET (MonoTransparentProxy
, rp
));
5122 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
5124 /* get the refletion type from the type handle */
5125 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
5126 mono_mb_emit_byte (mb
, CEE_MONO_LDPTR
);
5127 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, &klass
->byval_arg
));
5128 mono_mb_emit_native_call (mb
, from_handle_sig
, type_from_handle
);
5130 mono_mb_emit_ldarg (mb
, 0);
5132 /* make the call to CanCastTo (type, ob) */
5133 desc
= mono_method_desc_new ("IRemotingTypeInfo:CanCastTo", FALSE
);
5134 can_cast_to
= mono_method_desc_search_in_class (desc
, mono_defaults
.iremotingtypeinfo_class
);
5135 g_assert (can_cast_to
);
5136 mono_method_desc_free (desc
);
5137 mono_mb_emit_byte (mb
, CEE_CALLVIRT
);
5138 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, can_cast_to
));
5141 pos_failed
= mono_mb_emit_branch (mb
, CEE_BRFALSE
);
5143 /* Upgrade the proxy vtable by calling: mono_upgrade_remote_class_wrapper (type, ob)*/
5144 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
5145 mono_mb_emit_byte (mb
, CEE_MONO_LDPTR
);
5146 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, &klass
->byval_arg
));
5147 mono_mb_emit_native_call (mb
, from_handle_sig
, type_from_handle
);
5148 mono_mb_emit_ldarg (mb
, 0);
5150 mono_mb_emit_native_call (mb
, upgrade_proxy_sig
, mono_upgrade_remote_class_wrapper
);
5151 emit_thread_interrupt_checkpoint (mb
);
5153 mono_mb_emit_ldarg (mb
, 0);
5154 pos_end
= mono_mb_emit_branch (mb
, CEE_BR
);
5158 mono_mb_patch_addr (mb
, pos_failed
, mb
->pos
- (pos_failed
+ 4));
5159 mono_mb_emit_byte (mb
, CEE_LDNULL
);
5163 mono_mb_patch_addr (mb
, pos_end
, mb
->pos
- (pos_end
+ 4));
5164 mono_mb_emit_byte (mb
, CEE_RET
);
5166 res
= mono_mb_create_and_cache (proxy_isinst_hash
, klass
, mb
, isint_sig
, isint_sig
->param_count
+ 16);
5173 mono_upgrade_remote_class_wrapper (MonoReflectionType
*rtype
, MonoTransparentProxy
*tproxy
)
5176 klass
= mono_class_from_mono_type (rtype
->type
);
5177 mono_upgrade_remote_class (((MonoObject
*)tproxy
)->vtable
->domain
, tproxy
->remote_class
, klass
);
5178 ((MonoObject
*)tproxy
)->vtable
= tproxy
->remote_class
->vtable
;
5182 * mono_marshal_get_struct_to_ptr:
5185 * generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld)
5188 mono_marshal_get_struct_to_ptr (MonoClass
*klass
)
5190 MonoMethodBuilder
*mb
;
5191 static MonoMethod
*stoptr
= NULL
;
5194 g_assert (klass
!= NULL
);
5196 if (klass
->str_to_ptr
)
5197 return klass
->str_to_ptr
;
5200 stoptr
= mono_find_method_by_name (mono_defaults
.marshal_class
, "StructureToPtr", 3);
5203 mb
= mono_mb_new (klass
, stoptr
->name
, MONO_WRAPPER_UNKNOWN
);
5205 if (klass
->blittable
) {
5206 mono_mb_emit_byte (mb
, CEE_LDARG_1
);
5207 mono_mb_emit_byte (mb
, CEE_LDARG_0
);
5208 mono_mb_emit_ldflda (mb
, sizeof (MonoObject
));
5209 mono_mb_emit_icon (mb
, mono_class_value_size (klass
, NULL
));
5210 mono_mb_emit_byte (mb
, CEE_PREFIX1
);
5211 mono_mb_emit_byte (mb
, CEE_CPBLK
);
5214 /* allocate local 0 (pointer) src_ptr */
5215 mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
5216 /* allocate local 1 (pointer) dst_ptr */
5217 mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
5218 /* allocate local 2 (boolean) delete_old */
5219 mono_mb_add_local (mb
, &mono_defaults
.boolean_class
->byval_arg
);
5220 mono_mb_emit_byte (mb
, CEE_LDARG_2
);
5221 mono_mb_emit_byte (mb
, CEE_STLOC_2
);
5223 /* initialize src_ptr to point to the start of object data */
5224 mono_mb_emit_byte (mb
, CEE_LDARG_0
);
5225 mono_mb_emit_ldflda (mb
, sizeof (MonoObject
));
5226 mono_mb_emit_byte (mb
, CEE_STLOC_0
);
5228 /* initialize dst_ptr */
5229 mono_mb_emit_byte (mb
, CEE_LDARG_1
);
5230 mono_mb_emit_byte (mb
, CEE_STLOC_1
);
5232 emit_struct_conv (mb
, klass
, FALSE
);
5235 mono_mb_emit_byte (mb
, CEE_RET
);
5237 res
= mono_mb_create_method (mb
, stoptr
->signature
, 0);
5240 klass
->str_to_ptr
= res
;
5245 * mono_marshal_get_ptr_to_struct:
5248 * generates IL code for PtrToStructure (IntPtr src, object structure)
5251 mono_marshal_get_ptr_to_struct (MonoClass
*klass
)
5253 MonoMethodBuilder
*mb
;
5254 static MonoMethod
*ptostr
= NULL
;
5257 g_assert (klass
!= NULL
);
5259 if (klass
->ptr_to_str
)
5260 return klass
->ptr_to_str
;
5263 ptostr
= mono_find_method_by_name (mono_defaults
.marshal_class
, "PtrToStructure", 2);
5266 mb
= mono_mb_new (klass
, ptostr
->name
, MONO_WRAPPER_UNKNOWN
);
5268 if (((klass
->flags
& TYPE_ATTRIBUTE_LAYOUT_MASK
) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT
) || klass
->blittable
) {
5269 mono_mb_emit_byte (mb
, CEE_LDARG_1
);
5270 mono_mb_emit_ldflda (mb
, sizeof (MonoObject
));
5271 mono_mb_emit_byte (mb
, CEE_LDARG_0
);
5272 mono_mb_emit_icon (mb
, mono_class_value_size (klass
, NULL
));
5273 mono_mb_emit_byte (mb
, CEE_PREFIX1
);
5274 mono_mb_emit_byte (mb
, CEE_CPBLK
);
5277 /* allocate local 0 (pointer) src_ptr */
5278 mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
5279 /* allocate local 1 (pointer) dst_ptr */
5280 mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
5282 /* initialize src_ptr to point to the start of object data */
5283 mono_mb_emit_byte (mb
, CEE_LDARG_0
);
5284 mono_mb_emit_byte (mb
, CEE_STLOC_0
);
5286 /* initialize dst_ptr */
5287 mono_mb_emit_byte (mb
, CEE_LDARG_1
);
5288 mono_mb_emit_ldflda (mb
, sizeof (MonoObject
));
5289 mono_mb_emit_byte (mb
, CEE_STLOC_1
);
5291 emit_struct_conv (mb
, klass
, TRUE
);
5294 mono_mb_emit_byte (mb
, CEE_RET
);
5296 res
= mono_mb_create_method (mb
, ptostr
->signature
, 0);
5299 klass
->ptr_to_str
= res
;
5304 * generates IL code for the synchronized wrapper: the generated method
5305 * calls METHOD while locking 'this' or the parent type.
5308 mono_marshal_get_synchronized_wrapper (MonoMethod
*method
)
5310 static MonoMethodSignature
*from_handle_sig
= NULL
;
5311 static MonoMethod
*enter_method
, *exit_method
;
5312 MonoMethodSignature
*sig
;
5313 MonoExceptionClause
*clause
;
5314 MonoMethodHeader
*header
;
5315 MonoMethodBuilder
*mb
;
5318 int i
, pos
, this_local
, ret_local
= 0;
5322 if (method
->wrapper_type
== MONO_WRAPPER_SYNCHRONIZED
)
5325 cache
= method
->klass
->image
->synchronized_cache
;
5326 if ((res
= mono_marshal_find_in_cache (cache
, method
)))
5329 sig
= method
->signature
;
5331 mb
= mono_mb_new (method
->klass
, method
->name
, MONO_WRAPPER_SYNCHRONIZED
);
5334 if (!MONO_TYPE_IS_VOID (sig
->ret
))
5335 ret_local
= mono_mb_add_local (mb
, sig
->ret
);
5338 this_local
= mono_mb_add_local (mb
, &mono_defaults
.object_class
->byval_arg
);
5340 clause
= g_new0 (MonoExceptionClause
, 1);
5341 clause
->flags
= MONO_EXCEPTION_CLAUSE_FINALLY
;
5343 if (!enter_method
) {
5344 MonoMethodDesc
*desc
;
5346 desc
= mono_method_desc_new ("Monitor:Enter", FALSE
);
5347 enter_method
= mono_method_desc_search_in_class (desc
, mono_defaults
.monitor_class
);
5348 g_assert (enter_method
);
5349 mono_method_desc_free (desc
);
5350 desc
= mono_method_desc_new ("Monitor:Exit", FALSE
);
5351 exit_method
= mono_method_desc_search_in_class (desc
, mono_defaults
.monitor_class
);
5352 g_assert (exit_method
);
5353 mono_method_desc_free (desc
);
5356 * GetTypeFromHandle isn't called as a managed method because it has
5357 * a funky calling sequence, e.g. ldtoken+GetTypeFromHandle gets
5358 * transformed into something else by the JIT.
5360 from_handle_sig
= mono_metadata_signature_alloc (mono_defaults
.corlib
, 1);
5361 from_handle_sig
->params
[0] = &mono_defaults
.object_class
->byval_arg
;
5362 from_handle_sig
->ret
= &mono_defaults
.object_class
->byval_arg
;
5365 /* Push this or the type object */
5366 if (method
->flags
& METHOD_ATTRIBUTE_STATIC
) {
5367 mono_mb_emit_byte (mb
, MONO_CUSTOM_PREFIX
);
5368 mono_mb_emit_byte (mb
, CEE_MONO_LDPTR
);
5369 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, &method
->klass
->byval_arg
));
5370 mono_mb_emit_native_call (mb
, from_handle_sig
, type_from_handle
);
5373 mono_mb_emit_ldarg (mb
, 0);
5374 mono_mb_emit_stloc (mb
, this_local
);
5376 /* Call Monitor::Enter() */
5377 mono_mb_emit_ldloc (mb
, this_local
);
5378 mono_mb_emit_managed_call (mb
, enter_method
, NULL
);
5380 clause
->try_offset
= mb
->pos
;
5382 /* Call the method */
5384 mono_mb_emit_ldarg (mb
, 0);
5385 for (i
= 0; i
< sig
->param_count
; i
++)
5386 mono_mb_emit_ldarg (mb
, i
+ (sig
->hasthis
== TRUE
));
5387 mono_mb_emit_managed_call (mb
, method
, method
->signature
);
5388 if (!MONO_TYPE_IS_VOID (sig
->ret
))
5389 mono_mb_emit_stloc (mb
, ret_local
);
5391 mono_mb_emit_byte (mb
, CEE_LEAVE
);
5393 mono_mb_emit_i4 (mb
, 0);
5395 clause
->try_len
= mb
->pos
- clause
->try_offset
;
5396 clause
->handler_offset
= mb
->pos
;
5398 /* Call Monitor::Exit() */
5399 mono_mb_emit_ldloc (mb
, this_local
);
5400 /* mono_mb_emit_native_call (mb, exit_sig, mono_monitor_exit); */
5401 mono_mb_emit_managed_call (mb
, exit_method
, NULL
);
5402 mono_mb_emit_byte (mb
, CEE_ENDFINALLY
);
5404 clause
->handler_len
= mb
->pos
- clause
->handler_offset
;
5406 mono_mb_patch_addr (mb
, pos
, mb
->pos
- (pos
+ 4));
5407 if (!MONO_TYPE_IS_VOID (sig
->ret
))
5408 mono_mb_emit_ldloc (mb
, ret_local
);
5409 mono_mb_emit_byte (mb
, CEE_RET
);
5411 res
= mono_mb_create_and_cache (cache
, method
,
5412 mb
, sig
, sig
->param_count
+ 16);
5415 header
= ((MonoMethodNormal
*)res
)->header
;
5416 header
->num_clauses
= 1;
5417 header
->clauses
= clause
;
5423 mono_marshal_get_stelemref ()
5425 static MonoMethod
* ret
= NULL
;
5426 MonoMethodSignature
*sig
;
5427 MonoMethodBuilder
*mb
;
5429 guint32 b1
, b2
, b3
, b4
;
5436 mb
= mono_mb_new (mono_defaults
.object_class
, "stelemref", MONO_WRAPPER_STELEMREF
);
5439 sig
= mono_metadata_signature_alloc (mono_defaults
.corlib
, 3);
5441 /* void stelemref (void* array, int idx, void* value) */
5442 sig
->ret
= &mono_defaults
.void_class
->byval_arg
;
5443 sig
->params
[0] = &mono_defaults
.int_class
->byval_arg
;
5444 sig
->params
[1] = &mono_defaults
.int_class
->byval_arg
; /* this is a natural sized int */
5445 sig
->params
[2] = &mono_defaults
.int_class
->byval_arg
;
5447 aklass
= mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
5448 vklass
= mono_mb_add_local (mb
, &mono_defaults
.int_class
->byval_arg
);
5456 aklass = array->vtable->klass->element_class;
5457 vklass = value->vtable->klass;
5459 if (vklass->idepth < aklass->idepth)
5462 if (vklass->supertypes [aklass->idepth - 1] != aklass)
5466 array [idx] = value;
5470 if (mono_object_isinst (value, aklass))
5473 throw new ArrayTypeMismatchException ();
5477 mono_mb_emit_ldarg (mb
, 0);
5478 mono_mb_emit_ldarg (mb
, 1);
5479 mono_mb_emit_byte (mb
, CEE_LDELEMA
);
5480 mono_mb_emit_i4 (mb
, mono_mb_add_data (mb
, mono_defaults
.int_class
));
5481 mono_mb_emit_byte (mb
, CEE_POP
);
5483 /* if (!value) goto do_store */
5484 mono_mb_emit_ldarg (mb
, 2);
5485 b1
= mono_mb_emit_branch (mb
, CEE_BRFALSE
);
5487 /* aklass = array->vtable->klass->element_class */
5488 mono_mb_emit_ldarg (mb
, 0);
5489 mono_mb_emit_ldflda (mb
, G_STRUCT_OFFSET (MonoObject
, vtable
));
5490 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
5491 mono_mb_emit_ldflda (mb
, G_STRUCT_OFFSET (MonoVTable
, klass
));
5492 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
5493 mono_mb_emit_ldflda (mb
, G_STRUCT_OFFSET (MonoClass
, element_class
));
5494 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
5495 mono_mb_emit_stloc (mb
, aklass
);
5497 /* vklass = value->vtable->klass */
5498 mono_mb_emit_ldarg (mb
, 2);
5499 mono_mb_emit_ldflda (mb
, G_STRUCT_OFFSET (MonoObject
, vtable
));
5500 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
5501 mono_mb_emit_ldflda (mb
, G_STRUCT_OFFSET (MonoVTable
, klass
));
5502 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
5503 mono_mb_emit_stloc (mb
, vklass
);
5505 /* if (vklass->idepth < aklass->idepth) goto failue */
5506 mono_mb_emit_ldloc (mb
, vklass
);
5507 mono_mb_emit_ldflda (mb
, G_STRUCT_OFFSET (MonoClass
, idepth
));
5508 mono_mb_emit_byte (mb
, CEE_LDIND_I4
);
5510 mono_mb_emit_ldloc (mb
, aklass
);
5511 mono_mb_emit_ldflda (mb
, G_STRUCT_OFFSET (MonoClass
, idepth
));
5512 mono_mb_emit_byte (mb
, CEE_LDIND_I4
);
5514 b2
= mono_mb_emit_branch (mb
, CEE_BLT_UN
);
5516 /* if (vklass->supertypes [aklass->idepth - 1] != aklass) goto failure */
5517 mono_mb_emit_ldloc (mb
, vklass
);
5518 mono_mb_emit_ldflda (mb
, G_STRUCT_OFFSET (MonoClass
, supertypes
));
5519 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
5521 mono_mb_emit_ldloc (mb
, aklass
);
5522 mono_mb_emit_ldflda (mb
, G_STRUCT_OFFSET (MonoClass
, idepth
));
5523 mono_mb_emit_byte (mb
, CEE_LDIND_I4
);
5524 mono_mb_emit_icon (mb
, 1);
5525 mono_mb_emit_byte (mb
, CEE_SUB
);
5526 mono_mb_emit_icon (mb
, sizeof (void*));
5527 mono_mb_emit_byte (mb
, CEE_MUL
);
5528 mono_mb_emit_byte (mb
, CEE_ADD
);
5529 mono_mb_emit_byte (mb
, CEE_LDIND_I
);
5531 mono_mb_emit_ldloc (mb
, aklass
);
5533 b3
= mono_mb_emit_branch (mb
, CEE_BNE_UN
);
5537 mono_mb_patch_addr (mb
, b1
, mb
->pos
- (b1
+ 4));
5538 mono_mb_emit_ldarg (mb
, 0);
5539 mono_mb_emit_ldarg (mb
, 1);
5540 mono_mb_emit_ldarg (mb
, 2);
5541 mono_mb_emit_byte (mb
, CEE_STELEM_I
);
5543 mono_mb_emit_byte (mb
, CEE_RET
);
5546 mono_mb_patch_addr (mb
, b2
, mb
->pos
- (b2
+ 4));
5547 mono_mb_patch_addr (mb
, b3
, mb
->pos
- (b3
+ 4));
5549 mono_mb_emit_ldarg (mb
, 2);
5550 mono_mb_emit_ldloc (mb
, aklass
);
5551 mono_mb_emit_icall (mb
, mono_object_isinst
);
5553 b4
= mono_mb_emit_branch (mb
, CEE_BRTRUE
);
5554 mono_mb_patch_addr (mb
, b4
, copy_pos
- (b4
+ 4));
5555 mono_mb_emit_exception (mb
, "ArrayTypeMismatchException", NULL
);
5557 mono_mb_emit_byte (mb
, CEE_RET
);
5558 ret
= mono_mb_create_method (mb
, sig
, 4);
5564 mono_marshal_alloc (gulong size
)
5568 #ifdef PLATFORM_WIN32
5569 res
= CoTaskMemAlloc (size
);
5571 res
= g_try_malloc ((gulong
)size
);
5573 mono_gc_out_of_memory ((gulong
)size
);
5579 mono_marshal_free (gpointer ptr
)
5581 #ifdef PLATFORM_WIN32
5582 CoTaskMemFree (ptr
);
5589 mono_marshal_free_array (gpointer
*ptr
, int size
)
5596 for (i
= 0; i
< size
; i
++)
5602 mono_marshal_realloc (gpointer ptr
, gpointer size
)
5604 MONO_ARCH_SAVE_REGS
;
5606 return g_try_realloc (ptr
, (gulong
)size
);
5610 mono_marshal_string_to_utf16 (MonoString
*s
)
5612 return s
? mono_string_chars (s
) : NULL
;
5616 * mono_marshal_set_last_error:
5618 * This function is invoked to set the last error value from a P/Invoke call
5619 * which has SetLastError set.
5622 mono_marshal_set_last_error (void)
5625 TlsSetValue (last_error_tls_id
, (gpointer
)GetLastError ());
5627 TlsSetValue (last_error_tls_id
, (gpointer
)errno
);
5632 ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArray
*src
, gint32 start_index
,
5633 gpointer dest
, gint32 length
)
5638 MONO_ARCH_SAVE_REGS
;
5640 MONO_CHECK_ARG_NULL (src
);
5641 MONO_CHECK_ARG_NULL (dest
);
5643 g_assert (src
->obj
.vtable
->klass
->rank
== 1);
5644 g_assert (start_index
>= 0);
5645 g_assert (length
>= 0);
5646 g_assert (start_index
+ length
<= mono_array_length (src
));
5648 element_size
= mono_array_element_size (src
->obj
.vtable
->klass
);
5650 source_addr
= mono_array_addr_with_size (src
, element_size
, start_index
);
5652 memcpy (dest
, source_addr
, length
* element_size
);
5656 ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer src
, gint32 start_index
,
5657 MonoArray
*dest
, gint32 length
)
5662 MONO_ARCH_SAVE_REGS
;
5664 MONO_CHECK_ARG_NULL (src
);
5665 MONO_CHECK_ARG_NULL (dest
);
5667 g_assert (dest
->obj
.vtable
->klass
->rank
== 1);
5668 g_assert (start_index
>= 0);
5669 g_assert (length
>= 0);
5670 g_assert (start_index
+ length
<= mono_array_length (dest
));
5672 element_size
= mono_array_element_size (dest
->obj
.vtable
->klass
);
5674 dest_addr
= mono_array_addr_with_size (dest
, element_size
, start_index
);
5676 memcpy (dest_addr
, src
, length
* element_size
);
5679 #if NO_UNALIGNED_ACCESS
5680 #define RETURN_UNALIGNED(type, addr) \
5683 memcpy(&val, p + offset, sizeof(val)); \
5686 #define WRITE_UNALIGNED(type, addr, val) \
5687 memcpy(addr, &val, sizeof(type))
5689 #define RETURN_UNALIGNED(type, addr) \
5690 return *(type*)(p + offset);
5691 #define WRITE_UNALIGNED(type, addr, val) \
5692 (*(type *)(addr) = (val))
5696 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr
, gint32 offset
)
5700 MONO_ARCH_SAVE_REGS
;
5702 RETURN_UNALIGNED(gpointer
, p
+ offset
);
5706 ves_icall_System_Runtime_InteropServices_Marshal_ReadByte (gpointer ptr
, gint32 offset
)
5710 MONO_ARCH_SAVE_REGS
;
5712 return *(unsigned char*)(p
+ offset
);
5716 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt16 (gpointer ptr
, gint32 offset
)
5720 MONO_ARCH_SAVE_REGS
;
5722 RETURN_UNALIGNED(gint16
, p
+ offset
);
5726 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt32 (gpointer ptr
, gint32 offset
)
5730 MONO_ARCH_SAVE_REGS
;
5732 RETURN_UNALIGNED(gint32
, p
+ offset
);
5736 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt64 (gpointer ptr
, gint32 offset
)
5740 MONO_ARCH_SAVE_REGS
;
5742 RETURN_UNALIGNED(gint64
, p
+ offset
);
5746 ves_icall_System_Runtime_InteropServices_Marshal_WriteByte (gpointer ptr
, gint32 offset
, unsigned char val
)
5750 MONO_ARCH_SAVE_REGS
;
5752 *(unsigned char*)(p
+ offset
) = val
;
5756 ves_icall_System_Runtime_InteropServices_Marshal_WriteIntPtr (gpointer ptr
, gint32 offset
, gpointer val
)
5760 MONO_ARCH_SAVE_REGS
;
5762 WRITE_UNALIGNED(gpointer
, p
+ offset
, val
);
5766 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt16 (gpointer ptr
, gint32 offset
, gint16 val
)
5770 MONO_ARCH_SAVE_REGS
;
5772 WRITE_UNALIGNED(gint16
, p
+ offset
, val
);
5776 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt32 (gpointer ptr
, gint32 offset
, gint32 val
)
5780 MONO_ARCH_SAVE_REGS
;
5782 WRITE_UNALIGNED(gint32
, p
+ offset
, val
);
5786 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt64 (gpointer ptr
, gint32 offset
, gint64 val
)
5790 MONO_ARCH_SAVE_REGS
;
5792 WRITE_UNALIGNED(gint64
, p
+ offset
, val
);
5796 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (char *ptr
)
5798 MONO_ARCH_SAVE_REGS
;
5801 return mono_string_new (mono_domain_get (), "");
5803 return mono_string_new (mono_domain_get (), ptr
);
5807 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len (char *ptr
, gint32 len
)
5809 MONO_ARCH_SAVE_REGS
;
5812 return mono_string_new (mono_domain_get (), "");
5814 return mono_string_new_len (mono_domain_get (), ptr
, len
);
5818 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni (guint16
*ptr
)
5820 MonoDomain
*domain
= mono_domain_get ();
5824 MONO_ARCH_SAVE_REGS
;
5827 return mono_string_new (mono_domain_get (), "");
5832 return mono_string_new_utf16 (domain
, ptr
, len
);
5836 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len (guint16
*ptr
, gint32 len
)
5838 MonoDomain
*domain
= mono_domain_get ();
5840 MONO_ARCH_SAVE_REGS
;
5843 return mono_string_new (mono_domain_get (), "");
5845 return mono_string_new_utf16 (domain
, ptr
, len
);
5849 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR (gpointer ptr
)
5851 MONO_ARCH_SAVE_REGS
;
5853 g_warning ("PtrToStringBSTR not implemented");
5854 g_assert_not_reached ();
5860 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
5862 MONO_ARCH_SAVE_REGS
;
5864 return ((guint32
)TlsGetValue (last_error_tls_id
));
5868 ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType
*rtype
)
5874 MONO_ARCH_SAVE_REGS
;
5876 MONO_CHECK_ARG_NULL (rtype
);
5879 klass
= mono_class_from_mono_type (type
);
5880 layout
= (klass
->flags
& TYPE_ATTRIBUTE_LAYOUT_MASK
);
5882 if (layout
== TYPE_ATTRIBUTE_AUTO_LAYOUT
) {
5886 msg
= g_strdup_printf ("Type %s cannot be marshaled as an unmanaged structure.", klass
->name
);
5887 exc
= mono_get_exception_argument ("t", msg
);
5889 mono_raise_exception (exc
);
5893 return mono_class_native_size (klass
, NULL
);
5897 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject
*obj
, gpointer dst
, MonoBoolean delete_old
)
5902 MONO_ARCH_SAVE_REGS
;
5904 MONO_CHECK_ARG_NULL (obj
);
5905 MONO_CHECK_ARG_NULL (dst
);
5907 method
= mono_marshal_get_struct_to_ptr (obj
->vtable
->klass
);
5911 pa
[2] = &delete_old
;
5913 mono_runtime_invoke (method
, NULL
, pa
, NULL
);
5917 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src
, MonoObject
*dst
)
5922 MONO_ARCH_SAVE_REGS
;
5924 MONO_CHECK_ARG_NULL (src
);
5925 MONO_CHECK_ARG_NULL (dst
);
5927 method
= mono_marshal_get_ptr_to_struct (dst
->vtable
->klass
);
5932 mono_runtime_invoke (method
, NULL
, pa
, NULL
);
5936 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer src
, MonoReflectionType
*type
)
5938 MonoDomain
*domain
= mono_domain_get ();
5941 MONO_ARCH_SAVE_REGS
;
5943 MONO_CHECK_ARG_NULL (src
);
5944 MONO_CHECK_ARG_NULL (type
);
5946 res
= mono_object_new (domain
, mono_class_from_mono_type (type
->type
));
5948 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (src
, res
);
5954 ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType
*type
, MonoString
*field_name
)
5956 MonoMarshalType
*info
;
5959 int i
, match_index
= -1;
5961 MONO_ARCH_SAVE_REGS
;
5963 MONO_CHECK_ARG_NULL (type
);
5964 MONO_CHECK_ARG_NULL (field_name
);
5966 fname
= mono_string_to_utf8 (field_name
);
5967 klass
= mono_class_from_mono_type (type
->type
);
5969 while (klass
&& match_index
== -1) {
5970 for (i
= 0; i
< klass
->field
.count
; ++i
) {
5971 if (*fname
== *klass
->fields
[i
].name
&& strcmp (fname
, klass
->fields
[i
].name
) == 0) {
5977 if (match_index
== -1)
5978 klass
= klass
->parent
;
5983 if(match_index
== -1) {
5987 /* Get back original class instance */
5988 klass
= mono_class_from_mono_type (type
->type
);
5990 tmp
= g_strdup_printf ("Field passed in is not a marshaled member of the type %s", klass
->name
);
5991 exc
= mono_get_exception_argument ("fieldName", tmp
);
5994 mono_raise_exception ((MonoException
*)exc
);
5997 info
= mono_marshal_load_type_info (klass
);
5998 return info
->fields
[match_index
].offset
;
6002 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString
*string
)
6004 MONO_ARCH_SAVE_REGS
;
6006 return mono_string_to_utf8 (string
);
6010 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni (MonoString
*string
)
6012 MONO_ARCH_SAVE_REGS
;
6017 return g_memdup (mono_string_chars (string
), mono_string_length (string
)*2);
6021 mono_struct_delete_old (MonoClass
*klass
, char *ptr
)
6023 MonoMarshalType
*info
;
6026 info
= mono_marshal_load_type_info (klass
);
6028 for (i
= 0; i
< info
->num_fields
; i
++) {
6029 MonoMarshalNative ntype
;
6030 MonoMarshalConv conv
;
6031 MonoType
*ftype
= info
->fields
[i
].field
->type
;
6034 if (ftype
->attrs
& FIELD_ATTRIBUTE_STATIC
)
6037 ntype
= mono_type_to_unmanaged (ftype
, info
->fields
[i
].mspec
, TRUE
,
6038 klass
->unicode
, &conv
);
6040 cpos
= ptr
+ info
->fields
[i
].offset
;
6043 case MONO_MARSHAL_CONV_NONE
:
6044 if (MONO_TYPE_ISSTRUCT (ftype
)) {
6045 mono_struct_delete_old (ftype
->data
.klass
, cpos
);
6049 case MONO_MARSHAL_CONV_STR_LPWSTR
:
6050 case MONO_MARSHAL_CONV_STR_LPSTR
:
6051 case MONO_MARSHAL_CONV_STR_LPTSTR
:
6052 case MONO_MARSHAL_CONV_STR_BSTR
:
6053 case MONO_MARSHAL_CONV_STR_ANSIBSTR
:
6054 case MONO_MARSHAL_CONV_STR_TBSTR
:
6055 mono_marshal_free (*(gpointer
*)cpos
);
6064 ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure (gpointer src
, MonoReflectionType
*type
)
6068 MONO_ARCH_SAVE_REGS
;
6070 MONO_CHECK_ARG_NULL (src
);
6071 MONO_CHECK_ARG_NULL (type
);
6073 klass
= mono_class_from_mono_type (type
->type
);
6075 mono_struct_delete_old (klass
, (char *)src
);
6079 /* FIXME: on win32 we should probably use GlobalAlloc(). */
6081 ves_icall_System_Runtime_InteropServices_Marshal_AllocHGlobal (int size
)
6085 MONO_ARCH_SAVE_REGS
;
6087 if ((gulong
)size
== 0)
6088 /* This returns a valid pointer for size 0 on MS.NET */
6091 res
= g_try_malloc ((gulong
)size
);
6093 mono_gc_out_of_memory ((gulong
)size
);
6099 ves_icall_System_Runtime_InteropServices_Marshal_FreeHGlobal (void *ptr
)
6101 MONO_ARCH_SAVE_REGS
;
6107 ves_icall_System_Runtime_InteropServices_Marshal_AllocCoTaskMem (int size
)
6109 MONO_ARCH_SAVE_REGS
;
6111 #ifdef PLATFORM_WIN32
6112 return CoTaskMemAlloc (size
);
6114 return g_try_malloc ((gulong
)size
);
6119 ves_icall_System_Runtime_InteropServices_Marshal_FreeCoTaskMem (void *ptr
)
6121 MONO_ARCH_SAVE_REGS
;
6123 #ifdef PLATFORM_WIN32
6124 CoTaskMemFree (ptr
);
6131 ves_icall_System_Runtime_InteropServices_Marshal_UnsafeAddrOfPinnedArrayElement (MonoArray
*arrayobj
, int index
)
6133 return mono_array_addr_with_size (arrayobj
, mono_array_element_size (arrayobj
->obj
.vtable
->klass
), index
);
6137 ves_icall_System_Runtime_InteropServices_Marshal_GetDelegateForFunctionPointerInternal (void *ftn
, MonoReflectionType
*type
)
6139 return mono_ftnptr_to_delegate (mono_type_get_class (type
->type
), ftn
);
6143 mono_marshal_load_type_info (MonoClass
* klass
)
6145 int i
, j
, count
= 0, native_size
= 0, min_align
= 1;
6146 MonoMarshalType
*info
;
6149 g_assert (klass
!= NULL
);
6151 if (klass
->marshal_info
)
6152 return klass
->marshal_info
;
6155 mono_class_init (klass
);
6157 for (i
= 0; i
< klass
->field
.count
; ++i
) {
6158 if (klass
->fields
[i
].type
->attrs
& FIELD_ATTRIBUTE_STATIC
)
6160 if (mono_field_is_deleted (&klass
->fields
[i
]))
6165 layout
= klass
->flags
& TYPE_ATTRIBUTE_LAYOUT_MASK
;
6167 klass
->marshal_info
= info
= g_malloc0 (sizeof (MonoMarshalType
) + sizeof (MonoMarshalField
) * count
);
6168 info
->num_fields
= count
;
6170 /* Try to find a size for this type in metadata */
6171 mono_metadata_packing_from_typedef (klass
->image
, klass
->type_token
, NULL
, &native_size
);
6173 if (klass
->parent
) {
6174 int parent_size
= mono_class_native_size (klass
->parent
, NULL
);
6176 /* Add parent size to real size */
6177 native_size
+= parent_size
;
6178 info
->native_size
= parent_size
;
6181 for (j
= i
= 0; i
< klass
->field
.count
; ++i
) {
6184 if (klass
->fields
[i
].type
->attrs
& FIELD_ATTRIBUTE_STATIC
)
6187 if (mono_field_is_deleted (&klass
->fields
[i
]))
6189 if (klass
->fields
[i
].type
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL
)
6190 mono_metadata_field_info (klass
->image
, klass
->field
.first
+ i
,
6191 NULL
, NULL
, &info
->fields
[j
].mspec
);
6193 info
->fields
[j
].field
= &klass
->fields
[i
];
6195 if ((klass
->field
.count
== 1) && (klass
->instance_size
== sizeof (MonoObject
)) &&
6196 (strcmp (klass
->fields
[i
].name
, "$PRIVATE$") == 0)) {
6197 /* This field is a hack inserted by MCS to empty structures */
6202 case TYPE_ATTRIBUTE_AUTO_LAYOUT
:
6203 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT
:
6204 size
= mono_marshal_type_size (klass
->fields
[i
].type
, info
->fields
[j
].mspec
,
6205 &align
, TRUE
, klass
->unicode
);
6206 align
= klass
->packing_size
? MIN (klass
->packing_size
, align
): align
;
6207 min_align
= MAX (align
, min_align
);
6208 info
->fields
[j
].offset
= info
->native_size
;
6209 info
->fields
[j
].offset
+= align
- 1;
6210 info
->fields
[j
].offset
&= ~(align
- 1);
6211 info
->native_size
= info
->fields
[j
].offset
+ size
;
6213 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT
:
6214 size
= mono_marshal_type_size (klass
->fields
[i
].type
, info
->fields
[j
].mspec
,
6215 &align
, TRUE
, klass
->unicode
);
6216 align
= klass
->packing_size
? MIN (klass
->packing_size
, align
): align
;
6217 min_align
= MAX (align
, min_align
);
6218 info
->fields
[j
].offset
= klass
->fields
[i
].offset
- sizeof (MonoObject
);
6219 info
->native_size
= MAX (info
->native_size
, info
->fields
[j
].offset
+ size
);
6225 if(layout
!= TYPE_ATTRIBUTE_AUTO_LAYOUT
) {
6226 info
->native_size
= MAX (native_size
, info
->native_size
);
6229 if (info
->native_size
& (min_align
- 1)) {
6230 info
->native_size
+= min_align
- 1;
6231 info
->native_size
&= ~(min_align
- 1);
6234 /* Update the class's blittable info, if the layouts don't match */
6235 if (info
->native_size
!= mono_class_value_size (klass
, NULL
))
6236 klass
->blittable
= FALSE
;
6238 /* If this is an array type, ensure that we have element info */
6239 if (klass
->element_class
) {
6240 mono_marshal_load_type_info (klass
->element_class
);
6243 return klass
->marshal_info
;
6247 * mono_class_native_size:
6250 * Returns: the native size of an object instance (when marshaled
6251 * to unmanaged code)
6254 mono_class_native_size (MonoClass
*klass
, guint32
*align
)
6257 if (!klass
->marshal_info
)
6258 mono_marshal_load_type_info (klass
);
6261 *align
= klass
->min_align
;
6263 return klass
->marshal_info
->native_size
;
6267 * mono_type_native_stack_size:
6268 * @t: the type to return the size it uses on the stack
6270 * Returns: the number of bytes required to hold an instance of this
6271 * type on the native stack
6274 mono_type_native_stack_size (MonoType
*t
, gint
*align
)
6278 g_assert (t
!= NULL
);
6289 case MONO_TYPE_BOOLEAN
:
6290 case MONO_TYPE_CHAR
:
6299 case MONO_TYPE_STRING
:
6300 case MONO_TYPE_OBJECT
:
6301 case MONO_TYPE_CLASS
:
6302 case MONO_TYPE_SZARRAY
:
6304 case MONO_TYPE_FNPTR
:
6305 case MONO_TYPE_ARRAY
:
6306 case MONO_TYPE_TYPEDBYREF
:
6317 case MONO_TYPE_VALUETYPE
: {
6320 if (t
->data
.klass
->enumtype
)
6321 return mono_type_native_stack_size (t
->data
.klass
->enum_basetype
, align
);
6323 size
= mono_class_native_size (t
->data
.klass
, align
);
6324 *align
= *align
+ 3;
6334 g_error ("type 0x%02x unknown", t
->type
);
6339 /* __alignof__ returns the preferred alignment of values not the actual alignment used by
6340 the compiler so is wrong e.g. for Linux where doubles are aligned on a 4 byte boundary
6341 but __alignof__ returns 8 - using G_STRUCT_OFFSET works better */
6342 #define ALIGNMENT(type) G_STRUCT_OFFSET(struct { char c; type x; }, x)
6345 mono_marshal_type_size (MonoType
*type
, MonoMarshalSpec
*mspec
, gint32
*align
,
6346 gboolean as_field
, gboolean unicode
)
6348 MonoMarshalNative native_type
= mono_type_to_unmanaged (type
, mspec
, as_field
, unicode
, NULL
);
6351 switch (native_type
) {
6352 case MONO_NATIVE_BOOLEAN
:
6355 case MONO_NATIVE_I1
:
6356 case MONO_NATIVE_U1
:
6359 case MONO_NATIVE_I2
:
6360 case MONO_NATIVE_U2
:
6361 case MONO_NATIVE_VARIANTBOOL
:
6364 case MONO_NATIVE_I4
:
6365 case MONO_NATIVE_U4
:
6366 case MONO_NATIVE_ERROR
:
6369 case MONO_NATIVE_I8
:
6370 case MONO_NATIVE_U8
:
6371 *align
= ALIGNMENT(guint64
);
6373 case MONO_NATIVE_R4
:
6376 case MONO_NATIVE_R8
:
6377 *align
= ALIGNMENT(double);
6379 case MONO_NATIVE_INT
:
6380 case MONO_NATIVE_UINT
:
6381 case MONO_NATIVE_LPSTR
:
6382 case MONO_NATIVE_LPWSTR
:
6383 case MONO_NATIVE_LPTSTR
:
6384 case MONO_NATIVE_BSTR
:
6385 case MONO_NATIVE_ANSIBSTR
:
6386 case MONO_NATIVE_TBSTR
:
6387 case MONO_NATIVE_LPARRAY
:
6388 case MONO_NATIVE_SAFEARRAY
:
6389 case MONO_NATIVE_IUNKNOWN
:
6390 case MONO_NATIVE_IDISPATCH
:
6391 case MONO_NATIVE_INTERFACE
:
6392 case MONO_NATIVE_ASANY
:
6393 case MONO_NATIVE_FUNC
:
6394 case MONO_NATIVE_LPSTRUCT
:
6395 *align
= ALIGNMENT(gpointer
);
6396 return sizeof (gpointer
);
6397 case MONO_NATIVE_STRUCT
:
6398 klass
= mono_class_from_mono_type (type
);
6399 return mono_class_native_size (klass
, align
);
6400 case MONO_NATIVE_BYVALTSTR
: {
6401 int esize
= unicode
? 2: 1;
6404 return mspec
->data
.array_data
.num_elem
* esize
;
6406 case MONO_NATIVE_BYVALARRAY
: {
6408 klass
= mono_class_from_mono_type (type
);
6409 esize
= mono_class_native_size (klass
->element_class
, align
);
6411 return mspec
->data
.array_data
.num_elem
* esize
;
6413 case MONO_NATIVE_CUSTOM
:
6414 g_assert_not_reached ();
6416 case MONO_NATIVE_CURRENCY
:
6417 case MONO_NATIVE_VBBYREFSTR
:
6419 g_error ("native type %02x not implemented", native_type
);
6422 g_assert_not_reached ();
6427 mono_marshal_asany (MonoObject
*o
, MonoMarshalNative string_encoding
)
6435 t
= &o
->vtable
->klass
->byval_arg
;
6442 case MONO_TYPE_BOOLEAN
:
6445 case MONO_TYPE_CHAR
:
6450 return mono_object_unbox (o
);
6452 case MONO_TYPE_STRING
:
6453 switch (string_encoding
) {
6454 case MONO_NATIVE_LPWSTR
:
6455 return mono_string_to_utf16 ((MonoString
*)o
);
6457 case MONO_NATIVE_LPSTR
:
6458 return mono_string_to_lpstr ((MonoString
*)o
);
6461 g_warning ("marshaling conversion %d not implemented", string_encoding
);
6462 g_assert_not_reached ();
6465 case MONO_TYPE_CLASS
:
6466 case MONO_TYPE_VALUETYPE
: {
6470 MonoBoolean delete_old
= FALSE
;
6472 klass
= t
->data
.klass
;
6474 if ((klass
->flags
& TYPE_ATTRIBUTE_LAYOUT_MASK
) == TYPE_ATTRIBUTE_AUTO_LAYOUT
)
6477 if (((klass
->flags
& TYPE_ATTRIBUTE_LAYOUT_MASK
) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT
) ||
6478 klass
->blittable
|| klass
->enumtype
)
6479 return mono_object_unbox (o
);
6481 res
= mono_marshal_alloc (mono_class_native_size (klass
, NULL
));
6483 method
= mono_marshal_get_struct_to_ptr (o
->vtable
->klass
);
6487 pa
[2] = &delete_old
;
6489 mono_runtime_invoke (method
, NULL
, pa
, NULL
);
6495 mono_raise_exception (mono_get_exception_argument ("", "No PInvoke conversion exists for value passed to Object-typed parameter."));
6501 mono_marshal_free_asany (MonoObject
*o
, gpointer ptr
, MonoMarshalNative string_encoding
)
6509 t
= &o
->vtable
->klass
->byval_arg
;
6511 case MONO_TYPE_STRING
:
6512 switch (string_encoding
) {
6513 case MONO_NATIVE_LPWSTR
:
6514 case MONO_NATIVE_LPSTR
:
6515 mono_marshal_free (ptr
);
6518 g_warning ("marshaling conversion %d not implemented", string_encoding
);
6519 g_assert_not_reached ();
6522 case MONO_TYPE_CLASS
:
6523 case MONO_TYPE_VALUETYPE
: {
6524 klass
= t
->data
.klass
;
6526 if (((klass
->flags
& TYPE_ATTRIBUTE_LAYOUT_MASK
) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT
) ||
6527 klass
->blittable
|| klass
->enumtype
)
6530 mono_struct_delete_old (klass
, ptr
);
6532 mono_marshal_free (ptr
);