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"
19 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
23 #include "mono/cil/opcode.def"
28 struct _MonoMethodBuilder {
32 guint32 code_size, pos;
37 mono_delegate_to_ftnptr (MonoDelegate *delegate)
39 MonoMethod *method, *invoke, *wrapper;
40 MonoMethodSignature *sig;
46 if (delegate->delegate_trampoline)
47 return delegate->delegate_trampoline;
49 klass = ((MonoObject *)delegate)->vtable->klass;
50 g_assert (klass->delegate);
52 method = delegate->method_info->method;
53 sig = method->signature;
55 invoke = mono_get_delegate_invoke (klass);
56 wrapper = mono_marshal_get_managed_wrapper (invoke, (MonoObject *)delegate);
58 delegate->delegate_trampoline = mono_compile_method (wrapper);
60 return delegate->delegate_trampoline;
64 mono_array_to_savearray (MonoArray *array)
69 g_assert_not_reached ();
74 mono_array_to_lparray (MonoArray *array)
79 g_assert_not_reached ();
84 mono_string_to_ansibstr (MonoString *string_obj)
86 g_error ("implement me");
91 mono_string_to_bstr (MonoString *string_obj)
93 g_error ("implement me");
98 mono_string_to_byvalstr (gpointer dst, MonoString *src, int size)
103 g_assert (dst != NULL);
107 memset (dst, 0, size);
111 s = mono_string_to_utf8 (src);
112 len = MIN (size, strlen (s));
113 memcpy (dst, s, len);
116 *((char *)dst + size - 1) = 0;
120 mono_string_to_byvalwstr (gpointer dst, MonoString *src, int size)
124 g_assert (dst != NULL);
128 memset (dst, 0, size);
132 len = MIN (size, (mono_string_length (src) * 2));
133 memcpy (dst, mono_string_chars (src), len);
135 *((char *)dst + size - 1) = 0;
136 *((char *)dst + size - 2) = 0;
141 mono_find_method_by_name (MonoClass *klass, const char *name, int param_count)
143 MonoMethod *res = NULL;
146 for (i = 0; i < klass->method.count; ++i) {
147 if ((klass->methods [i]->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
148 klass->methods [i]->name[0] == name [0] &&
149 !strcmp (name, klass->methods [i]->name) &&
150 klass->methods [i]->signature->param_count == param_count) {
151 res = klass->methods [i];
159 mono_mb_free (MonoMethodBuilder *mb)
161 g_list_free (mb->locals_list);
166 mono_mb_new (MonoClass *klass, const char *name)
168 MonoMethodBuilder *mb;
171 g_assert (klass != NULL);
172 g_assert (name != NULL);
174 mb = g_new0 (MonoMethodBuilder, 1);
176 mb->method = m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
179 m->name = g_strdup (name);
181 m->inline_count = -1;
185 mb->code = g_malloc (mb->code_size);
191 mono_mb_add_local (MonoMethodBuilder *mb, MonoType *type)
193 int res = mb->locals;
195 g_assert (mb != NULL);
196 g_assert (type != NULL);
198 mb->locals_list = g_list_append (mb->locals_list, type);
205 mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack)
207 MonoMethodHeader *header;
211 g_assert (mb != NULL);
213 ((MonoMethodNormal *)mb->method)->header = header = (MonoMethodHeader *)
214 g_malloc0 (sizeof (MonoMethodHeader) + mb->locals * sizeof (MonoType *));
219 header->max_stack = max_stack;
221 for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
222 header->locals [i] = (MonoType *)l->data;
225 mb->method->signature = signature;
226 header->code = mb->code;
227 header->code_size = mb->pos;
228 header->num_locals = mb->locals;
231 printf ("MB METHOD %s.%s:%s\n", mb->method->klass->name_space, mb->method->klass->name,
234 for (i = 0; i < mb->pos; i++)
235 printf (" IL%05x %02x\n", i, mb->code [i]);
243 mono_mb_add_data (MonoMethodBuilder *mb, gpointer data)
245 MonoMethodWrapper *mw;
247 g_assert (mb != NULL);
249 mw = (MonoMethodWrapper *)mb->method;
251 mw->data = g_list_append (mw->data, data);
253 return g_list_length (mw->data);
257 mono_mb_patch_addr (MonoMethodBuilder *mb, int pos, int value)
259 *((gint32 *)(&mb->code [pos])) = value;
263 mono_mb_emit_byte (MonoMethodBuilder *mb, guint8 op)
265 if (mb->pos >= mb->code_size) {
267 mb->code = g_realloc (mb->code, mb->code_size);
270 mb->code [mb->pos++] = op;
274 mono_mb_emit_i4 (MonoMethodBuilder *mb, gint32 data)
276 if ((mb->pos + 4) >= mb->code_size) {
278 mb->code = g_realloc (mb->code, mb->code_size);
281 *((gint32 *)(&mb->code [mb->pos])) = data;
286 mono_mb_emit_i2 (MonoMethodBuilder *mb, gint16 data)
288 if ((mb->pos + 2) >= mb->code_size) {
290 mb->code = g_realloc (mb->code, mb->code_size);
293 *((gint16 *)(&mb->code [mb->pos])) = data;
298 mono_mb_emit_ldarg (MonoMethodBuilder *mb, guint argnum)
301 mono_mb_emit_byte (mb, CEE_LDARG_0 + argnum);
302 } else if (argnum < 256) {
303 mono_mb_emit_byte (mb, CEE_LDARG_S);
304 mono_mb_emit_byte (mb, argnum);
306 mono_mb_emit_byte (mb, CEE_PREFIX1);
307 mono_mb_emit_byte (mb, CEE_LDARG);
308 mono_mb_emit_i4 (mb, argnum);
313 mono_mb_emit_ldarg_addr (MonoMethodBuilder *mb, guint argnum)
316 mono_mb_emit_byte (mb, CEE_LDARGA_S);
317 mono_mb_emit_byte (mb, argnum);
319 mono_mb_emit_byte (mb, CEE_PREFIX1);
320 mono_mb_emit_byte (mb, CEE_LDARGA);
321 mono_mb_emit_i4 (mb, argnum);
326 mono_mb_emit_ldloc (MonoMethodBuilder *mb, guint num)
329 mono_mb_emit_byte (mb, CEE_LDLOC_0 + num);
330 } else if (num < 256) {
331 mono_mb_emit_byte (mb, CEE_LDLOC_S);
332 mono_mb_emit_byte (mb, num);
334 mono_mb_emit_byte (mb, CEE_PREFIX1);
335 mono_mb_emit_byte (mb, CEE_LDLOC);
336 mono_mb_emit_i4 (mb, num);
341 mono_mb_emit_stloc (MonoMethodBuilder *mb, guint num)
344 mono_mb_emit_byte (mb, CEE_STLOC_0 + num);
345 } else if (num < 256) {
346 mono_mb_emit_byte (mb, CEE_STLOC_S);
347 mono_mb_emit_byte (mb, num);
349 mono_mb_emit_byte (mb, CEE_PREFIX1);
350 mono_mb_emit_byte (mb, CEE_STLOC);
351 mono_mb_emit_i4 (mb, num);
356 mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value)
358 if (value >= -1 && value < 8) {
359 mono_mb_emit_byte (mb, CEE_LDC_I4_0 + value);
360 } else if (value >= -128 && value <= 127) {
361 mono_mb_emit_byte (mb, CEE_LDC_I4_S);
362 mono_mb_emit_byte (mb, value);
364 mono_mb_emit_byte (mb, CEE_LDC_I4);
365 mono_mb_emit_i4 (mb, value);
370 mono_mb_emit_managed_call (MonoMethodBuilder *mb, MonoMethod *method, MonoMethodSignature *opt_sig)
373 opt_sig = method->signature;
374 mono_mb_emit_byte (mb, CEE_PREFIX1);
375 mono_mb_emit_byte (mb, CEE_LDFTN);
376 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
377 mono_mb_emit_byte (mb, CEE_CALLI);
378 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, opt_sig));
382 mono_mb_emit_native_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, gpointer func)
384 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
385 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
386 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, func));
387 mono_mb_emit_byte (mb, CEE_CALLI);
388 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
392 mono_mb_emit_exception (MonoMethodBuilder *mb)
394 mono_mb_emit_byte (mb, CEE_LDNULL);
395 mono_mb_emit_byte (mb, CEE_THROW);
400 mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint8 local, gint8 incr)
402 mono_mb_emit_ldloc (mb, local);
403 mono_mb_emit_icon (mb, incr);
404 mono_mb_emit_byte (mb, CEE_ADD);
405 mono_mb_emit_stloc (mb, local);
409 emit_ptr_to_str_conv (MonoMethodBuilder *mb, MonoMarshalConv conv, int usize, int msize)
411 /* fixme: dont know what do do here - docs say
412 this does not work for value types */
414 g_warning ("not implemented");
415 g_assert_not_reached ();
419 emit_str_to_ptr_conv (MonoMethodBuilder *mb, MonoMarshalConv conv, int usize, int msize)
422 case MONO_MARSHAL_CONV_BOOL_I4:
423 mono_mb_emit_byte (mb, CEE_LDLOC_1);
424 mono_mb_emit_byte (mb, CEE_LDLOC_0);
425 mono_mb_emit_byte (mb, CEE_LDIND_U1);
426 mono_mb_emit_byte (mb, CEE_STIND_I4);
428 case MONO_MARSHAL_CONV_STR_LPWSTR:
429 case MONO_MARSHAL_CONV_STR_LPSTR:
430 case MONO_MARSHAL_CONV_STR_LPTSTR:
431 case MONO_MARSHAL_CONV_STR_BSTR:
432 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
433 case MONO_MARSHAL_CONV_STR_TBSTR:
434 case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
435 case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
436 /* free space if ARG_2 == true */
437 mono_mb_emit_byte (mb, CEE_LDARG_2);
438 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
439 mono_mb_emit_byte (mb, 4);
440 mono_mb_emit_byte (mb, CEE_LDLOC_1);
441 mono_mb_emit_byte (mb, CEE_LDIND_I);
442 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
443 mono_mb_emit_byte (mb, CEE_MONO_FREE);
445 mono_mb_emit_byte (mb, CEE_LDLOC_1);
446 mono_mb_emit_byte (mb, CEE_LDLOC_0);
447 mono_mb_emit_byte (mb, CEE_LDIND_I);
448 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
449 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
450 mono_mb_emit_byte (mb, conv);
451 mono_mb_emit_byte (mb, CEE_STIND_I);
453 case MONO_MARSHAL_CONV_STR_BYVALSTR:
454 case MONO_MARSHAL_CONV_STR_BYVALWSTR: {
458 mono_mb_emit_byte (mb, CEE_LDLOC_1); /* dst */
459 mono_mb_emit_byte (mb, CEE_LDLOC_0);
460 mono_mb_emit_byte (mb, CEE_LDIND_I); /* src String */
461 mono_mb_emit_icon (mb, usize);
462 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
463 mono_mb_emit_byte (mb, CEE_MONO_PROC3);
464 mono_mb_emit_byte (mb, conv);
467 case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
471 mono_mb_emit_byte (mb, CEE_LDLOC_0);
472 mono_mb_emit_byte (mb, CEE_LDIND_I);
473 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
474 mono_mb_emit_byte (mb, 15);
476 mono_mb_emit_byte (mb, CEE_LDLOC_1);
477 mono_mb_emit_byte (mb, CEE_LDLOC_0);
478 mono_mb_emit_byte (mb, CEE_LDIND_I);
479 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
480 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
481 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
482 mono_mb_emit_byte (mb, CEE_ADD);
483 mono_mb_emit_icon (mb, usize);
484 mono_mb_emit_byte (mb, CEE_PREFIX1);
485 mono_mb_emit_byte (mb, CEE_CPBLK);
488 case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
490 g_error ("marshalling conversion %d not implemented", conv);
495 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
497 MonoMarshalType *info;
500 info = mono_marshal_load_type_info (klass);
502 for (i = 0; i < info->num_fields; i++) {
503 MonoMarshalNative ntype;
504 MonoMarshalConv conv;
505 MonoType *ftype = info->fields [i].field->type;
508 gboolean last_field = i < (info->num_fields -1) ? 0 : 1;
510 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
513 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, klass->unicode, &conv);
516 msize = klass->instance_size - info->fields [i].field->offset;
517 usize = info->native_size - info->fields [i].offset;
519 msize = klass->fields [i + 1].offset - info->fields [i].field->offset;
520 usize = info->fields [i + 1].offset - info->fields [i].offset;
522 g_assert (msize > 0 && usize > 0);
525 case MONO_MARSHAL_CONV_NONE:
527 if (ftype->byref || ftype->type == MONO_TYPE_I ||
528 ftype->type == MONO_TYPE_U) {
529 mono_mb_emit_byte (mb, CEE_LDLOC_1);
530 mono_mb_emit_byte (mb, CEE_LDLOC_0);
531 mono_mb_emit_byte (mb, CEE_LDIND_I);
532 mono_mb_emit_byte (mb, CEE_STIND_I);
536 switch (ftype->type) {
539 mono_mb_emit_byte (mb, CEE_LDLOC_1);
540 mono_mb_emit_byte (mb, CEE_LDLOC_0);
541 mono_mb_emit_byte (mb, CEE_LDIND_I4);
542 mono_mb_emit_byte (mb, CEE_STIND_I4);
546 case MONO_TYPE_BOOLEAN:
547 mono_mb_emit_byte (mb, CEE_LDLOC_1);
548 mono_mb_emit_byte (mb, CEE_LDLOC_0);
549 mono_mb_emit_byte (mb, CEE_LDIND_I1);
550 mono_mb_emit_byte (mb, CEE_STIND_I1);
554 mono_mb_emit_byte (mb, CEE_LDLOC_1);
555 mono_mb_emit_byte (mb, CEE_LDLOC_0);
556 mono_mb_emit_byte (mb, CEE_LDIND_I2);
557 mono_mb_emit_byte (mb, CEE_STIND_I2);
561 mono_mb_emit_byte (mb, CEE_LDLOC_1);
562 mono_mb_emit_byte (mb, CEE_LDLOC_0);
563 mono_mb_emit_byte (mb, CEE_LDIND_I8);
564 mono_mb_emit_byte (mb, CEE_STIND_I8);
567 mono_mb_emit_byte (mb, CEE_LDLOC_1);
568 mono_mb_emit_byte (mb, CEE_LDLOC_0);
569 mono_mb_emit_byte (mb, CEE_LDIND_R4);
570 mono_mb_emit_byte (mb, CEE_STIND_R4);
573 mono_mb_emit_byte (mb, CEE_LDLOC_1);
574 mono_mb_emit_byte (mb, CEE_LDLOC_0);
575 mono_mb_emit_byte (mb, CEE_LDIND_R8);
576 mono_mb_emit_byte (mb, CEE_STIND_R8);
578 case MONO_TYPE_VALUETYPE:
579 emit_struct_conv (mb, ftype->data.klass, to_object);
582 g_error ("marshalling type %02x not implemented", ftype->type);
588 emit_ptr_to_str_conv (mb, conv, usize, msize);
590 emit_str_to_ptr_conv (mb, conv, usize, msize);
594 mono_mb_emit_add_to_local (mb, 0, msize);
595 mono_mb_emit_add_to_local (mb, 1, usize);
601 delegate_test (MonoDelegate *delegate, gpointer *params)
603 g_assert_not_reached ();
608 mono_marshal_get_delegate_begin_invoke (MonoMethod *method)
610 MonoMethodSignature *sig;
611 static MonoMethodSignature *csig = NULL;
612 MonoMethodBuilder *mb;
614 MonoClass *ret_class;
618 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
619 !strcmp (method->name, "BeginInvoke"));
621 sig = method->signature;
624 ret_type = &mono_defaults.int_class->byval_arg;
625 else if (sig->ret->type == MONO_TYPE_VALUETYPE && sig->ret->data.klass->enumtype)
626 ret_type = sig->ret->data.klass->enum_basetype;
630 ret_class = mono_class_from_mono_type (ret_type);
634 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
635 csig = g_malloc0 (sigsize);
637 /* MonoObject *begin_invoke (MonoDelegate *delegate, gpointer params[]) */
638 csig->param_count = 2;
639 csig->ret = &mono_defaults.object_class->byval_arg;
640 csig->params [0] = &mono_defaults.object_class->byval_arg;
641 csig->params [1] = &mono_defaults.int_class->byval_arg;
644 mb = mono_mb_new (method->klass, method->name);
646 /* allocate local 0 (pointer) *params[] */
647 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
648 /* allocate local 1 (pointer) tmo */
649 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
651 /* alloate space on stack to store an array of pointers to the arguments */
652 mono_mb_emit_icon (mb, sizeof (gpointer) * (sig->param_count + 1));
653 mono_mb_emit_byte (mb, CEE_PREFIX1);
654 mono_mb_emit_byte (mb, CEE_LOCALLOC);
655 mono_mb_emit_byte (mb, CEE_STLOC_0);
658 mono_mb_emit_byte (mb, CEE_LDLOC_0);
659 mono_mb_emit_byte (mb, CEE_STLOC_1);
661 for (i = 0; i < sig->param_count; i++) {
663 mono_mb_emit_byte (mb, CEE_LDLOC_1);
664 mono_mb_emit_ldarg_addr (mb, i);
665 mono_mb_emit_byte (mb, CEE_STIND_I);
666 /* tmp = tmp + sizeof (gpointer) */
667 if (i < (sig->param_count - 1))
668 mono_mb_emit_add_to_local (mb, 1, sizeof (gpointer));
671 mono_mb_emit_ldarg (mb, 0);
672 mono_mb_emit_byte (mb, CEE_LDLOC_0);
673 mono_mb_emit_native_call (mb, csig, delegate_test);
675 /* unbox the result if necessary */
677 switch (ret_type->type) {
678 case MONO_TYPE_STRING:
679 case MONO_TYPE_CLASS:
680 case MONO_TYPE_OBJECT:
681 case MONO_TYPE_ARRAY:
682 case MONO_TYPE_SZARRAY:
688 case MONO_TYPE_BOOLEAN:
700 case MONO_TYPE_VALUETYPE:
701 mono_mb_emit_byte (mb, CEE_UNBOX);
702 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, ret_class));
705 g_warning ("type 0x%x not handled", ret_type->type);
706 g_assert_not_reached ();
709 mono_mb_emit_byte (mb, CEE_RET);
711 res = mono_mb_create_method (mb, sig, 0);
717 * the returned method invokes all methods in a multicast delegate
720 mono_marshal_get_delegate_invoke (MonoMethod *method)
722 MonoMethodSignature *sig, *static_sig;
724 MonoMethodBuilder *mb;
729 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
730 !strcmp (method->name, "Invoke"));
732 cache = method->klass->image->delegate_invoke_cache;
733 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
736 sig = method->signature;
738 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
739 static_sig = g_memdup (sig, sigsize);
740 static_sig->hasthis = 0;
742 mb = mono_mb_new (method->klass, method->name);
744 /* allocate local 0 (object) prev */
745 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
746 /* allocate local 1 (object) target */
747 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
748 /* allocate local 2 (pointer) mptr */
749 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
751 /* allocate local 3 to store the return value */
752 if (sig->ret->type != MONO_TYPE_VOID)
753 mono_mb_add_local (mb, sig->ret);
755 g_assert (sig->hasthis);
757 /* prev = addr of delegate */
758 mono_mb_emit_ldarg (mb, 0);
759 mono_mb_emit_stloc (mb, 0);
763 /* target = delegate->target */
764 mono_mb_emit_ldloc (mb, 0);
765 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
766 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
767 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoDelegate, target));
768 mono_mb_emit_byte (mb, CEE_ADD);
769 mono_mb_emit_byte (mb, CEE_LDIND_I);
770 mono_mb_emit_stloc (mb, 1);
772 /* mptr = delegate->method_ptr */
773 mono_mb_emit_ldloc (mb, 0);
774 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
775 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
776 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
777 mono_mb_emit_byte (mb, CEE_ADD);
778 mono_mb_emit_byte (mb, CEE_LDIND_I);
779 mono_mb_emit_stloc (mb, 2);
781 /* target == null ? */
782 mono_mb_emit_ldloc (mb, 1);
783 mono_mb_emit_byte (mb, CEE_BRTRUE);
785 mono_mb_emit_i4 (mb, 0);
787 /* emit static method call */
789 for (i = 0; i < sig->param_count; i++)
790 mono_mb_emit_ldarg (mb, i + 1);
792 mono_mb_emit_ldloc (mb, 2);
793 mono_mb_emit_byte (mb, CEE_CALLI);
794 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, static_sig));
796 if (sig->ret->type != MONO_TYPE_VOID)
797 mono_mb_emit_stloc (mb, 3);
799 mono_mb_emit_byte (mb, CEE_BR);
801 mono_mb_emit_i4 (mb, 0);
803 /* target != null, emit non static method call */
805 mono_mb_patch_addr (mb, pos [1], mb->pos - (pos [1] + 4));
806 mono_mb_emit_ldloc (mb, 1);
808 for (i = 0; i < sig->param_count; i++)
809 mono_mb_emit_ldarg (mb, i + 1);
811 mono_mb_emit_ldloc (mb, 2);
812 mono_mb_emit_byte (mb, CEE_CALLI);
813 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
815 if (sig->ret->type != MONO_TYPE_VOID)
816 mono_mb_emit_stloc (mb, 3);
818 mono_mb_patch_addr (mb, pos [2], mb->pos - (pos [2] + 4));
820 /* prev = delegate->prev */
821 mono_mb_emit_ldloc (mb, 0);
822 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
823 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
824 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoMulticastDelegate, prev));
825 mono_mb_emit_byte (mb, CEE_ADD);
826 mono_mb_emit_byte (mb, CEE_LDIND_I);
827 mono_mb_emit_stloc (mb, 0);
829 /* if prev != null goto loop */
830 mono_mb_emit_ldloc (mb, 0);
831 mono_mb_emit_byte (mb, CEE_BRTRUE);
832 mono_mb_emit_i4 (mb, pos [0] - (mb->pos + 4));
834 if (sig->ret->type != MONO_TYPE_VOID)
835 mono_mb_emit_ldloc (mb, 3);
837 mono_mb_emit_byte (mb, CEE_RET);
839 res = mono_mb_create_method (mb, sig, 0);
842 g_hash_table_insert (cache, method, res);
848 * generates IL code for the runtime invoke function
849 * MonoObject *runtime_invoke (MonoObject *this, void **params, MonoObject **exc)
851 * we also catch exceptions if exc != null
854 mono_marshal_get_runtime_invoke (MonoMethod *method)
856 MonoMethodSignature *sig, *csig;
857 MonoExceptionClause *clause;
858 MonoMethodHeader *header;
859 MonoMethodBuilder *mb;
862 static MonoString *string_dummy = NULL;
867 cache = method->klass->image->runtime_invoke_cache;
868 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
871 /* to make it work with our special string constructors */
873 string_dummy = mono_string_new_wrapper ("dummy");
875 sig = method->signature;
877 sigsize = sizeof (MonoMethodSignature) + 3 * sizeof (MonoType *);
878 csig = g_malloc0 (sigsize);
880 csig->param_count = 3;
881 csig->ret = &mono_defaults.object_class->byval_arg;
882 csig->params [0] = &mono_defaults.object_class->byval_arg;
883 csig->params [1] = &mono_defaults.int_class->byval_arg;
884 csig->params [2] = &mono_defaults.int_class->byval_arg;
886 mb = mono_mb_new (method->klass, method->name);
888 /* allocate local 0 (object) tmp */
889 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
890 /* allocate local 1 (object) exc */
891 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
894 /* cond set *exc to null */
895 mono_mb_emit_byte (mb, CEE_LDARG_2);
896 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
897 mono_mb_emit_byte (mb, 3);
898 mono_mb_emit_byte (mb, CEE_LDARG_2);
899 mono_mb_emit_byte (mb, CEE_LDNULL);
900 mono_mb_emit_byte (mb, CEE_STIND_I);
903 if (method->string_ctor) {
904 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
905 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
906 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, string_dummy));
908 mono_mb_emit_ldarg (mb, 0);
912 for (i = 0; i < sig->param_count; i++) {
913 MonoType *t = sig->params [i];
916 mono_mb_emit_ldarg (mb, 1);
918 mono_mb_emit_icon (mb, sizeof (gpointer) * i);
919 mono_mb_emit_byte (mb, CEE_ADD);
921 mono_mb_emit_byte (mb, CEE_LDIND_I);
926 type = sig->params [i]->type;
930 mono_mb_emit_byte (mb, CEE_LDIND_I1);
932 case MONO_TYPE_BOOLEAN:
934 mono_mb_emit_byte (mb, CEE_LDIND_U1);
937 mono_mb_emit_byte (mb, CEE_LDIND_I2);
941 mono_mb_emit_byte (mb, CEE_LDIND_U2);
943 #if SIZEOF_VOID_P == 4
947 mono_mb_emit_byte (mb, CEE_LDIND_I4);
949 #if SIZEOF_VOID_P == 4
953 mono_mb_emit_byte (mb, CEE_LDIND_U4);
956 mono_mb_emit_byte (mb, CEE_LDIND_R4);
959 mono_mb_emit_byte (mb, CEE_LDIND_R8);
961 #if SIZEOF_VOID_P == 8
967 mono_mb_emit_byte (mb, CEE_LDIND_I8);
969 case MONO_TYPE_STRING:
970 case MONO_TYPE_CLASS:
971 case MONO_TYPE_ARRAY:
973 case MONO_TYPE_SZARRAY:
974 case MONO_TYPE_OBJECT:
977 case MONO_TYPE_VALUETYPE:
978 if (t->data.klass->enumtype) {
979 type = t->data.klass->enum_basetype->type;
982 g_assert_not_reached ();
985 g_assert_not_reached ();
989 if (method->string_ctor) {
990 MonoMethodSignature *strsig;
992 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
993 strsig = g_memdup (sig, sigsize);
994 strsig->ret = &mono_defaults.string_class->byval_arg;
996 mono_mb_emit_managed_call (mb, method, strsig);
998 mono_mb_emit_managed_call (mb, method, NULL);
1000 switch (sig->ret->type) {
1001 case MONO_TYPE_VOID:
1002 if (!method->string_ctor)
1003 mono_mb_emit_byte (mb, CEE_LDNULL);
1017 case MONO_TYPE_VALUETYPE:
1018 /* box value types */
1019 mono_mb_emit_byte (mb, CEE_BOX);
1020 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (sig->ret)));
1022 case MONO_TYPE_STRING:
1023 case MONO_TYPE_CLASS:
1024 case MONO_TYPE_ARRAY:
1025 case MONO_TYPE_SZARRAY:
1026 case MONO_TYPE_OBJECT:
1031 g_assert_not_reached ();
1034 mono_mb_emit_stloc (mb, 0);
1036 mono_mb_emit_byte (mb, CEE_LEAVE);
1038 mono_mb_emit_i4 (mb, 0);
1040 /* fixme: use a filter clause and only catch exceptions
1041 * when exc != null. With RETHROW we get wrong stack
1043 clause = g_new0 (MonoExceptionClause, 1);
1044 clause->flags = MONO_EXCEPTION_CLAUSE_NONE;
1045 clause->try_offset = 0;
1046 clause->try_len = mb->pos;
1047 clause->handler_offset = mb->pos;
1051 /* store exception */
1052 mono_mb_emit_stloc (mb, 1);
1054 mono_mb_emit_byte (mb, CEE_LDARG_2);
1055 mono_mb_emit_byte (mb, CEE_BRTRUE_S);
1056 mono_mb_emit_byte (mb, 2);
1057 mono_mb_emit_byte (mb, CEE_PREFIX1);
1058 mono_mb_emit_byte (mb, CEE_RETHROW);
1060 mono_mb_emit_byte (mb, CEE_LDARG_2);
1061 mono_mb_emit_ldloc (mb, 1);
1062 mono_mb_emit_byte (mb, CEE_STIND_I);
1064 mono_mb_emit_byte (mb, CEE_LEAVE);
1065 mono_mb_emit_i4 (mb, 0);
1067 clause->handler_len = mb->pos - clause->handler_offset;
1070 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1071 mono_mb_emit_ldloc (mb, 0);
1072 mono_mb_emit_byte (mb, CEE_RET);
1074 res = mono_mb_create_method (mb, csig, 0);
1077 header = ((MonoMethodNormal *)res)->header;
1078 header->num_clauses = 1;
1079 header->clauses = clause;
1081 g_hash_table_insert (cache, method, res);
1087 * generates IL code to call managed methods from unmanaged code
1090 mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this)
1092 MonoMethodSignature *sig, *csig;
1093 MonoMethodBuilder *mb;
1098 g_assert (method != NULL);
1100 cache = method->klass->image->managed_wrapper_cache;
1101 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1104 sig = method->signature;
1106 mb = mono_mb_new (method->klass, method->name);
1108 /* we copy the signature, so that we can modify it */
1109 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1110 csig = g_memdup (sig, sigsize);
1112 /* fixme: howto handle this ? */
1116 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1117 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1118 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, this));
1123 g_assert_not_reached ();
1127 for (i = 0; i < sig->param_count; i++) {
1128 MonoType *t = sig->params [i];
1144 mono_mb_emit_ldarg (mb, i);
1146 case MONO_TYPE_STRING:
1147 csig->params [i] = &mono_defaults.int_class->byval_arg;
1148 mono_mb_emit_ldarg (mb, i);
1149 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1150 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1151 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
1153 case MONO_TYPE_CLASS:
1154 case MONO_TYPE_ARRAY:
1155 case MONO_TYPE_SZARRAY:
1156 case MONO_TYPE_OBJECT:
1157 /* fixme: conversions ? */
1158 mono_mb_emit_ldarg (mb, i);
1161 g_warning ("type 0x%02x unknown", t->type);
1162 g_assert_not_reached ();
1166 mono_mb_emit_managed_call (mb, method, NULL);
1168 /* fixme: add return type conversions */
1170 mono_mb_emit_byte (mb, CEE_RET);
1172 res = mono_mb_create_method (mb, csig, 0);
1175 g_hash_table_insert (cache, method, res);
1181 * generates IL code for the pinvoke wrapper (the generated method
1182 * call the unamnage code in method->addr)
1185 mono_marshal_get_native_wrapper (MonoMethod *method)
1187 MonoMethodSignature *sig, *csig;
1188 MonoMethodBuilder *mb;
1192 gboolean pinvoke = FALSE;
1193 int i, argnum, *tmp_locals, sigsize;
1195 g_assert (method != NULL);
1197 cache = method->klass->image->native_wrapper_cache;
1198 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1201 sig = method->signature;
1203 if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
1204 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
1207 mb = mono_mb_new (method->klass, method->name);
1209 mb->method->save_lmf = 1;
1211 if (pinvoke && !method->addr)
1212 mono_lookup_pinvoke_call (method);
1214 if (!method->addr) {
1215 mono_mb_emit_exception (mb);
1216 res = mono_mb_create_method (mb, sig, 0);
1218 g_hash_table_insert (cache, method, res);
1222 /* we copy the signature, so that we can modify it */
1223 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1224 csig = g_memdup (sig, sigsize);
1226 if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
1228 if (method->string_ctor)
1229 csig->ret = &mono_defaults.string_class->byval_arg;
1232 mono_mb_emit_byte (mb, CEE_LDARG_0);
1234 for (i = 0; i < sig->param_count; i++)
1235 mono_mb_emit_ldarg (mb, i + sig->hasthis);
1237 g_assert (method->addr);
1238 mono_mb_emit_native_call (mb, csig, method->addr);
1240 mono_mb_emit_byte (mb, CEE_RET);
1242 res = mono_mb_create_method (mb, csig, 0);
1244 g_hash_table_insert (cache, method, res);
1250 /* we allocate local for use with emit_struct_conv() */
1251 /* allocate local 0 (pointer) src_ptr */
1252 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1253 /* allocate local 1 (pointer) dst_ptr */
1254 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1255 /* allocate local 2 (pointer) as tmp/scratch storage */
1256 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1258 if (sig->ret->type != MONO_TYPE_VOID) {
1259 /* allocate local 3 to store the return value */
1260 mono_mb_add_local (mb, sig->ret);
1263 /* we first do all conversions */
1264 tmp_locals = alloca (sizeof (int) * sig->param_count);
1265 for (i = 0; i < sig->param_count; i ++) {
1266 MonoType *t = sig->params [i];
1268 argnum = i + sig->hasthis;
1270 /* allocate one tmp/scratch storage for each parameter */
1271 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1274 case MONO_TYPE_VALUETYPE:
1275 klass = sig->params [i]->data.klass;
1276 if (klass->enumtype)
1279 /* store the address of the source into local variable 0 */
1280 mono_mb_emit_byte (mb, CEE_LDARGA);
1281 mono_mb_emit_i2 (mb, argnum);
1282 mono_mb_emit_byte (mb, CEE_STLOC_0);
1284 /* allocate space for the native struct and
1285 * store the address into local variable 1 (dest) */
1286 mono_mb_emit_icon (mb, mono_class_native_size (klass));
1287 mono_mb_emit_byte (mb, CEE_LOCALLOC);
1288 mono_mb_emit_stloc (mb, tmp_locals [i]);
1289 mono_mb_emit_ldloc (mb, tmp_locals [i]);
1290 mono_mb_emit_byte (mb, CEE_STLOC_1);
1292 /* emit valuetype convnversion code code */
1293 emit_struct_conv (mb, sig->params [i]->data.klass, FALSE);
1296 case MONO_TYPE_STRING:
1297 /* fixme: load the address instead */
1298 mono_mb_emit_ldarg (mb, argnum);
1299 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1300 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1301 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
1302 mono_mb_emit_stloc (mb, tmp_locals [i]);
1304 case MONO_TYPE_CLASS:
1305 case MONO_TYPE_OBJECT:
1306 if (t->data.klass->delegate) {
1307 mono_mb_emit_ldarg (mb, argnum);
1308 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1309 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1310 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_DEL_FTN);
1311 mono_mb_emit_stloc (mb, tmp_locals [i]);
1313 mono_mb_emit_ldarg (mb, argnum);
1314 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1315 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
1316 /* fixme: convert to what ? */
1317 mono_mb_emit_stloc (mb, tmp_locals [i]);
1323 /* push all arguments */
1326 mono_mb_emit_byte (mb, CEE_LDARG_0);
1328 for (i = 0; i < sig->param_count; i++) {
1329 MonoType *t = sig->params [i];
1331 argnum = i + sig->hasthis;
1334 mono_mb_emit_ldarg (mb, argnum);
1339 case MONO_TYPE_BOOLEAN:
1340 mono_mb_emit_ldarg (mb, argnum);
1355 mono_mb_emit_ldarg (mb, argnum);
1357 case MONO_TYPE_VALUETYPE:
1358 klass = sig->params [i]->data.klass;
1359 if (klass->enumtype) {
1360 mono_mb_emit_ldarg (mb, argnum);
1363 mono_mb_emit_ldloc (mb, tmp_locals [i]);
1364 //mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1365 //mono_mb_emit_byte (mb, CEE_MONO_LDOBJ);
1366 //mono_mb_emit_i4 (mb, mono_klass_native_size (klass));
1369 case MONO_TYPE_STRING:
1370 /* fixme: load the address instead */
1371 mono_mb_emit_ldloc (mb, tmp_locals [i]);
1373 case MONO_TYPE_CLASS:
1374 case MONO_TYPE_OBJECT:
1375 mono_mb_emit_ldloc (mb, tmp_locals [i]);
1377 case MONO_TYPE_CHAR:
1378 case MONO_TYPE_ARRAY:
1379 case MONO_TYPE_SZARRAY:
1380 case MONO_TYPE_TYPEDBYREF:
1381 case MONO_TYPE_FNPTR:
1383 g_warning ("type 0x%02x unknown", t->type);
1384 g_assert_not_reached ();
1388 /* call the native method */
1389 mono_mb_emit_native_call (mb, csig, method->addr);
1391 switch (sig->ret->type) {
1392 case MONO_TYPE_VOID:
1406 /* no conversions necessary */
1408 case MONO_TYPE_BOOLEAN:
1409 /* maybe we need to make sure that it fits within 8 bits */
1411 case MONO_TYPE_STRING:
1412 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1413 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1414 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
1416 case MONO_TYPE_ARRAY:
1417 case MONO_TYPE_SZARRAY:
1418 case MONO_TYPE_CLASS:
1419 case MONO_TYPE_OBJECT:
1420 /* fixme: we need conversions here */
1422 case MONO_TYPE_CHAR:
1423 case MONO_TYPE_TYPEDBYREF:
1424 case MONO_TYPE_FNPTR:
1426 g_warning ("return type 0x%02x unknown", sig->ret->type);
1427 g_assert_not_reached ();
1430 mono_mb_emit_byte (mb, CEE_RET);
1432 res = mono_mb_create_method (mb, sig, 0);
1435 g_hash_table_insert (cache, method, res);
1441 * generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld)
1444 mono_marshal_get_struct_to_ptr (MonoClass *klass)
1446 MonoMethodBuilder *mb;
1447 static MonoMethod *stoptr = NULL;
1450 g_assert (klass != NULL);
1452 if (klass->str_to_ptr)
1453 return klass->str_to_ptr;
1456 stoptr = mono_find_method_by_name (mono_defaults.marshal_class, "StructureToPtr", 3);
1459 mb = mono_mb_new (stoptr->klass, stoptr->name);
1461 /* allocate local 0 (pointer) src_ptr */
1462 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1463 /* allocate local 1 (pointer) dst_ptr */
1464 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1465 /* allocate local 2 (pointer) as tmp/scratch storage */
1466 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1468 /* initialize src_ptr to point to the start of object data */
1469 mono_mb_emit_byte (mb, CEE_LDARG_0);
1470 mono_mb_emit_icon (mb, sizeof (MonoObject));
1471 mono_mb_emit_byte (mb, CEE_ADD);
1472 mono_mb_emit_byte (mb, CEE_STLOC_0);
1474 /* initialize dst_ptr */
1475 mono_mb_emit_byte (mb, CEE_LDARG_1);
1476 mono_mb_emit_byte (mb, CEE_STLOC_1);
1478 emit_struct_conv (mb, klass, FALSE);
1480 mono_mb_emit_byte (mb, CEE_RET);
1482 res = mono_mb_create_method (mb, stoptr->signature, 0);
1485 klass->str_to_ptr = res;
1490 * generates IL code for PtrToStructure (IntPtr src, object structure)
1493 mono_marshal_get_ptr_to_struct (MonoClass *klass)
1495 MonoMethodBuilder *mb;
1496 static MonoMethod *ptostr = NULL;
1499 g_assert (klass != NULL);
1501 if (klass->ptr_to_str)
1502 return klass->ptr_to_str;
1505 ptostr = mono_find_method_by_name (mono_defaults.marshal_class, "PtrToStructure", 2);
1508 mb = mono_mb_new (ptostr->klass, ptostr->name);
1510 /* allocate local 0 (pointer) src_ptr */
1511 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1512 /* allocate local 1 (pointer) dst_ptr */
1513 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1514 /* allocate local 2 (pointer) as tmp/scratch storage */
1515 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1517 /* initialize src_ptr to point to the start of object data */
1518 mono_mb_emit_byte (mb, CEE_LDARG_0);
1519 mono_mb_emit_byte (mb, CEE_STLOC_0);
1521 /* initialize dst_ptr */
1522 mono_mb_emit_byte (mb, CEE_LDARG_1);
1523 mono_mb_emit_icon (mb, sizeof (MonoObject));
1524 mono_mb_emit_byte (mb, CEE_ADD);
1525 mono_mb_emit_byte (mb, CEE_STLOC_1);
1527 emit_struct_conv (mb, klass, TRUE);
1529 mono_mb_emit_byte (mb, CEE_RET);
1531 res = mono_mb_create_method (mb, ptostr->signature, 0);
1534 klass->ptr_to_str = res;
1538 /* FIXME: on win32 we should probably use GlobalAlloc(). */
1540 mono_marshal_alloc (gpointer size) {
1541 return g_try_malloc ((gulong)size);
1545 mono_marshal_free (gpointer ptr) {
1550 mono_marshal_realloc (gpointer ptr, gpointer size) {
1551 return g_try_realloc (ptr, (gulong)size);
1555 mono_marshal_string_array (MonoArray *array)
1563 len = mono_array_length (array);
1565 result = g_malloc (sizeof (char*) * len);
1566 for (i = 0; i < len; ++i) {
1567 MonoString *s = (MonoString*)mono_array_get (array, gpointer, i);
1568 result [i] = s ? mono_string_to_utf8 (s): NULL;
1574 ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArray *src, gint32 start_index,
1575 gpointer dest, gint32 length)
1580 MONO_CHECK_ARG_NULL (src);
1581 MONO_CHECK_ARG_NULL (dest);
1583 g_assert (src->obj.vtable->klass->rank == 1);
1584 g_assert (start_index >= 0 && start_index < mono_array_length (src));
1585 g_assert (start_index + length <= mono_array_length (src));
1587 element_size = mono_array_element_size (src->obj.vtable->klass);
1589 source_addr = mono_array_addr_with_size (src, element_size, start_index);
1591 memcpy (dest, source_addr, length * element_size);
1595 ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer src, gint32 start_index,
1596 MonoArray *dest, gint32 length)
1601 MONO_CHECK_ARG_NULL (src);
1602 MONO_CHECK_ARG_NULL (dest);
1604 g_assert (dest->obj.vtable->klass->rank == 1);
1605 g_assert (start_index >= 0 && start_index < mono_array_length (dest));
1606 g_assert (start_index + length <= mono_array_length (dest));
1608 element_size = mono_array_element_size (dest->obj.vtable->klass);
1610 dest_addr = mono_array_addr_with_size (dest, element_size, start_index);
1612 memcpy (dest_addr, src, length * element_size);
1616 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr, gint32 offset)
1619 return *(gpointer*)(p + offset);
1623 ves_icall_System_Runtime_InteropServices_Marshal_ReadByte (gpointer ptr, gint32 offset)
1626 return *(unsigned char*)(p + offset);
1630 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt16 (gpointer ptr, gint32 offset)
1633 return *(gint16*)(p + offset);
1637 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt32 (gpointer ptr, gint32 offset)
1640 return *(gint32*)(p + offset);
1644 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt64 (gpointer ptr, gint32 offset)
1647 return *(gint64*)(p + offset);
1651 ves_icall_System_Runtime_InteropServices_Marshal_WriteByte (gpointer ptr, gint32 offset, unsigned char val)
1654 *(unsigned char*)(p + offset) = val;
1658 ves_icall_System_Runtime_InteropServices_Marshal_WriteIntPtr (gpointer ptr, gint32 offset, gpointer val)
1661 *(gpointer*)(p + offset) = val;
1665 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt16 (gpointer ptr, gint32 offset, gint16 val)
1668 *(gint16*)(p + offset) = val;
1672 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt32 (gpointer ptr, gint32 offset, gint32 val)
1675 *(gint32*)(p + offset) = val;
1679 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt64 (gpointer ptr, gint32 offset, gint64 val)
1682 *(gint64*)(p + offset) = val;
1686 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAuto (gpointer ptr)
1688 MonoDomain *domain = mono_domain_get ();
1690 return mono_string_new (domain, (char *)ptr);
1694 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
1696 return (GetLastError ());
1700 ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype)
1704 MONO_CHECK_ARG_NULL (rtype);
1706 klass = mono_class_from_mono_type (rtype->type);
1708 return mono_class_native_size (klass);
1712 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old)
1717 MONO_CHECK_ARG_NULL (obj);
1718 MONO_CHECK_ARG_NULL (dst);
1720 method = mono_marshal_get_struct_to_ptr (obj->vtable->klass);
1724 pa [2] = &delete_old;
1726 mono_runtime_invoke (method, NULL, pa, NULL);
1730 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, MonoObject *dst)
1735 MONO_CHECK_ARG_NULL (src);
1736 MONO_CHECK_ARG_NULL (dst);
1738 method = mono_marshal_get_ptr_to_struct (dst->vtable->klass);
1743 mono_runtime_invoke (method, NULL, pa, NULL);