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"
21 //#define DEBUG_RUNTIME_CODE
23 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
27 #include "mono/cil/opcode.def"
32 struct _MonoMethodBuilder {
36 guint32 code_size, pos;
40 #ifdef DEBUG_RUNTIME_CODE
42 indenter (MonoDisHelper *dh, MonoMethod *method, guint32 ip_offset)
44 return g_strdup (" ");
47 static MonoDisHelper marshal_dh = {
58 mono_delegate_to_ftnptr (MonoDelegate *delegate)
60 MonoMethod *method, *invoke, *wrapper;
61 MonoMethodSignature *sig;
67 if (delegate->delegate_trampoline)
68 return delegate->delegate_trampoline;
70 klass = ((MonoObject *)delegate)->vtable->klass;
71 g_assert (klass->delegate);
73 method = delegate->method_info->method;
74 sig = method->signature;
76 invoke = mono_get_delegate_invoke (klass);
77 wrapper = mono_marshal_get_managed_wrapper (invoke, (MonoObject *)delegate);
79 delegate->delegate_trampoline = mono_compile_method (wrapper);
81 return delegate->delegate_trampoline;
85 mono_array_to_savearray (MonoArray *array)
90 g_assert_not_reached ();
95 mono_array_to_lparray (MonoArray *array)
100 g_assert_not_reached ();
105 mono_string_to_ansibstr (MonoString *string_obj)
107 g_error ("implement me");
112 mono_string_to_bstr (MonoString *string_obj)
114 g_error ("implement me");
119 mono_string_to_byvalstr (gpointer dst, MonoString *src, int size)
124 g_assert (dst != NULL);
128 memset (dst, 0, size);
132 s = mono_string_to_utf8 (src);
133 len = MIN (size, strlen (s));
134 memcpy (dst, s, len);
137 *((char *)dst + size - 1) = 0;
141 mono_string_to_byvalwstr (gpointer dst, MonoString *src, int size)
145 g_assert (dst != NULL);
149 memset (dst, 0, size);
153 len = MIN (size, (mono_string_length (src) * 2));
154 memcpy (dst, mono_string_chars (src), len);
156 *((char *)dst + size - 1) = 0;
157 *((char *)dst + size - 2) = 0;
162 mono_find_method_by_name (MonoClass *klass, const char *name, int param_count)
164 MonoMethod *res = NULL;
167 for (i = 0; i < klass->method.count; ++i) {
168 if ((klass->methods [i]->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
169 klass->methods [i]->name[0] == name [0] &&
170 !strcmp (name, klass->methods [i]->name) &&
171 klass->methods [i]->signature->param_count == param_count) {
172 res = klass->methods [i];
180 mono_mb_free (MonoMethodBuilder *mb)
182 g_list_free (mb->locals_list);
187 mono_mb_new (MonoClass *klass, const char *name)
189 MonoMethodBuilder *mb;
192 g_assert (klass != NULL);
193 g_assert (name != NULL);
195 mb = g_new0 (MonoMethodBuilder, 1);
197 mb->method = m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
200 m->name = g_strdup (name);
202 m->inline_count = -1;
203 m->wrapper_type = MONO_WRAPPER_UNKNOWN;
206 mb->code = g_malloc (mb->code_size);
212 mono_mb_add_local (MonoMethodBuilder *mb, MonoType *type)
214 int res = mb->locals;
216 g_assert (mb != NULL);
217 g_assert (type != NULL);
219 mb->locals_list = g_list_append (mb->locals_list, type);
226 mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack)
228 MonoMethodHeader *header;
232 g_assert (mb != NULL);
234 ((MonoMethodNormal *)mb->method)->header = header = (MonoMethodHeader *)
235 g_malloc0 (sizeof (MonoMethodHeader) + mb->locals * sizeof (MonoType *));
240 header->max_stack = max_stack;
242 for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
243 header->locals [i] = (MonoType *)l->data;
246 mb->method->signature = signature;
247 header->code = mb->code;
248 header->code_size = mb->pos;
249 header->num_locals = mb->locals;
251 #ifdef DEBUG_RUNTIME_CODE
252 printf ("RUNTIME CODE FOR %s\n", mono_method_full_name (mb->method, TRUE));
253 printf ("%s\n", mono_disasm_code (&marshal_dh, mb->method, mb->code, mb->code + mb->pos));
260 mono_mb_add_data (MonoMethodBuilder *mb, gpointer data)
262 MonoMethodWrapper *mw;
264 g_assert (mb != NULL);
266 mw = (MonoMethodWrapper *)mb->method;
268 mw->data = g_list_append (mw->data, data);
270 return g_list_length (mw->data);
274 mono_mb_patch_addr (MonoMethodBuilder *mb, int pos, int value)
276 *((gint32 *)(&mb->code [pos])) = value;
280 mono_mb_emit_byte (MonoMethodBuilder *mb, guint8 op)
282 if (mb->pos >= mb->code_size) {
284 mb->code = g_realloc (mb->code, mb->code_size);
287 mb->code [mb->pos++] = op;
291 mono_mb_emit_i4 (MonoMethodBuilder *mb, gint32 data)
293 if ((mb->pos + 4) >= mb->code_size) {
295 mb->code = g_realloc (mb->code, mb->code_size);
298 *((gint32 *)(&mb->code [mb->pos])) = data;
303 mono_mb_emit_i2 (MonoMethodBuilder *mb, gint16 data)
305 if ((mb->pos + 2) >= mb->code_size) {
307 mb->code = g_realloc (mb->code, mb->code_size);
310 *((gint16 *)(&mb->code [mb->pos])) = data;
315 mono_mb_emit_ldarg (MonoMethodBuilder *mb, guint argnum)
318 mono_mb_emit_byte (mb, CEE_LDARG_0 + argnum);
319 } else if (argnum < 256) {
320 mono_mb_emit_byte (mb, CEE_LDARG_S);
321 mono_mb_emit_byte (mb, argnum);
323 mono_mb_emit_byte (mb, CEE_PREFIX1);
324 mono_mb_emit_byte (mb, CEE_LDARG);
325 mono_mb_emit_i4 (mb, argnum);
330 mono_mb_emit_ldarg_addr (MonoMethodBuilder *mb, guint argnum)
333 mono_mb_emit_byte (mb, CEE_LDARGA_S);
334 mono_mb_emit_byte (mb, argnum);
336 mono_mb_emit_byte (mb, CEE_PREFIX1);
337 mono_mb_emit_byte (mb, CEE_LDARGA);
338 mono_mb_emit_i4 (mb, argnum);
343 mono_mb_emit_ldloc (MonoMethodBuilder *mb, guint num)
346 mono_mb_emit_byte (mb, CEE_LDLOC_0 + num);
347 } else if (num < 256) {
348 mono_mb_emit_byte (mb, CEE_LDLOC_S);
349 mono_mb_emit_byte (mb, num);
351 mono_mb_emit_byte (mb, CEE_PREFIX1);
352 mono_mb_emit_byte (mb, CEE_LDLOC);
353 mono_mb_emit_i4 (mb, num);
358 mono_mb_emit_stloc (MonoMethodBuilder *mb, guint num)
361 mono_mb_emit_byte (mb, CEE_STLOC_0 + num);
362 } else if (num < 256) {
363 mono_mb_emit_byte (mb, CEE_STLOC_S);
364 mono_mb_emit_byte (mb, num);
366 mono_mb_emit_byte (mb, CEE_PREFIX1);
367 mono_mb_emit_byte (mb, CEE_STLOC);
368 mono_mb_emit_i4 (mb, num);
373 mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value)
375 if (value >= -1 && value < 8) {
376 mono_mb_emit_byte (mb, CEE_LDC_I4_0 + value);
377 } else if (value >= -128 && value <= 127) {
378 mono_mb_emit_byte (mb, CEE_LDC_I4_S);
379 mono_mb_emit_byte (mb, value);
381 mono_mb_emit_byte (mb, CEE_LDC_I4);
382 mono_mb_emit_i4 (mb, value);
387 mono_mb_emit_managed_call (MonoMethodBuilder *mb, MonoMethod *method, MonoMethodSignature *opt_sig)
390 opt_sig = method->signature;
391 mono_mb_emit_byte (mb, CEE_PREFIX1);
392 mono_mb_emit_byte (mb, CEE_LDFTN);
393 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
394 mono_mb_emit_byte (mb, CEE_CALLI);
395 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, opt_sig));
399 mono_mb_emit_native_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, gpointer func)
401 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
402 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
403 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, func));
404 mono_mb_emit_byte (mb, CEE_CALLI);
405 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
409 mono_mb_emit_exception (MonoMethodBuilder *mb)
411 mono_mb_emit_byte (mb, CEE_LDNULL);
412 mono_mb_emit_byte (mb, CEE_THROW);
417 mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint8 local, gint8 incr)
419 mono_mb_emit_ldloc (mb, local);
420 mono_mb_emit_icon (mb, incr);
421 mono_mb_emit_byte (mb, CEE_ADD);
422 mono_mb_emit_stloc (mb, local);
426 emit_ptr_to_str_conv (MonoMethodBuilder *mb, MonoMarshalConv conv, int usize, int msize)
428 /* fixme: dont know what do do here - docs say
429 this does not work for value types */
431 g_warning ("not implemented");
432 g_assert_not_reached ();
436 emit_str_to_ptr_conv (MonoMethodBuilder *mb, MonoMarshalConv conv, int usize, int msize)
439 case MONO_MARSHAL_CONV_BOOL_I4:
440 mono_mb_emit_byte (mb, CEE_LDLOC_1);
441 mono_mb_emit_byte (mb, CEE_LDLOC_0);
442 mono_mb_emit_byte (mb, CEE_LDIND_U1);
443 mono_mb_emit_byte (mb, CEE_STIND_I4);
445 case MONO_MARSHAL_CONV_STR_LPWSTR:
446 case MONO_MARSHAL_CONV_STR_LPSTR:
447 case MONO_MARSHAL_CONV_STR_LPTSTR:
448 case MONO_MARSHAL_CONV_STR_BSTR:
449 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
450 case MONO_MARSHAL_CONV_STR_TBSTR:
451 case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
452 case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
453 /* free space if ARG_2 == true */
454 mono_mb_emit_byte (mb, CEE_LDARG_2);
455 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
456 mono_mb_emit_byte (mb, 4);
457 mono_mb_emit_byte (mb, CEE_LDLOC_1);
458 mono_mb_emit_byte (mb, CEE_LDIND_I);
459 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
460 mono_mb_emit_byte (mb, CEE_MONO_FREE);
462 mono_mb_emit_byte (mb, CEE_LDLOC_1);
463 mono_mb_emit_byte (mb, CEE_LDLOC_0);
464 mono_mb_emit_byte (mb, CEE_LDIND_I);
465 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
466 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
467 mono_mb_emit_byte (mb, conv);
468 mono_mb_emit_byte (mb, CEE_STIND_I);
470 case MONO_MARSHAL_CONV_STR_BYVALSTR:
471 case MONO_MARSHAL_CONV_STR_BYVALWSTR: {
475 mono_mb_emit_byte (mb, CEE_LDLOC_1); /* dst */
476 mono_mb_emit_byte (mb, CEE_LDLOC_0);
477 mono_mb_emit_byte (mb, CEE_LDIND_I); /* src String */
478 mono_mb_emit_icon (mb, usize);
479 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
480 mono_mb_emit_byte (mb, CEE_MONO_PROC3);
481 mono_mb_emit_byte (mb, conv);
484 case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
488 mono_mb_emit_byte (mb, CEE_LDLOC_0);
489 mono_mb_emit_byte (mb, CEE_LDIND_I);
490 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
491 mono_mb_emit_byte (mb, 15);
493 mono_mb_emit_byte (mb, CEE_LDLOC_1);
494 mono_mb_emit_byte (mb, CEE_LDLOC_0);
495 mono_mb_emit_byte (mb, CEE_LDIND_I);
496 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
497 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
498 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
499 mono_mb_emit_byte (mb, CEE_ADD);
500 mono_mb_emit_icon (mb, usize);
501 mono_mb_emit_byte (mb, CEE_PREFIX1);
502 mono_mb_emit_byte (mb, CEE_CPBLK);
505 case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
507 g_error ("marshalling conversion %d not implemented", conv);
512 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
514 MonoMarshalType *info;
517 info = mono_marshal_load_type_info (klass);
519 for (i = 0; i < info->num_fields; i++) {
520 MonoMarshalNative ntype;
521 MonoMarshalConv conv;
522 MonoType *ftype = info->fields [i].field->type;
525 gboolean last_field = i < (info->num_fields -1) ? 0 : 1;
527 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
530 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, klass->unicode, &conv);
533 msize = klass->instance_size - info->fields [i].field->offset;
534 usize = info->native_size - info->fields [i].offset;
536 msize = klass->fields [i + 1].offset - info->fields [i].field->offset;
537 usize = info->fields [i + 1].offset - info->fields [i].offset;
539 g_assert (msize > 0 && usize > 0);
542 case MONO_MARSHAL_CONV_NONE:
544 if (ftype->byref || ftype->type == MONO_TYPE_I ||
545 ftype->type == MONO_TYPE_U) {
546 mono_mb_emit_byte (mb, CEE_LDLOC_1);
547 mono_mb_emit_byte (mb, CEE_LDLOC_0);
548 mono_mb_emit_byte (mb, CEE_LDIND_I);
549 mono_mb_emit_byte (mb, CEE_STIND_I);
553 switch (ftype->type) {
556 mono_mb_emit_byte (mb, CEE_LDLOC_1);
557 mono_mb_emit_byte (mb, CEE_LDLOC_0);
558 mono_mb_emit_byte (mb, CEE_LDIND_I4);
559 mono_mb_emit_byte (mb, CEE_STIND_I4);
563 case MONO_TYPE_BOOLEAN:
564 mono_mb_emit_byte (mb, CEE_LDLOC_1);
565 mono_mb_emit_byte (mb, CEE_LDLOC_0);
566 mono_mb_emit_byte (mb, CEE_LDIND_I1);
567 mono_mb_emit_byte (mb, CEE_STIND_I1);
571 mono_mb_emit_byte (mb, CEE_LDLOC_1);
572 mono_mb_emit_byte (mb, CEE_LDLOC_0);
573 mono_mb_emit_byte (mb, CEE_LDIND_I2);
574 mono_mb_emit_byte (mb, CEE_STIND_I2);
578 mono_mb_emit_byte (mb, CEE_LDLOC_1);
579 mono_mb_emit_byte (mb, CEE_LDLOC_0);
580 mono_mb_emit_byte (mb, CEE_LDIND_I8);
581 mono_mb_emit_byte (mb, CEE_STIND_I8);
584 mono_mb_emit_byte (mb, CEE_LDLOC_1);
585 mono_mb_emit_byte (mb, CEE_LDLOC_0);
586 mono_mb_emit_byte (mb, CEE_LDIND_R4);
587 mono_mb_emit_byte (mb, CEE_STIND_R4);
590 mono_mb_emit_byte (mb, CEE_LDLOC_1);
591 mono_mb_emit_byte (mb, CEE_LDLOC_0);
592 mono_mb_emit_byte (mb, CEE_LDIND_R8);
593 mono_mb_emit_byte (mb, CEE_STIND_R8);
595 case MONO_TYPE_VALUETYPE:
596 emit_struct_conv (mb, ftype->data.klass, to_object);
599 g_error ("marshalling type %02x not implemented", ftype->type);
605 emit_ptr_to_str_conv (mb, conv, usize, msize);
607 emit_str_to_ptr_conv (mb, conv, usize, msize);
611 mono_mb_emit_add_to_local (mb, 0, msize);
612 mono_mb_emit_add_to_local (mb, 1, usize);
617 static MonoAsyncResult *
618 mono_delegate_begin_invoke (MonoDelegate *delegate, gpointer *params)
620 MonoMethodMessage *msg;
621 MonoDelegate *async_callback;
625 MonoMethod *method = NULL;
630 klass = delegate->object.vtable->klass;
632 method = mono_get_delegate_invoke (klass);
633 for (i = 0; i < klass->method.count; ++i) {
634 if (klass->methods [i]->name[0] == 'B' &&
635 !strcmp ("BeginInvoke", klass->methods [i]->name)) {
636 method = klass->methods [i];
641 g_assert (method != NULL);
643 im = mono_get_delegate_invoke (method->klass);
645 msg = mono_method_call_message_new (method, params, im, &async_callback, &state);
647 return mono_thread_pool_add ((MonoObject *)delegate, msg, async_callback, state);
651 mono_mb_emit_save_args (MonoMethodBuilder *mb, MonoMethodSignature *sig, gboolean save_this)
653 int i, params_var, tmp_var;
655 /* allocate local (pointer) *params[] */
656 params_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
657 /* allocate local (pointer) tmp */
658 tmp_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
660 /* alloate space on stack to store an array of pointers to the arguments */
661 mono_mb_emit_icon (mb, sizeof (gpointer) * (sig->param_count + 1));
662 mono_mb_emit_byte (mb, CEE_PREFIX1);
663 mono_mb_emit_byte (mb, CEE_LOCALLOC);
664 mono_mb_emit_stloc (mb, params_var);
667 mono_mb_emit_ldloc (mb, params_var);
668 mono_mb_emit_stloc (mb, tmp_var);
670 if (save_this && sig->hasthis) {
671 mono_mb_emit_ldloc (mb, tmp_var);
672 mono_mb_emit_ldarg_addr (mb, 0);
673 mono_mb_emit_byte (mb, CEE_STIND_I);
674 /* tmp = tmp + sizeof (gpointer) */
675 if (sig->param_count)
676 mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
680 for (i = 0; i < sig->param_count; i++) {
681 mono_mb_emit_ldloc (mb, tmp_var);
682 mono_mb_emit_ldarg_addr (mb, i + sig->hasthis);
683 mono_mb_emit_byte (mb, CEE_STIND_I);
684 /* tmp = tmp + sizeof (gpointer) */
685 if (i < (sig->param_count - 1))
686 mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
693 mono_marshal_get_delegate_begin_invoke (MonoMethod *method)
695 MonoMethodSignature *sig;
696 static MonoMethodSignature *csig = NULL;
697 MonoMethodBuilder *mb;
702 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
703 !strcmp (method->name, "BeginInvoke"));
705 sig = method->signature;
707 cache = method->klass->image->delegate_begin_invoke_cache;
708 if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
711 g_assert (sig->hasthis);
714 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
715 csig = g_malloc0 (sigsize);
717 /* MonoAsyncResult * begin_invoke (MonoDelegate *delegate, gpointer params[]) */
718 csig->param_count = 2;
719 csig->ret = &mono_defaults.object_class->byval_arg;
720 csig->params [0] = &mono_defaults.object_class->byval_arg;
721 csig->params [1] = &mono_defaults.int_class->byval_arg;
724 mb = mono_mb_new (method->klass, method->name);
725 mb->method->wrapper_type = MONO_WRAPPER_DELEGATE_BEGIN_INVOKE;
726 mb->method->save_lmf = 1;
728 params_var = mono_mb_emit_save_args (mb, sig, FALSE);
730 mono_mb_emit_ldarg (mb, 0);
731 mono_mb_emit_ldloc (mb, params_var);
732 mono_mb_emit_native_call (mb, csig, mono_delegate_begin_invoke);
733 mono_mb_emit_byte (mb, CEE_RET);
735 res = mono_mb_create_method (mb, sig, 0);
737 g_hash_table_insert (cache, sig, res);
742 mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params)
744 MonoDomain *domain = mono_domain_get ();
745 MonoAsyncResult *ares;
746 MonoMethod *method = NULL;
747 MonoMethodSignature *sig;
748 MonoMethodMessage *msg;
749 MonoObject *res, *exc;
756 if (!delegate->method_info || !delegate->method_info->method)
757 g_assert_not_reached ();
759 klass = delegate->object.vtable->klass;
761 for (i = 0; i < klass->method.count; ++i) {
762 if (klass->methods [i]->name[0] == 'E' &&
763 !strcmp ("EndInvoke", klass->methods [i]->name)) {
764 method = klass->methods [i];
769 g_assert (method != NULL);
771 sig = method->signature;
773 msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
775 ares = mono_array_get (msg->args, gpointer, sig->param_count - 1);
778 res = mono_thread_pool_finish (ares, &out_args, &exc);
781 char *strace = mono_string_to_utf8 (((MonoException*)exc)->stack_trace);
783 tmp = g_strdup_printf ("%s\nException Rethrown at:\n", strace);
785 ((MonoException*)exc)->stack_trace = mono_string_new (domain, tmp);
787 mono_raise_exception ((MonoException*)exc);
790 mono_method_return_message_restore (method, params, out_args);
795 mono_mb_emit_restore_result (MonoMethodBuilder *mb, MonoType *return_type)
797 if (return_type->byref)
798 return_type = &mono_defaults.int_class->byval_arg;
799 else if (return_type->type == MONO_TYPE_VALUETYPE && return_type->data.klass->enumtype)
800 return_type = return_type->data.klass->enum_basetype;
802 switch (return_type->type) {
804 g_assert_not_reached ();
806 case MONO_TYPE_STRING:
807 case MONO_TYPE_CLASS:
808 case MONO_TYPE_OBJECT:
809 case MONO_TYPE_ARRAY:
810 case MONO_TYPE_SZARRAY:
814 case MONO_TYPE_BOOLEAN:
815 mono_mb_emit_byte (mb, CEE_UNBOX);
816 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
817 mono_mb_emit_byte (mb, CEE_LDIND_U1);
820 mono_mb_emit_byte (mb, CEE_UNBOX);
821 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
822 mono_mb_emit_byte (mb, CEE_LDIND_I1);
826 mono_mb_emit_byte (mb, CEE_UNBOX);
827 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
828 mono_mb_emit_byte (mb, CEE_LDIND_U2);
831 mono_mb_emit_byte (mb, CEE_UNBOX);
832 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
833 mono_mb_emit_byte (mb, CEE_LDIND_I2);
835 #if SIZEOF_VOID_P == 4
839 mono_mb_emit_byte (mb, CEE_UNBOX);
840 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
841 mono_mb_emit_byte (mb, CEE_LDIND_I4);
843 #if SIZEOF_VOID_P == 4
847 mono_mb_emit_byte (mb, CEE_UNBOX);
848 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
849 mono_mb_emit_byte (mb, CEE_LDIND_U4);
853 mono_mb_emit_byte (mb, CEE_UNBOX);
854 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
855 mono_mb_emit_byte (mb, CEE_LDIND_I8);
858 mono_mb_emit_byte (mb, CEE_UNBOX);
859 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
860 mono_mb_emit_byte (mb, CEE_LDIND_R4);
863 mono_mb_emit_byte (mb, CEE_UNBOX);
864 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
865 mono_mb_emit_byte (mb, CEE_LDIND_R8);
867 case MONO_TYPE_VALUETYPE: {
869 mono_mb_emit_byte (mb, CEE_UNBOX);
870 class = mono_mb_add_data (mb, mono_class_from_mono_type (return_type));
871 mono_mb_emit_i4 (mb, class);
872 mono_mb_emit_byte (mb, CEE_LDOBJ);
873 mono_mb_emit_i4 (mb, class);
877 g_warning ("type 0x%x not handled", return_type->type);
878 g_assert_not_reached ();
881 mono_mb_emit_byte (mb, CEE_RET);
885 mono_marshal_get_delegate_end_invoke (MonoMethod *method)
887 MonoMethodSignature *sig;
888 static MonoMethodSignature *csig = NULL;
889 MonoMethodBuilder *mb;
894 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
895 !strcmp (method->name, "EndInvoke"));
897 sig = method->signature;
899 cache = method->klass->image->delegate_end_invoke_cache;
900 if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
903 g_assert (sig->hasthis);
906 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
907 csig = g_malloc0 (sigsize);
909 /* MonoObject *end_invoke (MonoDelegate *delegate, gpointer params[]) */
910 csig->param_count = 2;
911 csig->ret = &mono_defaults.object_class->byval_arg;
912 csig->params [0] = &mono_defaults.object_class->byval_arg;
913 csig->params [1] = &mono_defaults.int_class->byval_arg;
916 mb = mono_mb_new (method->klass, method->name);
917 mb->method->wrapper_type = MONO_WRAPPER_DELEGATE_END_INVOKE;
918 mb->method->save_lmf = 1;
920 params_var = mono_mb_emit_save_args (mb, sig, FALSE);
922 mono_mb_emit_ldarg (mb, 0);
923 mono_mb_emit_ldloc (mb, params_var);
924 mono_mb_emit_native_call (mb, csig, mono_delegate_end_invoke);
926 if (sig->ret->type == MONO_TYPE_VOID)
927 mono_mb_emit_byte (mb, CEE_POP);
929 mono_mb_emit_restore_result (mb, sig->ret);
931 res = mono_mb_create_method (mb, sig, 0);
933 g_hash_table_insert (cache, sig, res);
938 mono_remoting_wrapper (MonoMethod *method, gpointer *params)
940 MonoMethodMessage *msg;
941 MonoTransparentProxy *this;
942 MonoObject *res, *exc;
945 this = *((MonoTransparentProxy **)params [0]);
948 g_assert (((MonoObject *)this)->vtable->klass == mono_defaults.transparent_proxy_class);
950 /* skip the this pointer */
953 msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
955 res = mono_remoting_invoke ((MonoObject *)this->rp, msg, &exc, &out_args);
958 mono_raise_exception ((MonoException *)exc);
960 mono_method_return_message_restore (method, params, out_args);
966 mono_marshal_get_remoting_invoke (MonoMethod *method)
968 MonoMethodSignature *sig;
969 static MonoMethodSignature *csig = NULL;
970 MonoMethodBuilder *mb;
977 if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE)
980 sig = method->signature;
982 /* we cant remote methods without this pointer */
986 cache = method->klass->image->remoting_invoke_cache;
987 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
991 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
992 csig = g_malloc0 (sigsize);
994 /* MonoObject *remoting_wrapper (MonoMethod *method, gpointer params[]) */
995 csig->param_count = 2;
996 csig->ret = &mono_defaults.object_class->byval_arg;
997 csig->params [0] = &mono_defaults.int_class->byval_arg;
998 csig->params [1] = &mono_defaults.int_class->byval_arg;
1001 mb = mono_mb_new (method->klass, method->name);
1002 mb->method->wrapper_type = MONO_WRAPPER_REMOTING_INVOKE;
1004 params_var = mono_mb_emit_save_args (mb, sig, TRUE);
1006 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1007 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1008 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
1009 mono_mb_emit_ldloc (mb, params_var);
1010 mono_mb_emit_native_call (mb, csig, mono_remoting_wrapper);
1012 if (sig->ret->type == MONO_TYPE_VOID)
1013 mono_mb_emit_byte (mb, CEE_POP);
1015 mono_mb_emit_restore_result (mb, sig->ret);
1017 res = mono_mb_create_method (mb, sig, 0);
1019 g_hash_table_insert (cache, method, res);
1024 * the returned method invokes all methods in a multicast delegate
1027 mono_marshal_get_delegate_invoke (MonoMethod *method)
1029 MonoMethodSignature *sig, *static_sig;
1031 MonoMethodBuilder *mb;
1036 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1037 !strcmp (method->name, "Invoke"));
1039 sig = method->signature;
1041 cache = method->klass->image->delegate_invoke_cache;
1042 if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1045 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1046 static_sig = g_memdup (sig, sigsize);
1047 static_sig->hasthis = 0;
1049 mb = mono_mb_new (method->klass, method->name);
1050 mb->method->wrapper_type = MONO_WRAPPER_DELEGATE_INVOKE;
1052 /* allocate local 0 (object) prev */
1053 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1054 /* allocate local 1 (object) target */
1055 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1056 /* allocate local 2 (pointer) mptr */
1057 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1059 /* allocate local 3 to store the return value */
1060 if (sig->ret->type != MONO_TYPE_VOID)
1061 mono_mb_add_local (mb, sig->ret);
1063 g_assert (sig->hasthis);
1065 /* prev = addr of delegate */
1066 mono_mb_emit_ldarg (mb, 0);
1067 mono_mb_emit_stloc (mb, 0);
1071 /* target = delegate->target */
1072 mono_mb_emit_ldloc (mb, 0);
1073 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1074 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
1075 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoDelegate, target));
1076 mono_mb_emit_byte (mb, CEE_ADD);
1077 mono_mb_emit_byte (mb, CEE_LDIND_I);
1078 mono_mb_emit_stloc (mb, 1);
1080 /* mptr = delegate->method_ptr */
1081 mono_mb_emit_ldloc (mb, 0);
1082 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1083 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
1084 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1085 mono_mb_emit_byte (mb, CEE_ADD);
1086 mono_mb_emit_byte (mb, CEE_LDIND_I);
1087 mono_mb_emit_stloc (mb, 2);
1089 /* target == null ? */
1090 mono_mb_emit_ldloc (mb, 1);
1091 mono_mb_emit_byte (mb, CEE_BRTRUE);
1093 mono_mb_emit_i4 (mb, 0);
1095 /* emit static method call */
1097 for (i = 0; i < sig->param_count; i++)
1098 mono_mb_emit_ldarg (mb, i + 1);
1100 mono_mb_emit_ldloc (mb, 2);
1101 mono_mb_emit_byte (mb, CEE_CALLI);
1102 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, static_sig));
1104 if (sig->ret->type != MONO_TYPE_VOID)
1105 mono_mb_emit_stloc (mb, 3);
1107 mono_mb_emit_byte (mb, CEE_BR);
1109 mono_mb_emit_i4 (mb, 0);
1111 /* target != null, emit non static method call */
1113 mono_mb_patch_addr (mb, pos [1], mb->pos - (pos [1] + 4));
1114 mono_mb_emit_ldloc (mb, 1);
1116 for (i = 0; i < sig->param_count; i++)
1117 mono_mb_emit_ldarg (mb, i + 1);
1119 mono_mb_emit_ldloc (mb, 2);
1120 mono_mb_emit_byte (mb, CEE_CALLI);
1121 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
1123 if (sig->ret->type != MONO_TYPE_VOID)
1124 mono_mb_emit_stloc (mb, 3);
1126 mono_mb_patch_addr (mb, pos [2], mb->pos - (pos [2] + 4));
1128 /* prev = delegate->prev */
1129 mono_mb_emit_ldloc (mb, 0);
1130 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1131 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
1132 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoMulticastDelegate, prev));
1133 mono_mb_emit_byte (mb, CEE_ADD);
1134 mono_mb_emit_byte (mb, CEE_LDIND_I);
1135 mono_mb_emit_stloc (mb, 0);
1137 /* if prev != null goto loop */
1138 mono_mb_emit_ldloc (mb, 0);
1139 mono_mb_emit_byte (mb, CEE_BRTRUE);
1140 mono_mb_emit_i4 (mb, pos [0] - (mb->pos + 4));
1142 if (sig->ret->type != MONO_TYPE_VOID)
1143 mono_mb_emit_ldloc (mb, 3);
1145 mono_mb_emit_byte (mb, CEE_RET);
1147 res = mono_mb_create_method (mb, sig, 0);
1150 g_hash_table_insert (cache, sig, res);
1156 * generates IL code for the runtime invoke function
1157 * MonoObject *runtime_invoke (MonoObject *this, void **params, MonoObject **exc)
1159 * we also catch exceptions if exc != null
1162 mono_marshal_get_runtime_invoke (MonoMethod *method)
1164 MonoMethodSignature *sig, *csig;
1165 MonoExceptionClause *clause;
1166 MonoMethodHeader *header;
1167 MonoMethodBuilder *mb;
1170 static MonoString *string_dummy = NULL;
1171 int i, pos, sigsize;
1175 cache = method->klass->image->runtime_invoke_cache;
1176 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1179 /* to make it work with our special string constructors */
1181 string_dummy = mono_string_new_wrapper ("dummy");
1183 sig = method->signature;
1185 sigsize = sizeof (MonoMethodSignature) + 3 * sizeof (MonoType *);
1186 csig = g_malloc0 (sigsize);
1188 csig->param_count = 3;
1189 csig->ret = &mono_defaults.object_class->byval_arg;
1190 csig->params [0] = &mono_defaults.object_class->byval_arg;
1191 csig->params [1] = &mono_defaults.int_class->byval_arg;
1192 csig->params [2] = &mono_defaults.int_class->byval_arg;
1194 mb = mono_mb_new (method->klass, method->name);
1195 mb->method->wrapper_type = MONO_WRAPPER_RUNTIME_INVOKE;
1197 /* allocate local 0 (object) tmp */
1198 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1199 /* allocate local 1 (object) exc */
1200 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1202 /* cond set *exc to null */
1203 mono_mb_emit_byte (mb, CEE_LDARG_2);
1204 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
1205 mono_mb_emit_byte (mb, 3);
1206 mono_mb_emit_byte (mb, CEE_LDARG_2);
1207 mono_mb_emit_byte (mb, CEE_LDNULL);
1208 mono_mb_emit_byte (mb, CEE_STIND_I);
1211 if (method->string_ctor) {
1212 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1213 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1214 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, string_dummy));
1216 mono_mb_emit_ldarg (mb, 0);
1220 for (i = 0; i < sig->param_count; i++) {
1221 MonoType *t = sig->params [i];
1224 mono_mb_emit_ldarg (mb, 1);
1226 mono_mb_emit_icon (mb, sizeof (gpointer) * i);
1227 mono_mb_emit_byte (mb, CEE_ADD);
1229 mono_mb_emit_byte (mb, CEE_LDIND_I);
1234 type = sig->params [i]->type;
1238 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1240 case MONO_TYPE_BOOLEAN:
1242 mono_mb_emit_byte (mb, CEE_LDIND_U1);
1245 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1248 case MONO_TYPE_CHAR:
1249 mono_mb_emit_byte (mb, CEE_LDIND_U2);
1251 #if SIZEOF_VOID_P == 4
1255 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1257 #if SIZEOF_VOID_P == 4
1261 mono_mb_emit_byte (mb, CEE_LDIND_U4);
1264 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1267 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1269 #if SIZEOF_VOID_P == 8
1275 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1277 case MONO_TYPE_STRING:
1278 case MONO_TYPE_CLASS:
1279 case MONO_TYPE_ARRAY:
1281 case MONO_TYPE_SZARRAY:
1282 case MONO_TYPE_OBJECT:
1285 case MONO_TYPE_VALUETYPE:
1286 if (t->data.klass->enumtype) {
1287 type = t->data.klass->enum_basetype->type;
1290 g_assert_not_reached ();
1293 g_assert_not_reached ();
1297 if (method->string_ctor) {
1298 MonoMethodSignature *strsig;
1300 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1301 strsig = g_memdup (sig, sigsize);
1302 strsig->ret = &mono_defaults.string_class->byval_arg;
1304 mono_mb_emit_managed_call (mb, method, strsig);
1306 mono_mb_emit_managed_call (mb, method, NULL);
1308 switch (sig->ret->type) {
1309 case MONO_TYPE_VOID:
1310 if (!method->string_ctor)
1311 mono_mb_emit_byte (mb, CEE_LDNULL);
1325 case MONO_TYPE_VALUETYPE:
1326 /* box value types */
1327 mono_mb_emit_byte (mb, CEE_BOX);
1328 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (sig->ret)));
1330 case MONO_TYPE_STRING:
1331 case MONO_TYPE_CLASS:
1332 case MONO_TYPE_ARRAY:
1333 case MONO_TYPE_SZARRAY:
1334 case MONO_TYPE_OBJECT:
1339 g_assert_not_reached ();
1342 mono_mb_emit_stloc (mb, 0);
1344 mono_mb_emit_byte (mb, CEE_LEAVE);
1346 mono_mb_emit_i4 (mb, 0);
1348 /* fixme: use a filter clause and only catch exceptions
1349 * when exc != null. With RETHROW we get wrong stack
1351 clause = g_new0 (MonoExceptionClause, 1);
1352 clause->flags = MONO_EXCEPTION_CLAUSE_NONE;
1353 clause->try_offset = 0;
1354 clause->try_len = mb->pos;
1355 clause->handler_offset = mb->pos;
1359 /* store exception */
1360 mono_mb_emit_stloc (mb, 1);
1362 mono_mb_emit_byte (mb, CEE_LDARG_2);
1363 mono_mb_emit_byte (mb, CEE_BRTRUE_S);
1364 mono_mb_emit_byte (mb, 2);
1365 mono_mb_emit_byte (mb, CEE_PREFIX1);
1366 mono_mb_emit_byte (mb, CEE_RETHROW);
1368 mono_mb_emit_byte (mb, CEE_LDARG_2);
1369 mono_mb_emit_ldloc (mb, 1);
1370 mono_mb_emit_byte (mb, CEE_STIND_I);
1372 mono_mb_emit_byte (mb, CEE_LEAVE);
1373 mono_mb_emit_i4 (mb, 0);
1375 clause->handler_len = mb->pos - clause->handler_offset;
1378 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1379 mono_mb_emit_ldloc (mb, 0);
1380 mono_mb_emit_byte (mb, CEE_RET);
1382 res = mono_mb_create_method (mb, csig, 0);
1385 header = ((MonoMethodNormal *)res)->header;
1386 header->num_clauses = 1;
1387 header->clauses = clause;
1389 g_hash_table_insert (cache, method, res);
1395 * generates IL code to call managed methods from unmanaged code
1398 mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this)
1400 MonoMethodSignature *sig, *csig;
1401 MonoMethodBuilder *mb;
1406 g_assert (method != NULL);
1408 cache = method->klass->image->managed_wrapper_cache;
1409 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1412 sig = method->signature;
1414 mb = mono_mb_new (method->klass, method->name);
1415 mb->method->wrapper_type = MONO_WRAPPER_NATIVE_TO_MANAGED;
1417 /* we copy the signature, so that we can modify it */
1418 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1419 csig = g_memdup (sig, sigsize);
1422 /* fixme: howto handle this ? */
1426 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1427 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1428 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, this));
1433 g_assert_not_reached ();
1437 for (i = 0; i < sig->param_count; i++) {
1438 MonoType *t = sig->params [i];
1454 mono_mb_emit_ldarg (mb, i);
1456 case MONO_TYPE_STRING:
1457 csig->params [i] = &mono_defaults.int_class->byval_arg;
1458 mono_mb_emit_ldarg (mb, i);
1459 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1460 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1461 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
1463 case MONO_TYPE_CLASS:
1464 case MONO_TYPE_ARRAY:
1465 case MONO_TYPE_SZARRAY:
1466 case MONO_TYPE_OBJECT:
1467 /* fixme: conversions ? */
1468 mono_mb_emit_ldarg (mb, i);
1471 g_warning ("type 0x%02x unknown", t->type);
1472 g_assert_not_reached ();
1476 mono_mb_emit_managed_call (mb, method, NULL);
1478 /* fixme: add return type conversions */
1480 mono_mb_emit_byte (mb, CEE_RET);
1482 res = mono_mb_create_method (mb, csig, 0);
1485 g_hash_table_insert (cache, method, res);
1491 * generates IL code for the pinvoke wrapper (the generated method
1492 * call the unamnage code in method->addr)
1495 mono_marshal_get_native_wrapper (MonoMethod *method)
1497 MonoMethodSignature *sig, *csig;
1498 MonoMethodBuilder *mb;
1502 gboolean pinvoke = FALSE;
1503 int i, argnum, *tmp_locals;
1506 g_assert (method != NULL);
1508 cache = method->klass->image->native_wrapper_cache;
1509 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1512 sig = method->signature;
1514 if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
1515 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
1518 mb = mono_mb_new (method->klass, method->name);
1519 mb->method->wrapper_type = MONO_WRAPPER_MANAGED_TO_NATIVE;
1521 mb->method->save_lmf = 1;
1523 if (pinvoke && !method->addr)
1524 mono_lookup_pinvoke_call (method);
1526 if (!method->addr) {
1527 mono_mb_emit_exception (mb);
1528 res = mono_mb_create_method (mb, sig, 0);
1530 g_hash_table_insert (cache, method, res);
1534 /* we copy the signature, so that we can modify it */
1535 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1536 csig = g_memdup (sig, sigsize);
1538 if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
1540 if (method->string_ctor)
1541 csig->ret = &mono_defaults.string_class->byval_arg;
1544 mono_mb_emit_byte (mb, CEE_LDARG_0);
1546 for (i = 0; i < sig->param_count; i++)
1547 mono_mb_emit_ldarg (mb, i + sig->hasthis);
1549 g_assert (method->addr);
1550 mono_mb_emit_native_call (mb, csig, method->addr);
1552 mono_mb_emit_byte (mb, CEE_RET);
1554 res = mono_mb_create_method (mb, csig, 0);
1556 g_hash_table_insert (cache, method, res);
1562 /* we allocate local for use with emit_struct_conv() */
1563 /* allocate local 0 (pointer) src_ptr */
1564 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1565 /* allocate local 1 (pointer) dst_ptr */
1566 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1567 /* allocate local 2 (pointer) as tmp/scratch storage */
1568 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1570 if (sig->ret->type != MONO_TYPE_VOID) {
1571 /* allocate local 3 to store the return value */
1572 mono_mb_add_local (mb, sig->ret);
1575 /* we first do all conversions */
1576 tmp_locals = alloca (sizeof (int) * sig->param_count);
1577 for (i = 0; i < sig->param_count; i ++) {
1578 MonoType *t = sig->params [i];
1580 argnum = i + sig->hasthis;
1582 /* allocate one tmp/scratch storage for each parameter */
1583 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1586 case MONO_TYPE_VALUETYPE:
1587 klass = sig->params [i]->data.klass;
1588 if (klass->enumtype)
1591 /* store the address of the source into local variable 0 */
1592 mono_mb_emit_byte (mb, CEE_LDARGA);
1593 mono_mb_emit_i2 (mb, argnum);
1594 mono_mb_emit_byte (mb, CEE_STLOC_0);
1596 /* allocate space for the native struct and
1597 * store the address into local variable 1 (dest) */
1598 mono_mb_emit_icon (mb, mono_class_native_size (klass));
1599 mono_mb_emit_byte (mb, CEE_LOCALLOC);
1600 mono_mb_emit_stloc (mb, tmp_locals [i]);
1601 mono_mb_emit_ldloc (mb, tmp_locals [i]);
1602 mono_mb_emit_byte (mb, CEE_STLOC_1);
1604 /* emit valuetype convnversion code code */
1605 emit_struct_conv (mb, sig->params [i]->data.klass, FALSE);
1608 case MONO_TYPE_STRING:
1609 /* fixme: load the address instead */
1610 mono_mb_emit_ldarg (mb, argnum);
1611 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1612 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1613 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
1614 mono_mb_emit_stloc (mb, tmp_locals [i]);
1616 case MONO_TYPE_CLASS:
1617 case MONO_TYPE_OBJECT:
1618 if (t->data.klass->delegate) {
1619 mono_mb_emit_ldarg (mb, argnum);
1620 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1621 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1622 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_DEL_FTN);
1623 mono_mb_emit_stloc (mb, tmp_locals [i]);
1625 mono_mb_emit_ldarg (mb, argnum);
1626 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1627 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
1628 /* fixme: convert to what ? */
1629 mono_mb_emit_stloc (mb, tmp_locals [i]);
1635 /* push all arguments */
1638 mono_mb_emit_byte (mb, CEE_LDARG_0);
1640 for (i = 0; i < sig->param_count; i++) {
1641 MonoType *t = sig->params [i];
1643 argnum = i + sig->hasthis;
1646 mono_mb_emit_ldarg (mb, argnum);
1651 case MONO_TYPE_BOOLEAN:
1652 mono_mb_emit_ldarg (mb, argnum);
1667 mono_mb_emit_ldarg (mb, argnum);
1669 case MONO_TYPE_VALUETYPE:
1670 klass = sig->params [i]->data.klass;
1671 if (klass->enumtype) {
1672 mono_mb_emit_ldarg (mb, argnum);
1675 mono_mb_emit_ldloc (mb, tmp_locals [i]);
1676 //mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1677 //mono_mb_emit_byte (mb, CEE_MONO_LDOBJ);
1678 //mono_mb_emit_i4 (mb, mono_klass_native_size (klass));
1681 case MONO_TYPE_STRING:
1682 /* fixme: load the address instead */
1683 mono_mb_emit_ldloc (mb, tmp_locals [i]);
1685 case MONO_TYPE_CLASS:
1686 case MONO_TYPE_OBJECT:
1687 mono_mb_emit_ldloc (mb, tmp_locals [i]);
1689 case MONO_TYPE_CHAR:
1690 case MONO_TYPE_ARRAY:
1691 case MONO_TYPE_SZARRAY:
1692 case MONO_TYPE_TYPEDBYREF:
1693 case MONO_TYPE_FNPTR:
1695 g_warning ("type 0x%02x unknown", t->type);
1696 g_assert_not_reached ();
1700 /* call the native method */
1701 mono_mb_emit_native_call (mb, csig, method->addr);
1703 type = sig->ret->type;
1706 case MONO_TYPE_VOID:
1720 /* no conversions necessary */
1722 case MONO_TYPE_BOOLEAN:
1723 /* maybe we need to make sure that it fits within 8 bits */
1725 case MONO_TYPE_VALUETYPE:
1726 if (sig->ret->data.klass->enumtype) {
1727 type = sig->ret->data.klass->enum_basetype->type;
1730 g_warning ("generic valutype %s not handled", sig->ret->data.klass->name);
1731 g_assert_not_reached ();
1734 case MONO_TYPE_STRING:
1735 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1736 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1737 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
1739 case MONO_TYPE_ARRAY:
1740 case MONO_TYPE_SZARRAY:
1741 case MONO_TYPE_CLASS:
1742 case MONO_TYPE_OBJECT:
1743 /* fixme: we need conversions here */
1745 case MONO_TYPE_CHAR:
1746 case MONO_TYPE_TYPEDBYREF:
1747 case MONO_TYPE_FNPTR:
1749 g_warning ("return type 0x%02x unknown", sig->ret->type);
1750 g_assert_not_reached ();
1753 mono_mb_emit_byte (mb, CEE_RET);
1755 res = mono_mb_create_method (mb, sig, 0);
1758 g_hash_table_insert (cache, method, res);
1764 * generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld)
1767 mono_marshal_get_struct_to_ptr (MonoClass *klass)
1769 MonoMethodBuilder *mb;
1770 static MonoMethod *stoptr = NULL;
1773 g_assert (klass != NULL);
1775 if (klass->str_to_ptr)
1776 return klass->str_to_ptr;
1779 stoptr = mono_find_method_by_name (mono_defaults.marshal_class, "StructureToPtr", 3);
1782 mb = mono_mb_new (stoptr->klass, stoptr->name);
1784 /* allocate local 0 (pointer) src_ptr */
1785 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1786 /* allocate local 1 (pointer) dst_ptr */
1787 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1788 /* allocate local 2 (pointer) as tmp/scratch storage */
1789 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1791 /* initialize src_ptr to point to the start of object data */
1792 mono_mb_emit_byte (mb, CEE_LDARG_0);
1793 mono_mb_emit_icon (mb, sizeof (MonoObject));
1794 mono_mb_emit_byte (mb, CEE_ADD);
1795 mono_mb_emit_byte (mb, CEE_STLOC_0);
1797 /* initialize dst_ptr */
1798 mono_mb_emit_byte (mb, CEE_LDARG_1);
1799 mono_mb_emit_byte (mb, CEE_STLOC_1);
1801 emit_struct_conv (mb, klass, FALSE);
1803 mono_mb_emit_byte (mb, CEE_RET);
1805 res = mono_mb_create_method (mb, stoptr->signature, 0);
1808 klass->str_to_ptr = res;
1813 * generates IL code for PtrToStructure (IntPtr src, object structure)
1816 mono_marshal_get_ptr_to_struct (MonoClass *klass)
1818 MonoMethodBuilder *mb;
1819 static MonoMethod *ptostr = NULL;
1822 g_assert (klass != NULL);
1824 if (klass->ptr_to_str)
1825 return klass->ptr_to_str;
1828 ptostr = mono_find_method_by_name (mono_defaults.marshal_class, "PtrToStructure", 2);
1831 mb = mono_mb_new (ptostr->klass, ptostr->name);
1833 /* allocate local 0 (pointer) src_ptr */
1834 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1835 /* allocate local 1 (pointer) dst_ptr */
1836 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1837 /* allocate local 2 (pointer) as tmp/scratch storage */
1838 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1840 /* initialize src_ptr to point to the start of object data */
1841 mono_mb_emit_byte (mb, CEE_LDARG_0);
1842 mono_mb_emit_byte (mb, CEE_STLOC_0);
1844 /* initialize dst_ptr */
1845 mono_mb_emit_byte (mb, CEE_LDARG_1);
1846 mono_mb_emit_icon (mb, sizeof (MonoObject));
1847 mono_mb_emit_byte (mb, CEE_ADD);
1848 mono_mb_emit_byte (mb, CEE_STLOC_1);
1850 emit_struct_conv (mb, klass, TRUE);
1852 mono_mb_emit_byte (mb, CEE_RET);
1854 res = mono_mb_create_method (mb, ptostr->signature, 0);
1857 klass->ptr_to_str = res;
1861 /* FIXME: on win32 we should probably use GlobalAlloc(). */
1863 mono_marshal_alloc (gpointer size) {
1864 return g_try_malloc ((gulong)size);
1868 mono_marshal_free (gpointer ptr) {
1873 mono_marshal_realloc (gpointer ptr, gpointer size) {
1874 return g_try_realloc (ptr, (gulong)size);
1878 mono_marshal_string_array (MonoArray *array)
1886 len = mono_array_length (array);
1888 result = g_malloc (sizeof (char*) * len);
1889 for (i = 0; i < len; ++i) {
1890 MonoString *s = (MonoString*)mono_array_get (array, gpointer, i);
1891 result [i] = s ? mono_string_to_utf8 (s): NULL;
1897 ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArray *src, gint32 start_index,
1898 gpointer dest, gint32 length)
1903 MONO_CHECK_ARG_NULL (src);
1904 MONO_CHECK_ARG_NULL (dest);
1906 g_assert (src->obj.vtable->klass->rank == 1);
1907 g_assert (start_index >= 0 && start_index < mono_array_length (src));
1908 g_assert (start_index + length <= mono_array_length (src));
1910 element_size = mono_array_element_size (src->obj.vtable->klass);
1912 source_addr = mono_array_addr_with_size (src, element_size, start_index);
1914 memcpy (dest, source_addr, length * element_size);
1918 ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer src, gint32 start_index,
1919 MonoArray *dest, gint32 length)
1924 MONO_CHECK_ARG_NULL (src);
1925 MONO_CHECK_ARG_NULL (dest);
1927 g_assert (dest->obj.vtable->klass->rank == 1);
1928 g_assert (start_index >= 0 && start_index < mono_array_length (dest));
1929 g_assert (start_index + length <= mono_array_length (dest));
1931 element_size = mono_array_element_size (dest->obj.vtable->klass);
1933 dest_addr = mono_array_addr_with_size (dest, element_size, start_index);
1935 memcpy (dest_addr, src, length * element_size);
1939 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr, gint32 offset)
1942 return *(gpointer*)(p + offset);
1946 ves_icall_System_Runtime_InteropServices_Marshal_ReadByte (gpointer ptr, gint32 offset)
1949 return *(unsigned char*)(p + offset);
1953 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt16 (gpointer ptr, gint32 offset)
1956 return *(gint16*)(p + offset);
1960 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt32 (gpointer ptr, gint32 offset)
1963 return *(gint32*)(p + offset);
1967 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt64 (gpointer ptr, gint32 offset)
1970 return *(gint64*)(p + offset);
1974 ves_icall_System_Runtime_InteropServices_Marshal_WriteByte (gpointer ptr, gint32 offset, unsigned char val)
1977 *(unsigned char*)(p + offset) = val;
1981 ves_icall_System_Runtime_InteropServices_Marshal_WriteIntPtr (gpointer ptr, gint32 offset, gpointer val)
1984 *(gpointer*)(p + offset) = val;
1988 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt16 (gpointer ptr, gint32 offset, gint16 val)
1991 *(gint16*)(p + offset) = val;
1995 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt32 (gpointer ptr, gint32 offset, gint32 val)
1998 *(gint32*)(p + offset) = val;
2002 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt64 (gpointer ptr, gint32 offset, gint64 val)
2005 *(gint64*)(p + offset) = val;
2009 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAuto (gpointer ptr)
2011 MonoDomain *domain = mono_domain_get ();
2013 return mono_string_new (domain, (char *)ptr);
2017 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
2019 return (GetLastError ());
2023 ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype)
2027 MONO_CHECK_ARG_NULL (rtype);
2029 klass = mono_class_from_mono_type (rtype->type);
2031 return mono_class_native_size (klass);
2035 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old)
2040 MONO_CHECK_ARG_NULL (obj);
2041 MONO_CHECK_ARG_NULL (dst);
2043 method = mono_marshal_get_struct_to_ptr (obj->vtable->klass);
2047 pa [2] = &delete_old;
2049 mono_runtime_invoke (method, NULL, pa, NULL);
2053 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, MonoObject *dst)
2058 MONO_CHECK_ARG_NULL (src);
2059 MONO_CHECK_ARG_NULL (dst);
2061 method = mono_marshal_get_ptr_to_struct (dst->vtable->klass);
2066 mono_runtime_invoke (method, NULL, pa, NULL);