2004-07-09 Ben Maurer <bmaurer@ximian.com>
[mono.git] / mono / metadata / marshal.c
1 /*
2  * marshal.c: Routines for marshaling complex types in P/Invoke methods.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
7  * (C) 2002 Ximian, Inc.  http://www.ximian.com
8  *
9  */
10
11 #include "config.h"
12 #include "object.h"
13 #include "loader.h"
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/os/gc_wrapper.h>
24 #include <string.h>
25 #include <errno.h>
26
27 /* #define DEBUG_RUNTIME_CODE */
28
29 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
30         a = i,
31
32 enum {
33 #include "mono/cil/opcode.def"
34         LAST = 0xff
35 };
36 #undef OPDEF
37
38 struct _MonoMethodBuilder {
39         MonoMethod *method;
40         GList *locals_list;
41         int locals;
42         guint32 code_size, pos;
43         unsigned char *code;
44 };
45
46 static void
47 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object);
48
49 static MonoMethod *
50 mono_find_method_by_name (MonoClass *klass, const char *name, int param_count)
51 {
52         MonoMethod *res = NULL;
53         int i;
54
55         for (i = 0; i < klass->method.count; ++i) {
56                 if (klass->methods [i]->name[0] == name [0] && 
57                     !strcmp (name, klass->methods [i]->name) &&
58                     klass->methods [i]->signature->param_count == param_count) {
59                         res = klass->methods [i];
60                         break;
61                 }
62         }
63         return res;
64 }
65
66 #ifdef DEBUG_RUNTIME_CODE
67 static char*
68 indenter (MonoDisHelper *dh, MonoMethod *method, guint32 ip_offset)
69 {
70         return g_strdup (" ");
71 }
72
73 static MonoDisHelper marshal_dh = {
74         "\n",
75         "IL_%04x: ",
76         "IL_%04x",
77         indenter, 
78         NULL,
79         NULL
80 };
81 #endif 
82
83 /* This mutex protects the various marshalling related caches in MonoImage */
84 static CRITICAL_SECTION marshal_mutex;
85
86 /* Maps wrapper methods to the methods they wrap */
87 static MonoGHashTable *wrapper_hash;
88
89 static guint32 last_error_tls_id;
90
91 static void
92 register_icall (gpointer func, const char *name, const char *sigstr, gboolean save)
93 {
94         MonoMethodSignature *sig = mono_create_icall_signature (sigstr);
95
96         mono_register_jit_icall (func, name, sig, save);
97 }
98
99 void
100 mono_marshal_init (void)
101 {
102         static gboolean module_initialized = FALSE;
103
104         if (!module_initialized) {
105                 module_initialized = TRUE;
106                 InitializeCriticalSection (&marshal_mutex);
107                 MONO_GC_REGISTER_ROOT (wrapper_hash);
108                 wrapper_hash = mono_g_hash_table_new (NULL, NULL);
109                 last_error_tls_id = TlsAlloc ();
110
111                 register_icall (mono_string_to_utf16, "mono_string_to_utf16", "ptr obj", FALSE);
112                 register_icall (mono_string_from_utf16, "mono_string_from_utf16", "obj ptr", FALSE);
113                 register_icall (mono_string_new_wrapper, "mono_string_new_wrapper", "obj ptr", FALSE);
114                 register_icall (mono_string_to_utf8, "mono_string_to_utf8", "ptr obj", FALSE);
115                 register_icall (mono_string_to_bstr, "mono_string_to_bstr", "ptr obj", FALSE);
116                 register_icall (mono_string_to_ansibstr, "mono_string_to_ansibstr", "ptr object", FALSE);
117                 register_icall (mono_string_builder_to_utf8, "mono_string_builder_to_utf8", "ptr object", FALSE);
118                 register_icall (mono_string_builder_to_utf16, "mono_string_builder_to_utf16", "ptr object", FALSE);
119                 register_icall (mono_array_to_savearray, "mono_array_to_savearray", "ptr object", FALSE);
120                 register_icall (mono_array_to_lparray, "mono_array_to_lparray", "ptr object", FALSE);
121                 register_icall (mono_delegate_to_ftnptr, "mono_delegate_to_ftnptr", "ptr object", FALSE);
122                 register_icall (mono_ftnptr_to_delegate, "mono_ftnptr_to_delegate", "object ptr ptr", FALSE);
123                 register_icall (mono_marshal_string_array, "mono_marshal_string_array", "ptr object", FALSE);
124                 register_icall (mono_marshal_string_array_to_unicode, "mono_marshal_string_array_to_unicode", "ptr object", FALSE);
125                 register_icall (mono_marshal_asany, "mono_marshal_asany", "ptr object int", FALSE);
126                 register_icall (mono_marshal_free_asany, "mono_marshal_free_asany", "void object ptr int", FALSE);
127                 register_icall (mono_string_utf8_to_builder, "mono_string_utf8_to_builder", "void ptr ptr", FALSE);
128                 register_icall (mono_string_utf16_to_builder, "mono_string_utf16_to_builder", "void ptr ptr", FALSE);
129                 register_icall (mono_marshal_free_array, "mono_marshal_free_array", "void ptr ptr", FALSE);
130                 register_icall (mono_string_to_byvalstr, "mono_string_to_byvalstr", "void ptr ptr ptr", FALSE);
131                 register_icall (mono_string_to_byvalwstr, "mono_string_to_byvalwstr", "void ptr ptr ptr", FALSE);
132                 register_icall (g_free, "g_free", "void ptr", FALSE);
133         }
134 }
135
136 gpointer
137 mono_delegate_to_ftnptr (MonoDelegate *delegate)
138 {
139         MonoMethod *method, *wrapper, *invoke;
140         MonoMarshalSpec **mspecs;
141         MonoClass *klass;
142         int i;
143
144         if (!delegate)
145                 return NULL;
146
147         if (delegate->delegate_trampoline)
148                 return delegate->delegate_trampoline;
149
150         klass = ((MonoObject *)delegate)->vtable->klass;
151         g_assert (klass->delegate);
152
153
154         method = delegate->method_info->method;
155         invoke = mono_find_method_by_name (klass, "Invoke", method->signature->param_count);
156
157         mspecs = g_new (MonoMarshalSpec*, invoke->signature->param_count + 1);
158         mono_method_get_marshal_info (invoke, mspecs);
159
160         wrapper = mono_marshal_get_managed_wrapper (method, delegate->target, mspecs);
161
162         for (i = invoke->signature->param_count; i >= 0; i--)
163                 g_free (mspecs [i]);
164         g_free (mspecs);
165
166         delegate->delegate_trampoline =  mono_compile_method (wrapper);
167
168         return delegate->delegate_trampoline;
169 }
170
171 MonoDelegate*
172 mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn)
173 {
174         MonoDelegate *d;
175         MonoJitInfo *ji;
176
177         d = (MonoDelegate*)mono_object_new (mono_domain_get (), klass);
178
179         ji = mono_jit_info_table_find (mono_domain_get (), ftn);
180         if (ji == NULL)
181                 mono_raise_exception (mono_get_exception_argument ("", "Function pointer was not created by a Delegate."));
182
183         /* FIXME: discard the wrapper and call the original method */
184         mono_delegate_ctor ((MonoObject*)d, NULL, ftn);
185
186         return d;
187 }
188
189 gpointer
190 mono_array_to_savearray (MonoArray *array)
191 {
192         if (!array)
193                 return NULL;
194
195         g_assert_not_reached ();
196         return NULL;
197 }
198
199 gpointer
200 mono_array_to_lparray (MonoArray *array)
201 {
202         if (!array)
203                 return NULL;
204
205         /* fixme: maybe we need to make a copy */
206         return array->vector;
207 }
208
209 void
210 mono_string_utf8_to_builder (MonoStringBuilder *sb, char *text)
211 {
212         GError *error = NULL;
213         guint16 *ut;
214         glong items_written;
215         int l;
216
217         if (!sb || !text)
218                 return;
219
220         l = strlen (text);
221
222         ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
223         
224         if (items_written > mono_stringbuilder_capacity (sb))
225                 items_written = mono_stringbuilder_capacity (sb);
226         
227         if (!error) {
228                 memcpy (mono_string_chars (sb->str), ut, items_written * 2);
229                 sb->length = items_written;
230         } else 
231                 g_error_free (error);
232
233         g_free (ut);
234 }
235
236 void
237 mono_string_utf16_to_builder (MonoStringBuilder *sb, gunichar2 *text)
238 {
239         guint32 len;
240
241         if (!sb || !text)
242                 return;
243
244         g_assert (mono_string_chars (sb->str) == text);
245
246         for (len = 0; text [len] != 0; ++len)
247                 ;
248
249         sb->length = len;
250 }
251
252 gpointer
253 mono_string_builder_to_utf8 (MonoStringBuilder *sb)
254 {
255         GError *error = NULL;
256         glong *res;
257         gchar *tmp;
258
259         if (!sb)
260                 return NULL;
261
262         res = g_malloc0 (mono_stringbuilder_capacity (sb) + 1);
263
264         tmp = g_utf16_to_utf8 (mono_string_chars (sb->str), sb->length, NULL, res, &error);
265         if (error) {
266                 g_error_free (error);
267                 mono_raise_exception (mono_get_exception_execution_engine ("Failed to convert StringBuilder from utf16 to utf8"));
268         }
269         else
270                 memcpy (res, tmp, sb->length + 1);
271
272         return res;
273 }
274
275 gpointer
276 mono_string_builder_to_utf16 (MonoStringBuilder *sb)
277 {
278         if (!sb)
279                 return NULL;
280
281         return mono_string_chars (sb->str);
282 }
283
284 gpointer
285 mono_string_to_ansibstr (MonoString *string_obj)
286 {
287         g_error ("implement me");
288         return NULL;
289 }
290
291 gpointer
292 mono_string_to_bstr (MonoString *string_obj)
293 {
294         g_error ("implement me");
295         return NULL;
296 }
297
298 void
299 mono_string_to_byvalstr (gpointer dst, MonoString *src, int size)
300 {
301         char *s;
302         int len;
303
304         g_assert (dst != NULL);
305         g_assert (size > 0);
306
307         memset (dst, 0, size);
308         
309         if (!src)
310                 return;
311
312         s = mono_string_to_utf8 (src);
313         len = MIN (size, strlen (s));
314         memcpy (dst, s, len);
315         g_free (s);
316
317         *((char *)dst + size - 1) = 0;
318 }
319
320 void
321 mono_string_to_byvalwstr (gpointer dst, MonoString *src, int size)
322 {
323         int len;
324
325         g_assert (dst != NULL);
326         g_assert (size > 1);
327
328         if (!src) {
329                 memset (dst, 0, size);
330                 return;
331         }
332
333         len = MIN (size, (mono_string_length (src) * 2));
334         memcpy (dst, mono_string_chars (src), len);
335
336         *((char *)dst + size - 1) = 0;
337         *((char *)dst + size - 2) = 0;
338 }
339
340 void
341 mono_mb_free (MonoMethodBuilder *mb)
342 {
343         g_list_free (mb->locals_list);
344         g_free (mb);
345 }
346
347 MonoMethodBuilder *
348 mono_mb_new (MonoClass *klass, const char *name, MonoWrapperType type)
349 {
350         MonoMethodBuilder *mb;
351         MonoMethod *m;
352
353         g_assert (klass != NULL);
354         g_assert (name != NULL);
355
356         mb = g_new0 (MonoMethodBuilder, 1);
357
358         mb->method = m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
359
360         m->klass = klass;
361         m->name = g_strdup (name);
362         m->inline_info = 1;
363         m->inline_count = -1;
364         m->wrapper_type = type;
365
366         mb->code_size = 256;
367         mb->code = g_malloc (mb->code_size);
368         
369         return mb;
370 }
371
372 int
373 mono_mb_add_local (MonoMethodBuilder *mb, MonoType *type)
374 {
375         int res = mb->locals;
376
377         g_assert (mb != NULL);
378         g_assert (type != NULL);
379
380         mb->locals_list = g_list_append (mb->locals_list, type);
381         mb->locals++;
382
383         return res;
384 }
385
386 MonoMethod *
387 mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack)
388 {
389         MonoMethodHeader *header;
390         GList *l;
391         int i;
392
393         g_assert (mb != NULL);
394
395         ((MonoMethodNormal *)mb->method)->header = header = (MonoMethodHeader *) 
396                 g_malloc0 (sizeof (MonoMethodHeader) + mb->locals * sizeof (MonoType *));
397
398         if (max_stack < 8)
399                 max_stack = 8;
400
401         header->max_stack = max_stack;
402
403         for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
404                 header->locals [i] = (MonoType *)l->data;
405         }
406
407         mb->method->signature = signature;
408         header->code = mb->code;
409         header->code_size = mb->pos;
410         header->num_locals = mb->locals;
411
412 #ifdef DEBUG_RUNTIME_CODE
413         printf ("RUNTIME CODE FOR %s\n", mono_method_full_name (mb->method, TRUE));
414         printf ("%s\n", mono_disasm_code (&marshal_dh, mb->method, mb->code, mb->code + mb->pos));
415 #endif
416
417         return mb->method;
418 }
419
420 guint32
421 mono_mb_add_data (MonoMethodBuilder *mb, gpointer data)
422 {
423         MonoMethodWrapper *mw;
424
425         g_assert (mb != NULL);
426
427         mw = (MonoMethodWrapper *)mb->method;
428
429         mw->data = g_list_append (mw->data, data);
430
431         return g_list_length (mw->data);
432 }
433
434 void
435 mono_mb_patch_addr (MonoMethodBuilder *mb, int pos, int value)
436 {
437         mb->code [pos] = value & 0xff;
438         mb->code [pos + 1] = (value >> 8) & 0xff;
439         mb->code [pos + 2] = (value >> 16) & 0xff;
440         mb->code [pos + 3] = (value >> 24) & 0xff;
441 }
442
443 void
444 mono_mb_patch_addr_s (MonoMethodBuilder *mb, int pos, gint8 value)
445 {
446         *((gint8 *)(&mb->code [pos])) = value;
447 }
448
449 void
450 mono_mb_emit_byte (MonoMethodBuilder *mb, guint8 op)
451 {
452         if (mb->pos >= mb->code_size) {
453                 mb->code_size += 64;
454                 mb->code = g_realloc (mb->code, mb->code_size);
455         }
456
457         mb->code [mb->pos++] = op;
458 }
459
460 void
461 mono_mb_emit_ldflda (MonoMethodBuilder *mb, gint32 offset)
462 {
463         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
464         mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
465
466         if (offset) {
467                 mono_mb_emit_icon (mb, offset);
468                 mono_mb_emit_byte (mb, CEE_ADD);
469         }
470 }
471
472 static int
473 mono_mb_emit_proxy_check (MonoMethodBuilder *mb, int branch_code)
474 {
475         int pos;
476         mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoObject, vtable));
477         mono_mb_emit_byte (mb, CEE_LDIND_I);
478         mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoVTable, klass));
479         mono_mb_emit_byte (mb, CEE_ADD);
480         mono_mb_emit_byte (mb, CEE_LDIND_I);
481         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
482         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
483         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_defaults.transparent_proxy_class));
484         mono_mb_emit_byte (mb, branch_code);
485         pos = mb->pos;
486         mono_mb_emit_i4 (mb, 0);
487         return pos;
488 }
489
490 void
491 mono_mb_emit_i4 (MonoMethodBuilder *mb, gint32 data)
492 {
493         if ((mb->pos + 4) >= mb->code_size) {
494                 mb->code_size += 64;
495                 mb->code = g_realloc (mb->code, mb->code_size);
496         }
497
498         mono_mb_patch_addr (mb, mb->pos, data);
499         mb->pos += 4;
500 }
501
502 void
503 mono_mb_emit_i2 (MonoMethodBuilder *mb, gint16 data)
504 {
505         if ((mb->pos + 2) >= mb->code_size) {
506                 mb->code_size += 64;
507                 mb->code = g_realloc (mb->code, mb->code_size);
508         }
509
510         mb->code [mb->pos] = data & 0xff;
511         mb->code [mb->pos + 1] = (data >> 8) & 0xff;
512         mb->pos += 2;
513 }
514
515 void
516 mono_mb_emit_ldstr (MonoMethodBuilder *mb, char *str)
517 {
518         mono_mb_emit_byte (mb, CEE_LDSTR);
519         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, str));
520 }
521
522
523 void
524 mono_mb_emit_ldarg (MonoMethodBuilder *mb, guint argnum)
525 {
526         if (argnum < 4) {
527                 mono_mb_emit_byte (mb, CEE_LDARG_0 + argnum);
528         } else if (argnum < 256) {
529                 mono_mb_emit_byte (mb, CEE_LDARG_S);
530                 mono_mb_emit_byte (mb, argnum);
531         } else {
532                 mono_mb_emit_byte (mb, CEE_PREFIX1);
533                 mono_mb_emit_byte (mb, CEE_LDARG);
534                 mono_mb_emit_i2 (mb, argnum);
535         }
536 }
537
538 void
539 mono_mb_emit_ldarg_addr (MonoMethodBuilder *mb, guint argnum)
540 {
541         if (argnum < 256) {
542                 mono_mb_emit_byte (mb, CEE_LDARGA_S);
543                 mono_mb_emit_byte (mb, argnum);
544         } else {
545                 mono_mb_emit_byte (mb, CEE_PREFIX1);
546                 mono_mb_emit_byte (mb, CEE_LDARGA);
547                 mono_mb_emit_i2 (mb, argnum);
548         }
549 }
550
551 void
552 mono_mb_emit_ldloc_addr (MonoMethodBuilder *mb, guint locnum)
553 {
554         if (locnum < 256) {
555                 mono_mb_emit_byte (mb, CEE_LDLOCA_S);
556                 mono_mb_emit_byte (mb, locnum);
557         } else {
558                 mono_mb_emit_byte (mb, CEE_PREFIX1);
559                 mono_mb_emit_byte (mb, CEE_LDLOCA);
560                 mono_mb_emit_i2 (mb, locnum);
561         }
562 }
563
564 void
565 mono_mb_emit_ldloc (MonoMethodBuilder *mb, guint num)
566 {
567         if (num < 4) {
568                 mono_mb_emit_byte (mb, CEE_LDLOC_0 + num);
569         } else if (num < 256) {
570                 mono_mb_emit_byte (mb, CEE_LDLOC_S);
571                 mono_mb_emit_byte (mb, num);
572         } else {
573                 mono_mb_emit_byte (mb, CEE_PREFIX1);
574                 mono_mb_emit_byte (mb, CEE_LDLOC);
575                 mono_mb_emit_i2 (mb, num);
576         }
577 }
578
579 void
580 mono_mb_emit_stloc (MonoMethodBuilder *mb, guint num)
581 {
582         if (num < 4) {
583                 mono_mb_emit_byte (mb, CEE_STLOC_0 + num);
584         } else if (num < 256) {
585                 mono_mb_emit_byte (mb, CEE_STLOC_S);
586                 mono_mb_emit_byte (mb, num);
587         } else {
588                 mono_mb_emit_byte (mb, CEE_PREFIX1);
589                 mono_mb_emit_byte (mb, CEE_STLOC);
590                 mono_mb_emit_i2 (mb, num);
591         }
592 }
593
594 void
595 mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value)
596 {
597         if (value >= -1 && value < 8) {
598                 mono_mb_emit_byte (mb, CEE_LDC_I4_0 + value);
599         } else if (value >= -128 && value <= 127) {
600                 mono_mb_emit_byte (mb, CEE_LDC_I4_S);
601                 mono_mb_emit_byte (mb, value);
602         } else {
603                 mono_mb_emit_byte (mb, CEE_LDC_I4);
604                 mono_mb_emit_i4 (mb, value);
605         }
606 }
607
608 guint32
609 mono_mb_emit_branch (MonoMethodBuilder *mb, guint8 op)
610 {
611         guint32 res;
612         mono_mb_emit_byte (mb, op);
613         res = mb->pos;
614         mono_mb_emit_i4 (mb, 0);
615         return res;
616 }
617
618 static void
619 mono_mb_emit_calli (MonoMethodBuilder *mb, MonoMethodSignature *sig)
620 {
621         mono_mb_emit_byte (mb, CEE_CALLI);
622         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
623 }
624
625 void
626 mono_mb_emit_managed_call (MonoMethodBuilder *mb, MonoMethod *method, MonoMethodSignature *opt_sig)
627 {
628         mono_mb_emit_byte (mb, CEE_PREFIX1);
629         mono_mb_emit_byte (mb, CEE_LDFTN);
630         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
631         mono_mb_emit_calli (mb, opt_sig ? opt_sig : method->signature);
632 }
633
634 void
635 mono_mb_emit_native_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, gpointer func)
636 {
637         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
638         mono_mb_emit_byte (mb, CEE_MONO_SAVE_LMF);
639         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
640         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
641         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, func));
642         mono_mb_emit_calli (mb, sig);
643         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
644         mono_mb_emit_byte (mb, CEE_MONO_RESTORE_LMF);
645 }
646
647 static void
648 mono_mb_emit_icall (MonoMethodBuilder *mb, gpointer func)
649 {
650         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
651         mono_mb_emit_byte (mb, CEE_MONO_ICALL);
652         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, func));
653 }
654
655 void
656 mono_mb_emit_exception (MonoMethodBuilder *mb, const char *exc_name, const char *msg)
657 {
658         /* fixme: we need a better way to throw exception,
659          * supporting several exception types and messages */
660         MonoMethod *ctor = NULL;
661
662         MonoClass *mme = mono_class_from_name (mono_defaults.corlib, "System", exc_name);
663         int i;
664         mono_class_init (mme);
665         for (i = 0; i < mme->method.count; ++i) {
666                 if (strcmp (mme->methods [i]->name, ".ctor") == 0 && mme->methods [i]->signature->param_count == 0) {
667                         ctor = mme->methods [i];
668                         break;
669                 }
670         }
671         g_assert (ctor);
672         mono_mb_emit_byte (mb, CEE_NEWOBJ);
673         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, ctor));
674         if (msg != NULL) {
675                 mono_mb_emit_byte (mb, CEE_DUP);
676                 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoException, message));
677                 mono_mb_emit_ldstr (mb, (char*)msg);
678                 mono_mb_emit_byte (mb, CEE_STIND_I);
679         }
680         mono_mb_emit_byte (mb, CEE_THROW);
681 }
682
683 void
684 mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint16 local, gint32 incr)
685 {
686         mono_mb_emit_ldloc (mb, local); 
687         mono_mb_emit_icon (mb, incr);
688         mono_mb_emit_byte (mb, CEE_ADD);
689         mono_mb_emit_stloc (mb, local); 
690 }
691
692 static void
693 emit_ptr_to_str_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, 
694                       int usize, int msize, MonoMarshalSpec *mspec)
695 {
696         switch (conv) {
697         case MONO_MARSHAL_CONV_BOOL_I4:
698                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
699                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
700                 mono_mb_emit_byte (mb, CEE_LDIND_I4);
701                 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
702                 mono_mb_emit_byte (mb, 3);
703                 mono_mb_emit_byte (mb, CEE_LDC_I4_1);
704                 mono_mb_emit_byte (mb, CEE_BR_S);
705                 mono_mb_emit_byte (mb, 1);
706                 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
707                 mono_mb_emit_byte (mb, CEE_STIND_I1);
708                 break;
709         case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
710                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
711                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
712                 mono_mb_emit_byte (mb, CEE_LDIND_I2);
713                 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
714                 mono_mb_emit_byte (mb, 3);
715                 mono_mb_emit_byte (mb, CEE_LDC_I4_1);
716                 mono_mb_emit_byte (mb, CEE_BR_S);
717                 mono_mb_emit_byte (mb, 1);
718                 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
719                 mono_mb_emit_byte (mb, CEE_STIND_I1);
720                 break;
721         case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
722                 MonoClass *eclass = NULL;
723                 int esize;
724
725                 if (type->type == MONO_TYPE_SZARRAY) {
726                         eclass = type->data.klass;
727                 } else {
728                         g_assert_not_reached ();
729                 }
730
731                 if (eclass->valuetype)
732                         esize = mono_class_instance_size (eclass) - sizeof (MonoObject);
733                 else
734                         esize = sizeof (gpointer);
735
736                 /* create a new array */
737                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
738                 mono_mb_emit_icon (mb, mspec->data.array_data.num_elem);
739                 mono_mb_emit_byte (mb, CEE_NEWARR);     
740                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eclass));
741                 mono_mb_emit_byte (mb, CEE_STIND_I);
742
743                 /* copy the elements */
744                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
745                 mono_mb_emit_byte (mb, CEE_LDIND_I);
746                 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
747                 mono_mb_emit_byte (mb, CEE_ADD);
748                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
749                 mono_mb_emit_icon (mb, mspec->data.array_data.num_elem * esize);
750                 mono_mb_emit_byte (mb, CEE_PREFIX1);
751                 mono_mb_emit_byte (mb, CEE_CPBLK);                      
752
753                 break;
754         }
755         case MONO_MARSHAL_CONV_STR_BYVALSTR: 
756                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
757                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
758                 mono_mb_emit_icall (mb, mono_string_new_wrapper);
759                 mono_mb_emit_byte (mb, CEE_STIND_I);            
760                 break;
761         case MONO_MARSHAL_CONV_STR_LPTSTR:
762         case MONO_MARSHAL_CONV_STR_LPSTR:
763                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
764                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
765                 mono_mb_emit_byte (mb, CEE_LDIND_I);
766                 mono_mb_emit_icall (mb, mono_string_new_wrapper);
767                 mono_mb_emit_byte (mb, CEE_STIND_I);            
768                 break;
769         case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
770                 MonoClass *klass = mono_class_from_mono_type (type);
771                 int src_var, dst_var;
772
773                 src_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
774                 dst_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
775                 
776                 /* *dst = new object */
777                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
778                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
779                 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);        
780                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
781                 mono_mb_emit_byte (mb, CEE_STIND_I);
782         
783                 /* save the old src pointer */
784                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
785                 mono_mb_emit_stloc (mb, src_var);
786                 /* save the old dst pointer */
787                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
788                 mono_mb_emit_stloc (mb, dst_var);
789
790                 /* dst = pointer to newly created object data */
791                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
792                 mono_mb_emit_byte (mb, CEE_LDIND_I);
793                 mono_mb_emit_icon (mb, sizeof (MonoObject));
794                 mono_mb_emit_byte (mb, CEE_ADD);
795                 mono_mb_emit_byte (mb, CEE_STLOC_1); 
796
797                 emit_struct_conv (mb, klass, TRUE);
798                 
799                 /* restore the old src pointer */
800                 mono_mb_emit_ldloc (mb, src_var);
801                 mono_mb_emit_byte (mb, CEE_STLOC_0);
802                 /* restore the old dst pointer */
803                 mono_mb_emit_ldloc (mb, dst_var);
804                 mono_mb_emit_byte (mb, CEE_STLOC_1);
805                 break;
806         }
807         case MONO_MARSHAL_CONV_DEL_FTN: {
808                 /* fixme: we never convert functions back to delegates, dont 
809                 // know if thats the correct behaviour
810                 */
811                 break;
812         }
813         case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
814                 g_error ("Structure field of type %s can't be marshalled as LPArray", mono_class_from_mono_type (type)->name);
815                 break;
816         case MONO_MARSHAL_CONV_STR_LPWSTR:
817         case MONO_MARSHAL_CONV_STR_BSTR:
818         case MONO_MARSHAL_CONV_STR_ANSIBSTR:
819         case MONO_MARSHAL_CONV_STR_TBSTR:
820         case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
821         case MONO_MARSHAL_CONV_STR_BYVALWSTR: 
822         default:
823                 g_warning ("marshaling conversion %d not implemented", conv);
824                 g_assert_not_reached ();
825         }
826 }
827
828 static gpointer
829 conv_to_icall (MonoMarshalConv conv)
830 {
831         switch (conv) {
832         case MONO_MARSHAL_CONV_STR_LPWSTR:
833                 return mono_string_to_utf16;            
834         case MONO_MARSHAL_CONV_LPWSTR_STR:
835                 return mono_string_from_utf16;
836         case MONO_MARSHAL_CONV_LPSTR_STR:
837                 return mono_string_new_wrapper;
838         case MONO_MARSHAL_CONV_STR_LPTSTR:
839         case MONO_MARSHAL_CONV_STR_LPSTR:
840                 return mono_string_to_utf8;
841         case MONO_MARSHAL_CONV_STR_BSTR:
842                 return mono_string_to_bstr;
843         case MONO_MARSHAL_CONV_STR_TBSTR:
844         case MONO_MARSHAL_CONV_STR_ANSIBSTR:
845                 return mono_string_to_ansibstr;
846         case MONO_MARSHAL_CONV_SB_LPSTR:
847         case MONO_MARSHAL_CONV_SB_LPTSTR:
848                 return mono_string_builder_to_utf8;
849         case MONO_MARSHAL_CONV_SB_LPWSTR:
850                 return mono_string_builder_to_utf16;
851         case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
852                 return mono_array_to_savearray;
853         case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
854                 return mono_array_to_lparray;
855         case MONO_MARSHAL_CONV_DEL_FTN:
856                 return mono_delegate_to_ftnptr;
857         case MONO_MARSHAL_CONV_FTN_DEL:
858                 return mono_ftnptr_to_delegate;
859         case MONO_MARSHAL_CONV_LPSTR_SB:
860         case MONO_MARSHAL_CONV_LPTSTR_SB:
861                 return mono_string_utf8_to_builder;
862         case MONO_MARSHAL_CONV_LPWSTR_SB:
863                 return mono_string_utf16_to_builder;
864         case MONO_MARSHAL_FREE_ARRAY:
865                 return mono_marshal_free_array;
866         case MONO_MARSHAL_CONV_STR_BYVALSTR:
867                 return mono_string_to_byvalstr;
868         case MONO_MARSHAL_CONV_STR_BYVALWSTR:
869                 return mono_string_to_byvalwstr;
870         default:
871                 g_assert_not_reached ();
872         }
873
874         return NULL;
875 }
876
877 static void
878 emit_str_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, int usize, int msize,
879                       MonoMarshalSpec *mspec)
880 {
881         int pos;
882
883         switch (conv) {
884         case MONO_MARSHAL_CONV_BOOL_I4:
885                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
886                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
887                 mono_mb_emit_byte (mb, CEE_LDIND_U1);
888                 mono_mb_emit_byte (mb, CEE_STIND_I4);
889                 break;
890         case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
891                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
892                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
893                 mono_mb_emit_byte (mb, CEE_LDIND_U1);
894                 mono_mb_emit_byte (mb, CEE_NEG);
895                 mono_mb_emit_byte (mb, CEE_STIND_I2);
896                 break;
897         case MONO_MARSHAL_CONV_STR_LPWSTR:
898         case MONO_MARSHAL_CONV_STR_LPSTR:
899         case MONO_MARSHAL_CONV_STR_LPTSTR:
900         case MONO_MARSHAL_CONV_STR_BSTR:
901         case MONO_MARSHAL_CONV_STR_ANSIBSTR:
902         case MONO_MARSHAL_CONV_STR_TBSTR: {
903                 int pos;
904
905                 /* free space if free == true */
906                 mono_mb_emit_byte (mb, CEE_LDLOC_2);
907                 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
908                 pos = mb->pos;
909                 mono_mb_emit_byte (mb, 0);
910                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
911                 mono_mb_emit_byte (mb, CEE_LDIND_I);
912                 mono_mb_emit_icall (mb, g_free);
913                 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
914
915                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
916                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
917                 mono_mb_emit_byte (mb, CEE_LDIND_I);
918                 mono_mb_emit_icall (mb, conv_to_icall (conv));
919                 mono_mb_emit_byte (mb, CEE_STIND_I);    
920                 break;
921         }
922         case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
923         case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
924         case MONO_MARSHAL_CONV_DEL_FTN:
925                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
926                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
927                 mono_mb_emit_byte (mb, CEE_LDIND_I);
928                 mono_mb_emit_icall (mb, conv_to_icall (conv));
929                 mono_mb_emit_byte (mb, CEE_STIND_I);    
930                 break;
931         case MONO_MARSHAL_CONV_STR_BYVALSTR: 
932         case MONO_MARSHAL_CONV_STR_BYVALWSTR: {
933                 if (!usize)
934                         break;
935
936                 mono_mb_emit_byte (mb, CEE_LDLOC_1); /* dst */
937                 mono_mb_emit_byte (mb, CEE_LDLOC_0);    
938                 mono_mb_emit_byte (mb, CEE_LDIND_I); /* src String */
939                 mono_mb_emit_icon (mb, usize);
940                 mono_mb_emit_icall (mb, conv_to_icall (conv));
941                 break;
942         }
943         case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
944                 MonoClass *eclass = NULL;
945                 int esize;
946
947                 if (type->type == MONO_TYPE_SZARRAY) {
948                         eclass = type->data.klass;
949                 } else {
950                         g_assert_not_reached ();
951                 }
952
953                 if (eclass->valuetype)
954                         esize = mono_class_native_size (eclass, NULL);
955                 else
956                         esize = sizeof (gpointer);
957
958                 if (!usize) 
959                         break;
960
961                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
962                 mono_mb_emit_byte (mb, CEE_LDIND_I);            
963                 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
964                 pos = mb->pos;
965                 mono_mb_emit_byte (mb, 0);
966
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_I);    
970                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
971                 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
972                 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
973                 mono_mb_emit_byte (mb, CEE_ADD);
974                 mono_mb_emit_icon (mb, mspec->data.array_data.num_elem * esize);
975                 mono_mb_emit_byte (mb, CEE_PREFIX1);
976                 mono_mb_emit_byte (mb, CEE_CPBLK);                      
977                 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
978                 break;
979         }
980         case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
981                 int src_var, dst_var;
982
983                 src_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
984                 dst_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
985                 
986                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
987                 mono_mb_emit_byte (mb, CEE_LDIND_I);            
988                 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
989                 pos = mb->pos;
990                 mono_mb_emit_byte (mb, 0);
991                 
992                 /* save the old src pointer */
993                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
994                 mono_mb_emit_stloc (mb, src_var);
995                 /* save the old dst pointer */
996                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
997                 mono_mb_emit_stloc (mb, dst_var);
998
999                 /* src = pointer to object data */
1000                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1001                 mono_mb_emit_byte (mb, CEE_LDIND_I);            
1002                 mono_mb_emit_icon (mb, sizeof (MonoObject));
1003                 mono_mb_emit_byte (mb, CEE_ADD);
1004                 mono_mb_emit_byte (mb, CEE_STLOC_0); 
1005
1006                 emit_struct_conv (mb, mono_class_from_mono_type (type), FALSE);
1007                 
1008                 /* restore the old src pointer */
1009                 mono_mb_emit_ldloc (mb, src_var);
1010                 mono_mb_emit_byte (mb, CEE_STLOC_0);
1011                 /* restore the old dst pointer */
1012                 mono_mb_emit_ldloc (mb, dst_var);
1013                 mono_mb_emit_byte (mb, CEE_STLOC_1);
1014
1015                 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
1016                 break;
1017         }
1018         default: {
1019                 char *msg = g_strdup_printf ("marshalling conversion %d not implemented", conv);
1020                 MonoException *exc = mono_get_exception_not_implemented (msg);
1021                 g_warning (msg);
1022                 g_free (msg);
1023                 mono_raise_exception (exc);
1024         }
1025         }
1026 }
1027
1028 static void
1029 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
1030 {
1031         MonoMarshalType *info;
1032         int i;
1033
1034         if (klass->parent)
1035                 emit_struct_conv(mb, klass->parent, to_object);
1036
1037         info = mono_marshal_load_type_info (klass);
1038
1039         if (info->native_size == 0)
1040                 return;
1041
1042         if (klass->blittable) {
1043                 int msize = mono_class_value_size (klass, NULL);
1044                 g_assert (msize == info->native_size);
1045                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
1046                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1047                 mono_mb_emit_icon (mb, msize);
1048                 mono_mb_emit_byte (mb, CEE_PREFIX1);
1049                 mono_mb_emit_byte (mb, CEE_CPBLK);
1050
1051                 mono_mb_emit_add_to_local (mb, 0, msize);
1052                 mono_mb_emit_add_to_local (mb, 1, msize);
1053                 return;
1054         }
1055
1056         for (i = 0; i < info->num_fields; i++) {
1057                 MonoMarshalNative ntype;
1058                 MonoMarshalConv conv;
1059                 MonoType *ftype = info->fields [i].field->type;
1060                 int msize = 0;
1061                 int usize = 0;
1062                 gboolean last_field = i < (info->num_fields -1) ? 0 : 1;
1063
1064                 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
1065                         continue;
1066
1067                 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, klass->unicode, &conv);
1068                         
1069                 if (last_field) {
1070                         msize = klass->instance_size - info->fields [i].field->offset;
1071                         usize = info->native_size - info->fields [i].offset;
1072                 } else {
1073                         msize = info->fields [i + 1].field->offset - info->fields [i].field->offset;
1074                         usize = info->fields [i + 1].offset - info->fields [i].offset;
1075                 }
1076                 if ((msize < 0) || (usize < 0))
1077                         /* This happens with GC aware auto layout */
1078                         g_error ("Type %s which is passed to unmanaged code must have a StructLayout attribute", mono_type_full_name (&klass->byval_arg));
1079
1080                 g_assert ((msize >= 0) && (usize >= 0));
1081
1082                 switch (conv) {
1083                 case MONO_MARSHAL_CONV_NONE: {
1084                         int t;
1085
1086                         if (ftype->byref || ftype->type == MONO_TYPE_I ||
1087                             ftype->type == MONO_TYPE_U) {
1088                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
1089                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1090                                 mono_mb_emit_byte (mb, CEE_LDIND_I);
1091                                 mono_mb_emit_byte (mb, CEE_STIND_I);
1092                                 break;
1093                         }
1094
1095                         t = ftype->type;
1096                 handle_enum:
1097                         switch (t) {
1098                         case MONO_TYPE_I4:
1099                         case MONO_TYPE_U4:
1100 #if SIZEOF_VOID_P == 4
1101                         case MONO_TYPE_PTR:
1102 #endif
1103                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
1104                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1105                                 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1106                                 mono_mb_emit_byte (mb, CEE_STIND_I4);
1107                                 break;
1108                         case MONO_TYPE_I1:
1109                         case MONO_TYPE_U1:
1110                         case MONO_TYPE_BOOLEAN:
1111                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
1112                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1113                                 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1114                                 mono_mb_emit_byte (mb, CEE_STIND_I1);
1115                                 break;
1116                         case MONO_TYPE_I2:
1117                         case MONO_TYPE_U2:
1118                         case MONO_TYPE_CHAR:
1119                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
1120                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1121                                 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1122                                 mono_mb_emit_byte (mb, CEE_STIND_I2);
1123                                 break;
1124                         case MONO_TYPE_I8:
1125                         case MONO_TYPE_U8:
1126 #if SIZEOF_VOID_P == 8
1127                         case MONO_TYPE_PTR:
1128 #endif
1129                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
1130                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1131                                 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1132                                 mono_mb_emit_byte (mb, CEE_STIND_I8);
1133                                 break;
1134                         case MONO_TYPE_R4:
1135                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
1136                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1137                                 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1138                                 mono_mb_emit_byte (mb, CEE_STIND_R4);
1139                                 break;
1140                         case MONO_TYPE_R8:
1141                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
1142                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1143                                 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1144                                 mono_mb_emit_byte (mb, CEE_STIND_R8);
1145                                 break;
1146                         case MONO_TYPE_VALUETYPE:
1147                                 if (ftype->data.klass->enumtype) {
1148                                         t = ftype->data.klass->enum_basetype->type;
1149                                         goto handle_enum;
1150                                 }
1151                                 emit_struct_conv (mb, ftype->data.klass, to_object);
1152                                 continue;
1153                         default:
1154                                 g_warning ("marshaling type %02x not implemented", ftype->type);
1155                                 g_assert_not_reached ();
1156                         }
1157                         break;
1158                 }
1159                 default:
1160                         if (to_object) 
1161                                 emit_ptr_to_str_conv (mb, ftype, conv, usize, msize, info->fields [i].mspec);
1162                         else
1163                                 emit_str_to_ptr_conv (mb, ftype, conv, usize, msize, info->fields [i].mspec);   
1164                 }
1165                 
1166                 if (to_object) {
1167                         mono_mb_emit_add_to_local (mb, 0, usize);
1168                         mono_mb_emit_add_to_local (mb, 1, msize);
1169                 } else {
1170                         mono_mb_emit_add_to_local (mb, 0, msize);
1171                         mono_mb_emit_add_to_local (mb, 1, usize);
1172                 }                               
1173         }
1174 }
1175
1176 static void
1177 emit_thread_interrupt_checkpoint (MonoMethodBuilder *mb)
1178 {
1179         static MonoMethodSignature *state_check_sig = NULL;
1180         int pos_noabort;
1181         
1182         if (!state_check_sig) {
1183                 state_check_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
1184                 state_check_sig->ret = &mono_defaults.void_class->byval_arg;
1185                 state_check_sig->pinvoke = 0;
1186         }
1187         
1188         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1189         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1190         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, (gpointer) mono_thread_interruption_request_flag ()));
1191         mono_mb_emit_byte (mb, CEE_LDIND_I4);
1192         pos_noabort = mono_mb_emit_branch (mb, CEE_BRFALSE);
1193
1194         mono_mb_emit_native_call (mb, state_check_sig, mono_thread_interruption_checkpoint);
1195         
1196         mono_mb_patch_addr (mb, pos_noabort, mb->pos - (pos_noabort + 4));
1197 }
1198
1199 static MonoAsyncResult *
1200 mono_delegate_begin_invoke (MonoDelegate *delegate, gpointer *params)
1201 {
1202         MonoMethodMessage *msg;
1203         MonoDelegate *async_callback;
1204         MonoObject *state;
1205         MonoMethod *im;
1206         MonoClass *klass;
1207         MonoMethod *method = NULL;
1208         int i;
1209
1210         g_assert (delegate);
1211
1212         if (delegate->target && mono_object_class (delegate->target) == mono_defaults.transparent_proxy_class) {
1213
1214                 MonoTransparentProxy* tp = (MonoTransparentProxy *)delegate->target;
1215                 if (!tp->remote_class->proxy_class->contextbound || tp->rp->context != (MonoObject *) mono_context_get ()) {
1216
1217                         /* If the target is a proxy, make a direct call. Is proxy's work
1218                         // to make the call asynchronous.
1219                         */
1220                         MonoAsyncResult *ares;
1221                         MonoObject *exc;
1222                         MonoArray *out_args;
1223                         HANDLE handle;
1224                         method = delegate->method_info->method;
1225
1226                         msg = mono_method_call_message_new (mono_marshal_method_from_wrapper (method), params, NULL, &async_callback, &state);
1227                         handle = CreateEvent (NULL, TRUE, FALSE, NULL);
1228                         ares = mono_async_result_new (mono_domain_get (), handle, state, handle);
1229                         ares->async_delegate = (MonoObject *)delegate;
1230                         ares->async_callback = (MonoObject *)async_callback;
1231                         msg->async_result = ares;
1232                         msg->call_type = CallType_BeginInvoke;
1233
1234                         mono_remoting_invoke ((MonoObject *)tp->rp, msg, &exc, &out_args);
1235                         return ares;
1236                 }
1237         }
1238
1239         klass = delegate->object.vtable->klass;
1240
1241         method = mono_get_delegate_invoke (klass);
1242         for (i = 0; i < klass->method.count; ++i) {
1243                 if (klass->methods [i]->name[0] == 'B' && 
1244                     !strcmp ("BeginInvoke", klass->methods [i]->name)) {
1245                         method = klass->methods [i];
1246                         break;
1247                 }
1248         }
1249
1250         g_assert (method != NULL);
1251
1252         im = mono_get_delegate_invoke (method->klass);
1253         msg = mono_method_call_message_new (method, params, im, &async_callback, &state);
1254
1255         return mono_thread_pool_add ((MonoObject *)delegate, msg, async_callback, state);
1256 }
1257
1258 static int
1259 mono_mb_emit_save_args (MonoMethodBuilder *mb, MonoMethodSignature *sig, gboolean save_this)
1260 {
1261         int i, params_var, tmp_var;
1262
1263         /* allocate local (pointer) *params[] */
1264         params_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1265         /* allocate local (pointer) tmp */
1266         tmp_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1267
1268         /* alloate space on stack to store an array of pointers to the arguments */
1269         mono_mb_emit_icon (mb, sizeof (gpointer) * (sig->param_count + 1));
1270         mono_mb_emit_byte (mb, CEE_PREFIX1);
1271         mono_mb_emit_byte (mb, CEE_LOCALLOC);
1272         mono_mb_emit_stloc (mb, params_var);
1273
1274         /* tmp = params */
1275         mono_mb_emit_ldloc (mb, params_var);
1276         mono_mb_emit_stloc (mb, tmp_var);
1277
1278         if (save_this && sig->hasthis) {
1279                 mono_mb_emit_ldloc (mb, tmp_var);
1280                 mono_mb_emit_ldarg_addr (mb, 0);
1281                 mono_mb_emit_byte (mb, CEE_STIND_I);
1282                 /* tmp = tmp + sizeof (gpointer) */
1283                 if (sig->param_count)
1284                         mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
1285
1286         }
1287
1288         for (i = 0; i < sig->param_count; i++) {
1289                 mono_mb_emit_ldloc (mb, tmp_var);
1290                 mono_mb_emit_ldarg_addr (mb, i + sig->hasthis);
1291                 mono_mb_emit_byte (mb, CEE_STIND_I);
1292                 /* tmp = tmp + sizeof (gpointer) */
1293                 if (i < (sig->param_count - 1))
1294                         mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
1295         }
1296
1297         return params_var;
1298 }
1299
1300 static char*
1301 mono_signature_to_name (MonoMethodSignature *sig, const char *prefix)
1302 {
1303         int i;
1304         char *result;
1305         GString *res = g_string_new ("");
1306
1307         if (prefix) {
1308                 g_string_append (res, prefix);
1309                 g_string_append_c (res, '_');
1310         }
1311
1312         mono_type_get_desc (res, sig->ret, FALSE);
1313
1314         for (i = 0; i < sig->param_count; ++i) {
1315                 g_string_append_c (res, '_');
1316                 mono_type_get_desc (res, sig->params [i], FALSE);
1317         }
1318         result = res->str;
1319         g_string_free (res, FALSE);
1320         return result;
1321 }
1322
1323 /**
1324  * mono_marshal_get_string_encoding:
1325  *
1326  *  Return the string encoding which should be used for a given parameter.
1327  */
1328 static MonoMarshalNative
1329 mono_marshal_get_string_encoding (MonoMethodPInvoke *piinfo, MonoMarshalSpec *spec)
1330 {
1331         /* First try the parameter marshal info */
1332         if (spec) {
1333                 if (spec->native == MONO_NATIVE_LPARRAY) {
1334                         if (spec->data.array_data.elem_type != 0)
1335                                 return spec->data.array_data.elem_type;
1336                 }
1337                 else
1338                         return spec->native;
1339         }
1340
1341         if (!piinfo)
1342                 return MONO_NATIVE_LPSTR;
1343
1344         /* Then try the method level marshal info */
1345         switch (piinfo->piflags & PINVOKE_ATTRIBUTE_CHAR_SET_MASK) {
1346         case PINVOKE_ATTRIBUTE_CHAR_SET_ANSI:
1347                 return MONO_NATIVE_LPSTR;
1348         case PINVOKE_ATTRIBUTE_CHAR_SET_UNICODE:
1349                 return MONO_NATIVE_LPWSTR;
1350         case PINVOKE_ATTRIBUTE_CHAR_SET_AUTO:
1351                 return MONO_NATIVE_LPTSTR;
1352         default:
1353                 return MONO_NATIVE_LPSTR;
1354         }
1355 }
1356
1357 static MonoMarshalNative
1358 mono_marshal_get_stringbuilder_to_ptr_encoding (MonoMethodPInvoke *piinfo, MonoMarshalSpec *spec)
1359 {
1360         MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, spec);
1361
1362         switch (encoding) {
1363         case MONO_NATIVE_LPWSTR:
1364                 return MONO_MARSHAL_CONV_SB_LPWSTR;
1365                 break;
1366         case MONO_NATIVE_LPSTR:
1367                 return MONO_MARSHAL_CONV_SB_LPSTR;
1368                 break;
1369         case MONO_NATIVE_LPTSTR:
1370                 return MONO_MARSHAL_CONV_SB_LPTSTR;
1371                 break;
1372         default:
1373                 return -1;
1374         }
1375 }
1376
1377 static MonoMarshalNative
1378 mono_marshal_get_ptr_to_stringbuilder_encoding (MonoMethodPInvoke *piinfo, MonoMarshalSpec *spec, gboolean *need_free)
1379 {
1380         MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, spec);
1381
1382         *need_free = TRUE;
1383
1384         switch (encoding) {
1385         case MONO_NATIVE_LPWSTR:
1386                 /* 
1387                  * mono_string_builder_to_utf16 does not allocate a 
1388                  * new buffer, so no need to free it.
1389                  */
1390                 *need_free = FALSE;
1391                 return MONO_MARSHAL_CONV_LPWSTR_SB;
1392         case MONO_NATIVE_LPSTR:
1393                 return MONO_MARSHAL_CONV_LPSTR_SB;
1394                 break;
1395         case MONO_NATIVE_LPTSTR:
1396                 return MONO_MARSHAL_CONV_LPTSTR_SB;
1397                 break;
1398         default:
1399                 return -1;
1400         }
1401 }
1402
1403 static inline MonoMethod*
1404 mono_marshal_find_in_cache (GHashTable *cache, gpointer key)
1405 {
1406         MonoMethod *res;
1407
1408         EnterCriticalSection (&marshal_mutex);
1409         res = g_hash_table_lookup (cache, key);
1410         LeaveCriticalSection (&marshal_mutex);
1411         return res;
1412 }
1413
1414 /* Create the method from the builder and place it in the cache */
1415 static inline MonoMethod*
1416 mono_mb_create_and_cache (GHashTable *cache, gpointer key,
1417                                                            MonoMethodBuilder *mb, MonoMethodSignature *sig,
1418                                                            int max_stack)
1419 {
1420         MonoMethod *res;
1421
1422         EnterCriticalSection (&marshal_mutex);
1423         res = g_hash_table_lookup (cache, key);
1424         if (!res) {
1425                 /* This does not acquire any locks */
1426                 res = mono_mb_create_method (mb, sig, max_stack);
1427                 g_hash_table_insert (cache, key, res);
1428                 mono_g_hash_table_insert (wrapper_hash, res, key);
1429         }
1430         else
1431                 /* Somebody created it before us */
1432                 ;
1433         LeaveCriticalSection (&marshal_mutex);
1434
1435         return res;
1436 }               
1437
1438 MonoMethod *
1439 mono_marshal_method_from_wrapper (MonoMethod *wrapper)
1440 {
1441         MonoMethod *res;
1442
1443         if (wrapper->wrapper_type == MONO_WRAPPER_NONE)
1444                 return wrapper;
1445
1446         EnterCriticalSection (&marshal_mutex);
1447         res = mono_g_hash_table_lookup (wrapper_hash, wrapper);
1448         LeaveCriticalSection (&marshal_mutex);
1449
1450         if (res && wrapper->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)
1451                 /* See mono_marshal_get_remoting_invoke_with_check */
1452                 return (MonoMethod*)((char*)res - 1);
1453         else
1454                 return res;
1455 }
1456
1457 MonoMethod *
1458 mono_marshal_get_delegate_begin_invoke (MonoMethod *method)
1459 {
1460         MonoMethodSignature *sig;
1461         static MonoMethodSignature *csig = NULL;
1462         MonoMethodBuilder *mb;
1463         MonoMethod *res;
1464         GHashTable *cache;
1465         int params_var;
1466         char *name;
1467
1468         g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1469                   !strcmp (method->name, "BeginInvoke"));
1470
1471         sig = method->signature;
1472
1473         cache = method->klass->image->delegate_begin_invoke_cache;
1474         if ((res = mono_marshal_find_in_cache (cache, sig)))
1475                 return res;
1476
1477         g_assert (sig->hasthis);
1478
1479         if (!csig) {
1480                 csig = mono_metadata_signature_alloc (method->klass->image, 2);
1481
1482                 /* MonoAsyncResult * begin_invoke (MonoDelegate *delegate, gpointer params[]) */
1483                 csig->ret = &mono_defaults.object_class->byval_arg;
1484                 csig->params [0] = &mono_defaults.object_class->byval_arg;
1485                 csig->params [1] = &mono_defaults.int_class->byval_arg;
1486         }
1487
1488         name = mono_signature_to_name (sig, "begin_invoke");
1489         mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_BEGIN_INVOKE);
1490         g_free (name);
1491
1492         mb->method->save_lmf = 1;
1493
1494         params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1495
1496         mono_mb_emit_ldarg (mb, 0);
1497         mono_mb_emit_ldloc (mb, params_var);
1498         mono_mb_emit_native_call (mb, csig, mono_delegate_begin_invoke);
1499         emit_thread_interrupt_checkpoint (mb);
1500         mono_mb_emit_byte (mb, CEE_RET);
1501
1502         res = mono_mb_create_and_cache (cache, sig, mb, sig, sig->param_count + 16);
1503         mono_mb_free (mb);
1504         return res;
1505 }
1506
1507 static MonoObject *
1508 mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params)
1509 {
1510         MonoDomain *domain = mono_domain_get ();
1511         MonoAsyncResult *ares;
1512         MonoMethod *method = NULL;
1513         MonoMethodSignature *sig;
1514         MonoMethodMessage *msg;
1515         MonoObject *res, *exc;
1516         MonoArray *out_args;
1517         MonoClass *klass;
1518         int i;
1519
1520         g_assert (delegate);
1521
1522         if (!delegate->method_info || !delegate->method_info->method)
1523                 g_assert_not_reached ();
1524
1525         klass = delegate->object.vtable->klass;
1526
1527         for (i = 0; i < klass->method.count; ++i) {
1528                 if (klass->methods [i]->name[0] == 'E' && 
1529                     !strcmp ("EndInvoke", klass->methods [i]->name)) {
1530                         method = klass->methods [i];
1531                         break;
1532                 }
1533         }
1534
1535         g_assert (method != NULL);
1536
1537         sig = method->signature;
1538
1539         msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1540
1541         ares = mono_array_get (msg->args, gpointer, sig->param_count - 1);
1542         g_assert (ares);
1543
1544         if (delegate->target && mono_object_class (delegate->target) == mono_defaults.transparent_proxy_class) {
1545                 MonoTransparentProxy* tp = (MonoTransparentProxy *)delegate->target;
1546                 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
1547                 mono_message_init (domain, msg, delegate->method_info, NULL);
1548                 msg->call_type = CallType_EndInvoke;
1549                 msg->async_result = ares;
1550                 res = mono_remoting_invoke ((MonoObject *)tp->rp, msg, &exc, &out_args);
1551         }
1552         else
1553                 res = mono_thread_pool_finish (ares, &out_args, &exc);
1554
1555         if (exc) {
1556                 if (((MonoException*)exc)->stack_trace) {
1557                         char *strace = mono_string_to_utf8 (((MonoException*)exc)->stack_trace);
1558                         char  *tmp;
1559                         tmp = g_strdup_printf ("%s\nException Rethrown at:\n", strace);
1560                         g_free (strace);        
1561                         ((MonoException*)exc)->stack_trace = mono_string_new (domain, tmp);
1562                         g_free (tmp);
1563                 }
1564                 mono_raise_exception ((MonoException*)exc);
1565         }
1566
1567         mono_method_return_message_restore (method, params, out_args);
1568         return res;
1569 }
1570
1571 static void
1572 mono_mb_emit_restore_result (MonoMethodBuilder *mb, MonoType *return_type)
1573 {
1574         if (return_type->byref)
1575                 return_type = &mono_defaults.int_class->byval_arg;
1576         else if (return_type->type == MONO_TYPE_VALUETYPE && return_type->data.klass->enumtype)
1577                 return_type = return_type->data.klass->enum_basetype;
1578
1579         switch (return_type->type) {
1580         case MONO_TYPE_VOID:
1581                 g_assert_not_reached ();
1582                 break;
1583         case MONO_TYPE_PTR:
1584         case MONO_TYPE_STRING:
1585         case MONO_TYPE_CLASS: 
1586         case MONO_TYPE_OBJECT: 
1587         case MONO_TYPE_ARRAY: 
1588         case MONO_TYPE_SZARRAY: 
1589                 /* nothing to do */
1590                 break;
1591         case MONO_TYPE_U1:
1592         case MONO_TYPE_BOOLEAN:
1593                 mono_mb_emit_byte (mb, CEE_UNBOX);
1594                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1595                 mono_mb_emit_byte (mb, CEE_LDIND_U1);
1596                 break;
1597         case MONO_TYPE_I1:
1598                 mono_mb_emit_byte (mb, CEE_UNBOX);
1599                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1600                 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1601                 break;
1602         case MONO_TYPE_U2:
1603         case MONO_TYPE_CHAR:
1604                 mono_mb_emit_byte (mb, CEE_UNBOX);
1605                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1606                 mono_mb_emit_byte (mb, CEE_LDIND_U2);
1607                 break;
1608         case MONO_TYPE_I2:
1609                 mono_mb_emit_byte (mb, CEE_UNBOX);
1610                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1611                 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1612                 break;
1613         case MONO_TYPE_I:
1614         case MONO_TYPE_U:
1615                 mono_mb_emit_byte (mb, CEE_UNBOX);
1616                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1617                 mono_mb_emit_byte (mb, CEE_LDIND_I);
1618                 break;
1619         case MONO_TYPE_I4:
1620                 mono_mb_emit_byte (mb, CEE_UNBOX);
1621                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1622                 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1623                 break;
1624         case MONO_TYPE_U4:
1625                 mono_mb_emit_byte (mb, CEE_UNBOX);
1626                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1627                 mono_mb_emit_byte (mb, CEE_LDIND_U4);
1628                 break;
1629         case MONO_TYPE_U8:
1630         case MONO_TYPE_I8:
1631                 mono_mb_emit_byte (mb, CEE_UNBOX);
1632                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1633                 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1634                 break;
1635         case MONO_TYPE_R4:
1636                 mono_mb_emit_byte (mb, CEE_UNBOX);
1637                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1638                 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1639                 break;
1640         case MONO_TYPE_R8:
1641                 mono_mb_emit_byte (mb, CEE_UNBOX);
1642                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1643                 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1644                 break;
1645         case MONO_TYPE_VALUETYPE: {
1646                 int class;
1647                 mono_mb_emit_byte (mb, CEE_UNBOX);
1648                 class = mono_mb_add_data (mb, mono_class_from_mono_type (return_type));
1649                 mono_mb_emit_i4 (mb, class);
1650                 mono_mb_emit_byte (mb, CEE_LDOBJ);
1651                 mono_mb_emit_i4 (mb, class);
1652                 break;
1653         }
1654         default:
1655                 g_warning ("type 0x%x not handled", return_type->type);
1656                 g_assert_not_reached ();
1657         }
1658
1659         mono_mb_emit_byte (mb, CEE_RET);
1660 }
1661
1662 MonoMethod *
1663 mono_marshal_get_delegate_end_invoke (MonoMethod *method)
1664 {
1665         MonoMethodSignature *sig;
1666         static MonoMethodSignature *csig = NULL;
1667         MonoMethodBuilder *mb;
1668         MonoMethod *res;
1669         GHashTable *cache;
1670         int params_var;
1671         char *name;
1672
1673         g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1674                   !strcmp (method->name, "EndInvoke"));
1675
1676         sig = method->signature;
1677
1678         cache = method->klass->image->delegate_end_invoke_cache;
1679         if ((res = mono_marshal_find_in_cache (cache, sig)))
1680                 return res;
1681
1682         g_assert (sig->hasthis);
1683
1684         if (!csig) {
1685                 csig = mono_metadata_signature_alloc (method->klass->image, 2);
1686
1687                 /* MonoObject *end_invoke (MonoDelegate *delegate, gpointer params[]) */
1688                 csig->ret = &mono_defaults.object_class->byval_arg;
1689                 csig->params [0] = &mono_defaults.object_class->byval_arg;
1690                 csig->params [1] = &mono_defaults.int_class->byval_arg;
1691         }
1692
1693         name = mono_signature_to_name (sig, "end_invoke");
1694         mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_END_INVOKE);
1695         g_free (name);
1696
1697         mb->method->save_lmf = 1;
1698
1699         params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1700
1701         mono_mb_emit_ldarg (mb, 0);
1702         mono_mb_emit_ldloc (mb, params_var);
1703         mono_mb_emit_native_call (mb, csig, mono_delegate_end_invoke);
1704         emit_thread_interrupt_checkpoint (mb);
1705
1706         if (sig->ret->type == MONO_TYPE_VOID) {
1707                 mono_mb_emit_byte (mb, CEE_POP);
1708                 mono_mb_emit_byte (mb, CEE_RET);
1709         } else
1710                 mono_mb_emit_restore_result (mb, sig->ret);
1711
1712         res = mono_mb_create_and_cache (cache, sig,
1713                                                                                  mb, sig, sig->param_count + 16);
1714         mono_mb_free (mb);
1715
1716         return res;
1717 }
1718
1719 static MonoObject *
1720 mono_remoting_wrapper (MonoMethod *method, gpointer *params)
1721 {
1722         MonoMethodMessage *msg;
1723         MonoTransparentProxy *this;
1724         MonoObject *res, *exc;
1725         MonoArray *out_args;
1726
1727         this = *((MonoTransparentProxy **)params [0]);
1728
1729         g_assert (this);
1730         g_assert (((MonoObject *)this)->vtable->klass == mono_defaults.transparent_proxy_class);
1731         
1732         /* skip the this pointer */
1733         params++;
1734
1735         if (this->remote_class->proxy_class->contextbound && this->rp->context == (MonoObject *) mono_context_get ())
1736         {
1737                 int i;
1738                 MonoMethodSignature *sig = method->signature;
1739                 int count = sig->param_count;
1740                 gpointer* mparams = (gpointer*) alloca(count*sizeof(gpointer));
1741
1742                 for (i=0; i<count; i++) {
1743                         MonoClass *class = mono_class_from_mono_type (sig->params [i]);
1744                         if (class->valuetype) {
1745                                 if (sig->params [i]->byref)
1746                                         mparams[i] = *((gpointer *)params [i]);
1747                                 else 
1748                                         mparams[i] = params [i];
1749                         } else {
1750                                 mparams[i] = *((gpointer**)params [i]);
1751                         }
1752                 }
1753
1754                 return mono_runtime_invoke (method, method->klass->valuetype? mono_object_unbox ((MonoObject*)this): this, mparams, NULL);
1755         }
1756
1757         msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1758
1759         res = mono_remoting_invoke ((MonoObject *)this->rp, msg, &exc, &out_args);
1760
1761         if (exc)
1762                 mono_raise_exception ((MonoException *)exc);
1763
1764         mono_method_return_message_restore (method, params, out_args);
1765
1766         return res;
1767
1768
1769 MonoMethod *
1770 mono_marshal_get_remoting_invoke (MonoMethod *method)
1771 {
1772         MonoMethodSignature *sig;
1773         static MonoMethodSignature *csig = NULL;
1774         MonoMethodBuilder *mb;
1775         MonoMethod *res;
1776         GHashTable *cache;
1777         int params_var;
1778
1779         g_assert (method);
1780
1781         if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE)
1782                 return method;
1783
1784         sig = method->signature;
1785
1786         /* we cant remote methods without this pointer */
1787         if (!sig->hasthis)
1788                 return method;
1789
1790         cache = method->klass->image->remoting_invoke_cache;
1791         if ((res = mono_marshal_find_in_cache (cache, method)))
1792                 return res;
1793
1794         if (!csig) {
1795                 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
1796                 csig->params [0] = &mono_defaults.int_class->byval_arg;
1797                 csig->params [1] = &mono_defaults.int_class->byval_arg;
1798                 csig->ret = &mono_defaults.object_class->byval_arg;
1799                 csig->pinvoke = 1;
1800         }
1801
1802         mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE);
1803         mb->method->save_lmf = 1;
1804
1805         params_var = mono_mb_emit_save_args (mb, sig, TRUE);
1806
1807         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1808         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1809         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
1810         mono_mb_emit_ldloc (mb, params_var);
1811         mono_mb_emit_native_call (mb, csig, mono_remoting_wrapper);
1812         emit_thread_interrupt_checkpoint (mb);
1813
1814         if (sig->ret->type == MONO_TYPE_VOID) {
1815                 mono_mb_emit_byte (mb, CEE_POP);
1816                 mono_mb_emit_byte (mb, CEE_RET);
1817         } else {
1818                  mono_mb_emit_restore_result (mb, sig->ret);
1819         }
1820
1821         res = mono_mb_create_and_cache (cache, method, mb, sig, sig->param_count + 16);
1822         mono_mb_free (mb);
1823
1824         return res;
1825 }
1826
1827 MonoMethod *
1828 mono_marshal_get_remoting_invoke_with_check (MonoMethod *method)
1829 {
1830         MonoMethodSignature *sig;
1831         MonoMethodBuilder *mb;
1832         MonoMethod *res, *native;
1833         GHashTable *cache;
1834         int i, pos;
1835
1836         g_assert (method);
1837
1838         if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)
1839                 return method;
1840
1841         sig = method->signature;
1842
1843         /* we cant remote methods without this pointer */
1844         g_assert (sig->hasthis);
1845
1846         cache = method->klass->image->remoting_invoke_cache;
1847         if ((res = mono_marshal_find_in_cache (cache, (char *)method + 1)))
1848                 return res;
1849
1850         mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK);
1851
1852         mono_mb_emit_ldarg (mb, 0);
1853         pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
1854
1855         native = mono_marshal_get_remoting_invoke (method);
1856
1857         for (i = 0; i <= sig->param_count; i++)
1858                 mono_mb_emit_ldarg (mb, i);
1859         
1860         mono_mb_emit_managed_call (mb, native, native->signature);
1861         mono_mb_emit_byte (mb, CEE_RET);
1862
1863         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1864
1865         for (i = 0; i <= sig->param_count; i++)
1866                 mono_mb_emit_ldarg (mb, i);
1867                 
1868         mono_mb_emit_managed_call (mb, method, method->signature);
1869         mono_mb_emit_byte (mb, CEE_RET);
1870
1871         res = mono_mb_create_and_cache (cache, (char*)method + 1,
1872                                                                                  mb, sig, sig->param_count + 16);
1873         mono_mb_free (mb);
1874
1875         return res;
1876 }
1877
1878 /*
1879  * the returned method invokes all methods in a multicast delegate 
1880  */
1881 MonoMethod *
1882 mono_marshal_get_delegate_invoke (MonoMethod *method)
1883 {
1884         MonoMethodSignature *sig, *static_sig;
1885         int i;
1886         MonoMethodBuilder *mb;
1887         MonoMethod *res;
1888         GHashTable *cache;
1889         int pos0, pos1;
1890         char *name;
1891
1892         g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1893                   !strcmp (method->name, "Invoke"));
1894                 
1895         sig = method->signature;
1896
1897         cache = method->klass->image->delegate_invoke_cache;
1898         if ((res = mono_marshal_find_in_cache (cache, sig)))
1899                 return res;
1900
1901         static_sig = mono_metadata_signature_dup (sig);
1902         static_sig->hasthis = 0;
1903
1904         name = mono_signature_to_name (sig, "invoke");
1905         mb = mono_mb_new (mono_defaults.multicastdelegate_class, name,  MONO_WRAPPER_DELEGATE_INVOKE);
1906         g_free (name);
1907
1908         /* allocate local 0 (object) */
1909         mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1910
1911         g_assert (sig->hasthis);
1912         
1913         /*
1914          * if (prev != null)
1915          *      prev.Invoke( args .. );
1916          * return this.<target>( args .. );
1917          */
1918         
1919         /* this wrapper can be used in unmanaged-managed transitions */
1920         emit_thread_interrupt_checkpoint (mb);
1921         
1922         /* get this->prev */
1923         mono_mb_emit_ldarg (mb, 0);
1924         mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoMulticastDelegate, prev));
1925         mono_mb_emit_byte (mb, CEE_LDIND_I );
1926         mono_mb_emit_stloc (mb, 0);
1927
1928         /* if prev != null */
1929         mono_mb_emit_ldloc (mb, 0);
1930         mono_mb_emit_byte (mb, CEE_BRFALSE);
1931
1932         pos0 = mb->pos;
1933         mono_mb_emit_i4 (mb, 0);
1934
1935         /* then recurse */
1936         mono_mb_emit_ldloc (mb, 0);
1937         for (i = 0; i < sig->param_count; i++)
1938                 mono_mb_emit_ldarg (mb, i + 1);
1939         mono_mb_emit_managed_call (mb, method, method->signature);
1940         if (sig->ret->type != MONO_TYPE_VOID)
1941                 mono_mb_emit_byte (mb, CEE_POP);
1942
1943         /* continued or prev == null */
1944         mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1945
1946         /* get this->target */
1947         mono_mb_emit_ldarg (mb, 0);
1948         mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, target));
1949         mono_mb_emit_byte (mb, CEE_LDIND_I );
1950         mono_mb_emit_stloc (mb, 0);
1951
1952         /* if target != null */
1953         mono_mb_emit_ldloc (mb, 0);
1954         mono_mb_emit_byte (mb, CEE_BRFALSE);
1955         pos0 = mb->pos;
1956         mono_mb_emit_i4 (mb, 0);
1957         
1958         /* then call this->method_ptr nonstatic */
1959         mono_mb_emit_ldloc (mb, 0); 
1960         for (i = 0; i < sig->param_count; ++i)
1961                 mono_mb_emit_ldarg (mb, i + 1);
1962         mono_mb_emit_ldarg (mb, 0);
1963         mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1964         mono_mb_emit_byte (mb, CEE_LDIND_I );
1965         mono_mb_emit_byte (mb, CEE_CALLI);
1966         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
1967
1968         mono_mb_emit_byte (mb, CEE_BR);
1969         pos1 = mb->pos;
1970         mono_mb_emit_i4 (mb, 0);
1971
1972         /* else [target == null] call this->method_ptr static */
1973         mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1974
1975         for (i = 0; i < sig->param_count; ++i)
1976                 mono_mb_emit_ldarg (mb, i + 1);
1977         mono_mb_emit_ldarg (mb, 0);
1978         mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1979         mono_mb_emit_byte (mb, CEE_LDIND_I );
1980         mono_mb_emit_byte (mb, CEE_CALLI);
1981         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, static_sig));
1982
1983         /* return */
1984         mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
1985         mono_mb_emit_byte (mb, CEE_RET);
1986
1987         res = mono_mb_create_and_cache (cache, sig,
1988                                                                                  mb, sig, sig->param_count + 16);
1989         mono_mb_free (mb);
1990
1991         return res;     
1992 }
1993
1994 typedef struct {
1995         MonoMethod *ctor;
1996         MonoMethodSignature *sig;
1997 } CtorSigPair;
1998
1999 /*
2000  * generates IL code for the runtime invoke function 
2001  * MonoObject *runtime_invoke (MonoObject *this, void **params, MonoObject **exc, void* method)
2002  *
2003  * we also catch exceptions if exc != null
2004  */
2005 MonoMethod *
2006 mono_marshal_get_runtime_invoke (MonoMethod *method)
2007 {
2008         MonoMethodSignature *sig, *csig, *callsig;
2009         MonoExceptionClause *clause;
2010         MonoMethodHeader *header;
2011         MonoMethodBuilder *mb;
2012         GHashTable *cache = NULL;
2013         MonoClass *target_klass;
2014         MonoMethod *res = NULL;
2015         GSList *item;
2016         static MonoString *string_dummy = NULL;
2017         int i, pos;
2018         char *name;
2019
2020         g_assert (method);
2021
2022         target_klass = method->klass;
2023         
2024         EnterCriticalSection (&marshal_mutex);
2025
2026         if (method->string_ctor) {
2027                 static GSList *strsig_list = NULL;
2028                 CtorSigPair *cs;
2029
2030                 callsig = NULL;
2031                 for (item = strsig_list; item; item = item->next) {
2032                         cs = item->data;
2033                         if (mono_metadata_signature_equal (method->signature, cs->ctor->signature)) {
2034                                 callsig = cs->sig;
2035                                 break;
2036                         }
2037                 }
2038                 if (!callsig) {
2039                         callsig = mono_metadata_signature_dup (method->signature);
2040                         callsig->ret = &mono_defaults.string_class->byval_arg;
2041                         cs = g_new (CtorSigPair, 1);
2042                         cs->sig = callsig;
2043                         cs->ctor = method;
2044                         strsig_list = g_slist_prepend (strsig_list, cs);
2045                 }
2046         } else {
2047                 callsig = method->signature;
2048         }
2049
2050         cache = method->klass->image->runtime_invoke_cache;
2051
2052         /* from mono_marshal_find_in_cache */
2053         res = g_hash_table_lookup (cache, callsig);
2054         LeaveCriticalSection (&marshal_mutex);
2055
2056         if (res) {
2057                 return res;
2058         }
2059
2060         target_klass = mono_defaults.object_class;
2061
2062         /* to make it work with our special string constructors */
2063         if (!string_dummy) {
2064                 MONO_GC_REGISTER_ROOT (string_dummy);
2065                 string_dummy = mono_string_new_wrapper ("dummy");
2066         }
2067         
2068         sig = method->signature;
2069
2070         csig = mono_metadata_signature_alloc (method->klass->image, 4);
2071
2072         csig->ret = &mono_defaults.object_class->byval_arg;
2073         csig->params [0] = &mono_defaults.object_class->byval_arg;
2074         csig->params [1] = &mono_defaults.int_class->byval_arg;
2075         csig->params [2] = &mono_defaults.int_class->byval_arg;
2076         csig->params [3] = &mono_defaults.int_class->byval_arg;
2077
2078         name = mono_signature_to_name (callsig, "runtime_invoke");
2079         mb = mono_mb_new (target_klass, name,  MONO_WRAPPER_RUNTIME_INVOKE);
2080         g_free (name);
2081
2082         /* allocate local 0 (object) tmp */
2083         mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2084         /* allocate local 1 (object) exc */
2085         mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2086
2087         /* cond set *exc to null */
2088         mono_mb_emit_byte (mb, CEE_LDARG_2);
2089         mono_mb_emit_byte (mb, CEE_BRFALSE_S);
2090         mono_mb_emit_byte (mb, 3);      
2091         mono_mb_emit_byte (mb, CEE_LDARG_2);
2092         mono_mb_emit_byte (mb, CEE_LDNULL);
2093         mono_mb_emit_byte (mb, CEE_STIND_I);
2094
2095         if (sig->hasthis) {
2096                 if (method->string_ctor) {
2097                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2098                         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
2099                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, string_dummy));
2100                 } else {
2101                         mono_mb_emit_ldarg (mb, 0);
2102                 }
2103         }
2104
2105         for (i = 0; i < sig->param_count; i++) {
2106                 MonoType *t = sig->params [i];
2107                 int type;
2108
2109                 mono_mb_emit_ldarg (mb, 1);
2110                 if (i) {
2111                         mono_mb_emit_icon (mb, sizeof (gpointer) * i);
2112                         mono_mb_emit_byte (mb, CEE_ADD);
2113                 }
2114                 mono_mb_emit_byte (mb, CEE_LDIND_I);
2115
2116                 if (t->byref)
2117                         continue;
2118
2119                 type = sig->params [i]->type;
2120 handle_enum:
2121                 switch (type) {
2122                 case MONO_TYPE_I1:
2123                         mono_mb_emit_byte (mb, CEE_LDIND_I1);
2124                         break;
2125                 case MONO_TYPE_BOOLEAN:
2126                 case MONO_TYPE_U1:
2127                         mono_mb_emit_byte (mb, CEE_LDIND_U1);
2128                         break;
2129                 case MONO_TYPE_I2:
2130                         mono_mb_emit_byte (mb, CEE_LDIND_I2);
2131                         break;
2132                 case MONO_TYPE_U2:
2133                 case MONO_TYPE_CHAR:
2134                         mono_mb_emit_byte (mb, CEE_LDIND_U2);
2135                         break;
2136                 case MONO_TYPE_I:
2137                 case MONO_TYPE_U:
2138                         mono_mb_emit_byte (mb, CEE_LDIND_I);
2139                         break;
2140                 case MONO_TYPE_I4:
2141                         mono_mb_emit_byte (mb, CEE_LDIND_I4);
2142                         break;
2143                 case MONO_TYPE_U4:
2144                         mono_mb_emit_byte (mb, CEE_LDIND_U4);
2145                         break;
2146                 case MONO_TYPE_R4:
2147                         mono_mb_emit_byte (mb, CEE_LDIND_R4);
2148                         break;
2149                 case MONO_TYPE_R8:
2150                         mono_mb_emit_byte (mb, CEE_LDIND_R8);
2151                         break;
2152                 case MONO_TYPE_I8:
2153                 case MONO_TYPE_U8:
2154                         mono_mb_emit_byte (mb, CEE_LDIND_I8);
2155                         break;
2156                 case MONO_TYPE_STRING:
2157                 case MONO_TYPE_CLASS:  
2158                 case MONO_TYPE_ARRAY:
2159                 case MONO_TYPE_PTR:
2160                 case MONO_TYPE_SZARRAY:
2161                 case MONO_TYPE_OBJECT:
2162                         /* do nothing */
2163                         break;
2164                 case MONO_TYPE_VALUETYPE:
2165                         if (t->data.klass->enumtype) {
2166                                 type = t->data.klass->enum_basetype->type;
2167                                 goto handle_enum;
2168                         }
2169                         mono_mb_emit_byte (mb, CEE_LDOBJ);
2170                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, t->data.klass));
2171                         break;
2172                 default:
2173                         g_assert_not_reached ();
2174                 }               
2175         }
2176         
2177         mono_mb_emit_ldarg (mb, 3);
2178         mono_mb_emit_calli (mb, callsig);
2179
2180         if (sig->ret->byref) {
2181                 /* fixme: */
2182                 g_assert_not_reached ();
2183         }
2184
2185
2186         switch (sig->ret->type) {
2187         case MONO_TYPE_VOID:
2188                 if (!method->string_ctor)
2189                         mono_mb_emit_byte (mb, CEE_LDNULL);
2190                 break;
2191         case MONO_TYPE_BOOLEAN:
2192         case MONO_TYPE_CHAR:
2193         case MONO_TYPE_I1:
2194         case MONO_TYPE_U1:
2195         case MONO_TYPE_I2:
2196         case MONO_TYPE_U2:
2197         case MONO_TYPE_I4:
2198         case MONO_TYPE_U4:
2199         case MONO_TYPE_I:
2200         case MONO_TYPE_U:
2201         case MONO_TYPE_R4:
2202         case MONO_TYPE_R8:
2203         case MONO_TYPE_I8:
2204         case MONO_TYPE_U8:
2205         case MONO_TYPE_VALUETYPE:
2206                 /* box value types */
2207                 mono_mb_emit_byte (mb, CEE_BOX);
2208                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (sig->ret)));
2209                 break;
2210         case MONO_TYPE_STRING:
2211         case MONO_TYPE_CLASS:  
2212         case MONO_TYPE_ARRAY:
2213         case MONO_TYPE_SZARRAY:
2214         case MONO_TYPE_OBJECT:
2215                 /* nothing to do */
2216                 break;
2217         case MONO_TYPE_PTR:
2218         default:
2219                 g_assert_not_reached ();
2220         }
2221
2222         mono_mb_emit_stloc (mb, 0);
2223                 
2224         mono_mb_emit_byte (mb, CEE_LEAVE);
2225         pos = mb->pos;
2226         mono_mb_emit_i4 (mb, 0);
2227
2228         clause = g_new0 (MonoExceptionClause, 1);
2229         clause->flags = MONO_EXCEPTION_CLAUSE_FILTER;
2230         clause->try_len = mb->pos;
2231
2232         /* filter code */
2233         clause->token_or_filter = mb->pos;
2234         
2235         mono_mb_emit_byte (mb, CEE_POP);
2236         mono_mb_emit_byte (mb, CEE_LDARG_2);
2237         mono_mb_emit_byte (mb, CEE_LDC_I4_0);
2238         mono_mb_emit_byte (mb, CEE_PREFIX1);
2239         mono_mb_emit_byte (mb, CEE_CGT_UN);
2240         mono_mb_emit_byte (mb, CEE_PREFIX1);
2241         mono_mb_emit_byte (mb, CEE_ENDFILTER);
2242
2243         clause->handler_offset = mb->pos;
2244
2245         /* handler code */
2246         /* store exception */
2247         mono_mb_emit_stloc (mb, 1);
2248         
2249         mono_mb_emit_byte (mb, CEE_LDARG_2);
2250         mono_mb_emit_ldloc (mb, 1);
2251         mono_mb_emit_byte (mb, CEE_STIND_I);
2252
2253         mono_mb_emit_byte (mb, CEE_LDC_I4_0);
2254         mono_mb_emit_stloc (mb, 0);
2255
2256         mono_mb_emit_byte (mb, CEE_LEAVE);
2257         mono_mb_emit_i4 (mb, 0);
2258
2259         clause->handler_len = mb->pos - clause->handler_offset;
2260
2261         /* return result */
2262         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2263         mono_mb_emit_ldloc (mb, 0);
2264         mono_mb_emit_byte (mb, CEE_RET);
2265
2266         /* taken from mono_mb_create_and_cache */
2267         EnterCriticalSection (&marshal_mutex);
2268
2269         res = g_hash_table_lookup (cache, callsig);
2270         /* Somebody may have created it before us */
2271         if (!res) {
2272                 res = mono_mb_create_method (mb, csig, sig->param_count + 16);
2273                 g_hash_table_insert (cache, callsig, res);
2274                 mono_g_hash_table_insert (wrapper_hash, res, callsig);
2275         }
2276
2277         LeaveCriticalSection (&marshal_mutex);
2278         /* end mono_mb_create_and_cache */
2279
2280         mono_mb_free (mb);
2281
2282         header = ((MonoMethodNormal *)res)->header;
2283         header->num_clauses = 1;
2284         header->clauses = clause;
2285
2286         return res;     
2287 }
2288
2289 /*
2290  * generates IL code to call managed methods from unmanaged code 
2291  */
2292 MonoMethod *
2293 mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this, MonoMarshalSpec **mspecs)
2294 {
2295         MonoMethodSignature *sig, *csig;
2296         MonoMethodBuilder *mb;
2297         MonoClass *klass = NULL;
2298         MonoMethod *res;
2299         GHashTable *cache;
2300         int i, pos = 0, *tmp_locals;
2301         static MonoMethodSignature *alloc_sig = NULL;
2302         int retobj_var = 0;
2303
2304         g_assert (method != NULL);
2305         g_assert (!method->signature->pinvoke);
2306
2307         cache = method->klass->image->managed_wrapper_cache;
2308         if (!this && (res = mono_marshal_find_in_cache (cache, method)))
2309                 return res;
2310
2311         /* Under MS, the allocation should be done using CoTaskMemAlloc */
2312         if (!alloc_sig) {
2313                 alloc_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
2314                 alloc_sig->params [0] = &mono_defaults.int_class->byval_arg;
2315                 alloc_sig->ret = &mono_defaults.int_class->byval_arg;
2316                 alloc_sig->pinvoke = 1;
2317         }
2318
2319         if (this) {
2320                 /* fime: howto free that memory ? */
2321         }
2322
2323         sig = method->signature;
2324
2325         mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_NATIVE_TO_MANAGED);
2326
2327         /* allocate local 0 (pointer) src_ptr */
2328         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2329         /* allocate local 1 (pointer) dst_ptr */
2330         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2331         /* allocate local 2 (boolean) delete_old */
2332         mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2333
2334         if (!MONO_TYPE_IS_VOID(sig->ret)) {
2335                 /* allocate local 3 to store the return value */
2336                 mono_mb_add_local (mb, sig->ret);
2337         }
2338
2339         mono_mb_emit_icon (mb, 0);
2340         mono_mb_emit_byte (mb, CEE_STLOC_2);
2341
2342         /* we copy the signature, so that we can modify it */
2343         csig = mono_metadata_signature_dup (sig);
2344         csig->hasthis = 0;
2345         csig->pinvoke = 1;
2346
2347 #ifdef PLATFORM_WIN32
2348         /* 
2349          * Under windows, delegates passed to native code must use the STDCALL
2350          * calling convention.
2351          */
2352         csig->call_convention = MONO_CALL_STDCALL;
2353 #endif
2354
2355         /* fixme: howto handle this ? */
2356         if (sig->hasthis) {
2357
2358                 if (this) {
2359                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2360                         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
2361                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, this));
2362
2363
2364                 } else {
2365                         /* fixme: */
2366                         g_assert_not_reached ();
2367                 }
2368         } 
2369
2370
2371         /* we first do all conversions */
2372         tmp_locals = alloca (sizeof (int) * sig->param_count);
2373         for (i = 0; i < sig->param_count; i ++) {
2374                 MonoType *t = sig->params [i];
2375                 MonoMarshalSpec *spec = mspecs [i + 1];
2376
2377                 tmp_locals [i] = 0;
2378                 
2379                 /* Ensure that we have marshalling info for this param */
2380                 mono_marshal_load_type_info (mono_class_from_mono_type (t));
2381                 
2382                 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
2383                         MonoType *mtype;
2384                         MonoClass *mklass;
2385                         MonoMethod *marshal_native_to_managed;
2386                         MonoMethod *get_instance;
2387
2388                         /* FIXME: Call CleanUpNativeData after the call */
2389
2390                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
2391                         g_assert (mtype != NULL);
2392                         mklass = mono_class_from_mono_type (mtype);
2393                         g_assert (mklass != NULL);
2394
2395                         marshal_native_to_managed = mono_find_method_by_name (mklass, "MarshalNativeToManaged", 1);
2396                         g_assert (marshal_native_to_managed);
2397                         get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
2398                         g_assert (get_instance);
2399                         
2400                         switch (t->type) {
2401                         case MONO_TYPE_CLASS:
2402                         case MONO_TYPE_OBJECT:
2403                         case MONO_TYPE_STRING:
2404                         case MONO_TYPE_ARRAY:
2405                         case MONO_TYPE_SZARRAY:
2406                                 if (t->byref)
2407                                         break;
2408
2409                                 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2410
2411                                 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
2412
2413                                 mono_mb_emit_byte (mb, CEE_CALL);
2414                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
2415                                 
2416                                 mono_mb_emit_ldarg (mb, i);
2417                                 
2418                                 mono_mb_emit_byte (mb, CEE_CALLVIRT);
2419                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_native_to_managed));
2420                                 
2421                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
2422                                 break;
2423                         default:
2424                                 g_warning ("custom marshalling of type %x is currently not supported", t->type);
2425                                 g_assert_not_reached ();
2426                                 break;
2427                         }
2428                         continue;
2429                 }
2430
2431                 switch (t->type) {
2432                 case MONO_TYPE_CLASS: {
2433                         klass = t->data.klass;
2434
2435                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2436
2437                         if (klass->delegate) {
2438                                 g_assert (!t->byref);
2439                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2440                                 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
2441                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2442                                 mono_mb_emit_ldarg (mb, i);
2443                                 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL));
2444                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
2445                                 break;
2446                         }
2447
2448                         /* FIXME: Raise a MarshalDirectiveException here */
2449                         g_assert ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT);
2450
2451                         if (t->attrs & PARAM_ATTRIBUTE_OUT) {
2452                                 mono_mb_emit_byte (mb, CEE_LDNULL);
2453                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
2454                                 break;
2455                         }
2456
2457                         /* Set src */
2458                         mono_mb_emit_ldarg (mb, i);
2459                         if (t->byref) {
2460                                 int pos2;
2461
2462                                 /* Check for NULL and raise an exception */
2463                                 mono_mb_emit_byte (mb, CEE_BRTRUE);
2464                                 pos2 = mb->pos;
2465                                 mono_mb_emit_i4 (mb, 0);
2466
2467                                 mono_mb_emit_exception (mb, "ArgumentNullException", NULL);
2468
2469                                 mono_mb_patch_addr (mb, pos2, mb->pos - (pos2 + 4));
2470                                 mono_mb_emit_ldarg (mb, i);
2471                                 mono_mb_emit_byte (mb, CEE_LDIND_I);
2472                         }                               
2473
2474                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2475
2476                         mono_mb_emit_byte (mb, CEE_LDC_I4_0);
2477                         mono_mb_emit_stloc (mb, tmp_locals [i]);
2478
2479                         mono_mb_emit_byte (mb, CEE_LDLOC_0);
2480                         mono_mb_emit_byte (mb, CEE_BRFALSE);
2481                         pos = mb->pos;
2482                         mono_mb_emit_i4 (mb, 0);
2483
2484                         /* Create and set dst */
2485                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2486                         mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);        
2487                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2488                         mono_mb_emit_stloc (mb, tmp_locals [i]);
2489                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
2490                         mono_mb_emit_icon (mb, sizeof (MonoObject));
2491                         mono_mb_emit_byte (mb, CEE_ADD);
2492                         mono_mb_emit_byte (mb, CEE_STLOC_1); 
2493
2494                         /* emit valuetype conversion code */
2495                         emit_struct_conv (mb, klass, TRUE);
2496
2497                         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2498                         break;
2499                 }
2500                 case MONO_TYPE_VALUETYPE:
2501                         
2502                         klass = sig->params [i]->data.klass;
2503                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2504                             klass->blittable || klass->enumtype)
2505                                 break;
2506
2507                         tmp_locals [i] = mono_mb_add_local (mb, &klass->byval_arg);
2508
2509                         if (t->attrs & PARAM_ATTRIBUTE_OUT)
2510                                 break;
2511
2512                         if (t->byref) 
2513                                 mono_mb_emit_ldarg (mb, i);
2514                         else
2515                                 mono_mb_emit_ldarg_addr (mb, i);
2516                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2517
2518                         if (t->byref) {
2519                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2520                                 mono_mb_emit_byte (mb, CEE_BRFALSE);
2521                                 pos = mb->pos;
2522                                 mono_mb_emit_i4 (mb, 0);
2523                         }                       
2524
2525                         mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2526                         mono_mb_emit_byte (mb, CEE_STLOC_1);
2527
2528                         /* emit valuetype conversion code */
2529                         emit_struct_conv (mb, klass, TRUE);
2530
2531                         if (t->byref)
2532                                 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2533                         break;
2534                 case MONO_TYPE_STRING: {
2535                         MonoMarshalNative encoding = mono_marshal_get_string_encoding (NULL, spec);
2536
2537                         if (t->byref)
2538                                 continue;
2539
2540                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2541                         csig->params [i] = &mono_defaults.int_class->byval_arg;
2542
2543                         mono_mb_emit_ldarg (mb, i);
2544
2545                         switch (encoding) {
2546                         case MONO_NATIVE_LPWSTR:
2547                                 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_LPWSTR_STR));
2548                                 break;
2549                         case MONO_NATIVE_LPSTR:
2550                                 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_LPSTR_STR));
2551                                 break;
2552                         default: {
2553                                         char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding);
2554                                         MonoException *exc = mono_get_exception_not_implemented (msg);
2555                                         g_warning (msg);
2556                                         g_free (msg);
2557                                         mono_raise_exception (exc);
2558                                 }
2559                         }
2560
2561                         mono_mb_emit_stloc (mb, tmp_locals [i]);
2562                         break;  
2563                 }
2564                 case MONO_TYPE_ARRAY:
2565                 case MONO_TYPE_SZARRAY:
2566                         if (t->byref)
2567                                 continue;
2568
2569                         klass = mono_class_from_mono_type (t);
2570
2571                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2572                         csig->params [i] = &mono_defaults.int_class->byval_arg;
2573
2574                         g_warning ("array marshaling not implemented");
2575                         g_assert_not_reached ();
2576                         break;
2577                 }
2578         }
2579
2580         for (i = 0; i < sig->param_count; i++) {
2581                 MonoType *t = sig->params [i];
2582
2583                 switch (t->type) {
2584                 case MONO_TYPE_BOOLEAN:
2585                 case MONO_TYPE_I1:
2586                 case MONO_TYPE_U1:
2587                 case MONO_TYPE_I2:
2588                 case MONO_TYPE_U2:
2589                 case MONO_TYPE_I4:
2590                 case MONO_TYPE_U4:
2591                 case MONO_TYPE_I:
2592                 case MONO_TYPE_U:
2593                 case MONO_TYPE_PTR:
2594                 case MONO_TYPE_R4:
2595                 case MONO_TYPE_R8:
2596                 case MONO_TYPE_I8:
2597                 case MONO_TYPE_U8:
2598                         mono_mb_emit_ldarg (mb, i);
2599                         break;
2600                 case MONO_TYPE_STRING:
2601                         if (t->byref) {
2602                                 mono_mb_emit_ldarg (mb, i);
2603                         } else {
2604                                 g_assert (tmp_locals [i]);
2605                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2606                         }
2607                         break;  
2608                 case MONO_TYPE_CLASS:  
2609                         if (t->byref)
2610                                 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2611                         else
2612                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2613                         break;
2614                 case MONO_TYPE_ARRAY:
2615                 case MONO_TYPE_SZARRAY:
2616                 case MONO_TYPE_OBJECT:
2617                         if (tmp_locals [i])
2618                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2619                         else
2620                                 mono_mb_emit_ldarg (mb, i);
2621                         break;
2622                 case MONO_TYPE_VALUETYPE:
2623                         klass = sig->params [i]->data.klass;
2624                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2625                             klass->blittable || klass->enumtype) {
2626                                 mono_mb_emit_ldarg (mb, i);
2627                                 break;
2628                         }
2629
2630                         g_assert (tmp_locals [i]);
2631                         if (t->byref)
2632                                 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2633                         else
2634                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2635                         break;
2636                 default:
2637                         g_warning ("type 0x%02x unknown", t->type);     
2638                         g_assert_not_reached ();
2639                 }
2640         }
2641
2642         emit_thread_interrupt_checkpoint (mb);
2643         mono_mb_emit_managed_call (mb, method, NULL);
2644
2645         /* Ensure that we have marshalling info for the return */
2646         mono_marshal_load_type_info (mono_class_from_mono_type (sig->ret));
2647
2648         if (!sig->ret->byref) { 
2649                 switch (sig->ret->type) {
2650                 case MONO_TYPE_VOID:
2651                         break;
2652                 case MONO_TYPE_BOOLEAN:
2653                 case MONO_TYPE_I1:
2654                 case MONO_TYPE_U1:
2655                 case MONO_TYPE_I2:
2656                 case MONO_TYPE_U2:
2657                 case MONO_TYPE_I4:
2658                 case MONO_TYPE_U4:
2659                 case MONO_TYPE_I:
2660                 case MONO_TYPE_U:
2661                 case MONO_TYPE_PTR:
2662                 case MONO_TYPE_R4:
2663                 case MONO_TYPE_R8:
2664                 case MONO_TYPE_I8:
2665                 case MONO_TYPE_U8:
2666                 case MONO_TYPE_OBJECT:
2667                         mono_mb_emit_byte (mb, CEE_STLOC_3);
2668                         break;
2669                 case MONO_TYPE_STRING:          
2670                         csig->ret = &mono_defaults.int_class->byval_arg;
2671
2672                         mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_STR_LPSTR));
2673                         mono_mb_emit_byte (mb, CEE_STLOC_3);
2674                         break;
2675                 case MONO_TYPE_VALUETYPE:
2676                         klass = sig->ret->data.klass;
2677                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2678                             klass->blittable || klass->enumtype)
2679                                 break;
2680                         
2681                         /* load pointer to returned value type */
2682                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2683                         mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
2684                         
2685                         /* store the address of the source into local variable 0 */
2686                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2687                         /* allocate space for the native struct and
2688                          * store the address into dst_ptr */
2689                         retobj_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2690                         g_assert (retobj_var);
2691                         mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2692                         mono_mb_emit_byte (mb, CEE_CONV_I);
2693                         mono_mb_emit_native_call (mb, alloc_sig, mono_marshal_alloc);
2694                         emit_thread_interrupt_checkpoint (mb);
2695                         mono_mb_emit_byte (mb, CEE_STLOC_1);
2696                         mono_mb_emit_byte (mb, CEE_LDLOC_1);
2697                         mono_mb_emit_stloc (mb, retobj_var);
2698
2699                         /* emit valuetype conversion code */
2700                         emit_struct_conv (mb, klass, FALSE);
2701                         break;
2702                 case MONO_TYPE_CLASS: {
2703                         int pos2;
2704
2705                         klass = sig->ret->data.klass;
2706
2707                         if (klass->delegate) {
2708                                 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN));
2709                                 mono_mb_emit_byte (mb, CEE_STLOC_3);
2710                                 break;
2711                         }
2712
2713                         /* FIXME: Raise a MarshalDirectiveException here */
2714                         g_assert ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT);
2715
2716                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2717                         /* Check for null */
2718                         mono_mb_emit_byte (mb, CEE_LDLOC_0);
2719                         pos = mono_mb_emit_branch (mb, CEE_BRTRUE);
2720                         mono_mb_emit_byte (mb, CEE_LDNULL);
2721                         mono_mb_emit_byte (mb, CEE_STLOC_3);
2722                         pos2 = mono_mb_emit_branch (mb, CEE_BR);
2723
2724                         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2725
2726                         /* Set src */
2727                         mono_mb_emit_byte (mb, CEE_LDLOC_0);
2728                         mono_mb_emit_icon (mb, sizeof (MonoObject));
2729                         mono_mb_emit_byte (mb, CEE_ADD);
2730                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2731
2732                         /* Allocate and set dest */
2733                         mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2734                         mono_mb_emit_byte (mb, CEE_CONV_I);
2735                         mono_mb_emit_native_call (mb, alloc_sig, mono_marshal_alloc);
2736                         emit_thread_interrupt_checkpoint (mb);
2737                         mono_mb_emit_byte (mb, CEE_DUP);
2738                         mono_mb_emit_byte (mb, CEE_STLOC_1);
2739                         mono_mb_emit_byte (mb, CEE_STLOC_3);
2740
2741                         emit_struct_conv (mb, klass, FALSE);
2742
2743                         mono_mb_patch_addr (mb, pos2, mb->pos - (pos2 + 4));
2744                         break;
2745                 }
2746                 default:
2747                         g_warning ("return type 0x%02x unknown", sig->ret->type);       
2748                         g_assert_not_reached ();
2749                 }
2750         } else {
2751                 mono_mb_emit_byte (mb, CEE_STLOC_3);
2752         }
2753
2754         /* Convert byref arguments back */
2755         for (i = 0; i < sig->param_count; i ++) {
2756                 MonoType *t = sig->params [i];
2757
2758                 if (!t->byref)
2759                         continue;
2760
2761                 switch (t->type) {
2762                 case MONO_TYPE_CLASS: {
2763                         int pos2;
2764
2765                         klass = t->data.klass;
2766
2767                         /* Check for null */
2768                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
2769                         pos = mono_mb_emit_branch (mb, CEE_BRTRUE);
2770                         mono_mb_emit_ldarg (mb, i);
2771                         mono_mb_emit_byte (mb, CEE_LDC_I4_0);
2772                         mono_mb_emit_byte (mb, CEE_STIND_I);
2773                         pos2 = mono_mb_emit_branch (mb, CEE_BR);
2774
2775                         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));                      
2776                         
2777                         /* Set src */
2778                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
2779                         mono_mb_emit_icon (mb, sizeof (MonoObject));
2780                         mono_mb_emit_byte (mb, CEE_ADD);
2781                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2782
2783                         /* Allocate and set dest */
2784                         mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2785                         mono_mb_emit_byte (mb, CEE_CONV_I);
2786                         mono_mb_emit_native_call (mb, alloc_sig, mono_marshal_alloc);
2787                         emit_thread_interrupt_checkpoint (mb);
2788                         mono_mb_emit_byte (mb, CEE_STLOC_1);
2789
2790                         /* Update argument pointer */
2791                         mono_mb_emit_ldarg (mb, i);
2792                         mono_mb_emit_byte (mb, CEE_LDLOC_1);
2793                         mono_mb_emit_byte (mb, CEE_STIND_I);
2794
2795                         /* emit valuetype conversion code */
2796                         emit_struct_conv (mb, klass, FALSE);
2797
2798                         mono_mb_patch_addr (mb, pos2, mb->pos - (pos2 + 4));
2799                         break;
2800                 }
2801                 case MONO_TYPE_VALUETYPE: {
2802                         int pos2;
2803
2804                         klass = t->data.klass;
2805
2806                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2807                             klass->blittable || klass->enumtype) {
2808                                 break;
2809                         }
2810
2811                         /* Check for null */
2812                         mono_mb_emit_ldarg (mb, i);
2813                         pos2 = mono_mb_emit_branch (mb, CEE_BRFALSE);
2814
2815                         /* Set src */
2816                         mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2817                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2818
2819                         /* Set dest */
2820                         mono_mb_emit_ldarg (mb, i);
2821                         mono_mb_emit_byte (mb, CEE_STLOC_1);
2822
2823                         /* emit valuetype conversion code */
2824                         emit_struct_conv (mb, klass, FALSE);
2825
2826                         mono_mb_patch_addr (mb, pos2, mb->pos - (pos2 + 4));
2827                         break;
2828                 }
2829                 }
2830         }
2831
2832         if (retobj_var) {
2833                 mono_mb_emit_ldloc (mb, retobj_var);
2834                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2835                 mono_mb_emit_byte (mb, CEE_MONO_RETOBJ);
2836                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2837         }
2838         else {
2839                 if (!MONO_TYPE_IS_VOID(sig->ret))
2840                         mono_mb_emit_byte (mb, CEE_LDLOC_3);
2841                 mono_mb_emit_byte (mb, CEE_RET);
2842         }
2843
2844         if (!this)
2845                 res = mono_mb_create_and_cache (cache, method,
2846                                                                                          mb, csig, sig->param_count + 16);
2847         else
2848                 res = mono_mb_create_method (mb, csig, sig->param_count + 16);
2849         mono_mb_free (mb);
2850
2851         /* 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)); */
2852
2853         return res;
2854 }
2855
2856 /*
2857  * mono_marshal_get_ldfld_wrapper:
2858  * @type: the type of the field
2859  *
2860  * This method generates a function which can be use to load a field with type
2861  * @type from an object. The generated function has the following signature:
2862  * <@type> ldfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset)
2863  */
2864 MonoMethod *
2865 mono_marshal_get_ldfld_wrapper (MonoType *type)
2866 {
2867         MonoMethodSignature *sig, *csig;
2868         MonoMethodBuilder *mb;
2869         MonoMethod *res;
2870         MonoClass *klass;
2871         static GHashTable *ldfld_hash = NULL; 
2872         char *name;
2873         int t, pos0, pos1 = 0;
2874
2875         t = type->type;
2876
2877         if (!type->byref) {
2878                 if (type->type == MONO_TYPE_SZARRAY) {
2879                         klass = mono_defaults.array_class;
2880                 } else if (type->type == MONO_TYPE_VALUETYPE) {
2881                         klass = type->data.klass;
2882                         if (klass->enumtype) {
2883                                 t = klass->enum_basetype->type;
2884                                 klass = mono_class_from_mono_type (klass->enum_basetype);
2885                         }
2886                 } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
2887                            t == MONO_TYPE_CLASS) { 
2888                         klass = mono_defaults.object_class;
2889                 } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
2890                         klass = mono_defaults.int_class;
2891                 } else {
2892                         klass = mono_class_from_mono_type (type);                       
2893                 }
2894         } else {
2895                 klass = mono_defaults.int_class;
2896         }
2897
2898         EnterCriticalSection (&marshal_mutex);
2899         if (!ldfld_hash) 
2900                 ldfld_hash = g_hash_table_new (NULL, NULL);
2901         res = g_hash_table_lookup (ldfld_hash, klass);
2902         LeaveCriticalSection (&marshal_mutex);
2903         if (res)
2904                 return res;
2905
2906         name = g_strdup_printf ("__ldfld_wrapper_%s.%s", klass->name_space, klass->name); 
2907         mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_LDFLD);
2908         g_free (name);
2909
2910         mb->method->save_lmf = 1;
2911
2912         sig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
2913         sig->params [0] = &mono_defaults.object_class->byval_arg;
2914         sig->params [1] = &mono_defaults.int_class->byval_arg;
2915         sig->params [2] = &mono_defaults.int_class->byval_arg;
2916         sig->params [3] = &mono_defaults.int_class->byval_arg;
2917         sig->ret = &klass->byval_arg;
2918
2919         mono_mb_emit_ldarg (mb, 0);
2920         pos0 = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
2921
2922         mono_mb_emit_ldarg (mb, 0);
2923         mono_mb_emit_ldarg (mb, 1);
2924         mono_mb_emit_ldarg (mb, 2);
2925
2926         csig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
2927         csig->params [0] = &mono_defaults.object_class->byval_arg;
2928         csig->params [1] = &mono_defaults.int_class->byval_arg;
2929         csig->params [2] = &mono_defaults.int_class->byval_arg;
2930         csig->ret = &klass->this_arg;
2931         csig->pinvoke = 1;
2932
2933         mono_mb_emit_native_call (mb, csig, mono_load_remote_field_new);
2934         emit_thread_interrupt_checkpoint (mb);
2935
2936         if (klass->valuetype) {
2937                 mono_mb_emit_byte (mb, CEE_UNBOX);
2938                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));             
2939                 mono_mb_emit_byte (mb, CEE_BR);
2940                 pos1 = mb->pos;
2941                 mono_mb_emit_i4 (mb, 0);
2942         } else {
2943                 mono_mb_emit_byte (mb, CEE_RET);
2944         }
2945
2946
2947         mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
2948
2949         mono_mb_emit_ldarg (mb, 0);
2950         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2951         mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2952         mono_mb_emit_ldarg (mb, 3);
2953         mono_mb_emit_byte (mb, CEE_ADD);
2954
2955         if (klass->valuetype)
2956                 mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
2957
2958         switch (t) {
2959         case MONO_TYPE_I1:
2960         case MONO_TYPE_U1:
2961         case MONO_TYPE_BOOLEAN:
2962                 mono_mb_emit_byte (mb, CEE_LDIND_I1);
2963                 break;
2964         case MONO_TYPE_CHAR:
2965         case MONO_TYPE_I2:
2966         case MONO_TYPE_U2:
2967                 mono_mb_emit_byte (mb, CEE_LDIND_I2);
2968                 break;
2969         case MONO_TYPE_I4:
2970         case MONO_TYPE_U4:
2971                 mono_mb_emit_byte (mb, CEE_LDIND_I4);
2972                 break;
2973         case MONO_TYPE_I8:
2974         case MONO_TYPE_U8:
2975                 mono_mb_emit_byte (mb, CEE_LDIND_I8);
2976                 break;
2977         case MONO_TYPE_R4:
2978                 mono_mb_emit_byte (mb, CEE_LDIND_R4);
2979                 break;
2980         case MONO_TYPE_R8:
2981                 mono_mb_emit_byte (mb, CEE_LDIND_R8);
2982                 break;
2983         case MONO_TYPE_ARRAY:
2984         case MONO_TYPE_PTR:
2985         case MONO_TYPE_FNPTR:
2986         case MONO_TYPE_SZARRAY:
2987         case MONO_TYPE_OBJECT:
2988         case MONO_TYPE_CLASS:
2989         case MONO_TYPE_STRING:
2990         case MONO_TYPE_I:
2991         case MONO_TYPE_U:
2992                 mono_mb_emit_byte (mb, CEE_LDIND_I);
2993                 break;
2994         case MONO_TYPE_VALUETYPE:
2995                 g_assert (!klass->enumtype);
2996                 mono_mb_emit_byte (mb, CEE_LDOBJ);
2997                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2998                 break;
2999         default:
3000                 g_warning ("type %x not implemented", type->type);
3001                 g_assert_not_reached ();
3002         }
3003
3004         mono_mb_emit_byte (mb, CEE_RET);
3005        
3006         res = mono_mb_create_and_cache (ldfld_hash, klass,
3007                                                                                  mb, sig, sig->param_count + 16);
3008         mono_mb_free (mb);
3009         
3010         return res;
3011 }
3012
3013 /*
3014  * mono_marshal_get_stfld_wrapper:
3015  * @type: the type of the field
3016  *
3017  * This method generates a function which can be use to store a field with type
3018  * @type. The generated function has the following signature:
3019  * void stfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset, <@type> val)
3020  */
3021 MonoMethod *
3022 mono_marshal_get_stfld_wrapper (MonoType *type)
3023 {
3024         MonoMethodSignature *sig, *csig;
3025         MonoMethodBuilder *mb;
3026         MonoMethod *res;
3027         MonoClass *klass;
3028         static GHashTable *stfld_hash = NULL; 
3029         char *name;
3030         int t, pos;
3031
3032         t = type->type;
3033
3034         if (!type->byref) {
3035                 if (type->type == MONO_TYPE_SZARRAY) {
3036                         klass = mono_defaults.array_class;
3037                 } else if (type->type == MONO_TYPE_VALUETYPE) {
3038                         klass = type->data.klass;
3039                         if (klass->enumtype) {
3040                                 t = klass->enum_basetype->type;
3041                                 klass = mono_class_from_mono_type (klass->enum_basetype);
3042                         }
3043                 } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
3044                            t == MONO_TYPE_CLASS) { 
3045                         klass = mono_defaults.object_class;
3046                 } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
3047                         klass = mono_defaults.int_class;
3048                 } else {
3049                         klass = mono_class_from_mono_type (type);                       
3050                 }
3051         } else {
3052                 klass = mono_defaults.int_class;
3053         }
3054
3055         EnterCriticalSection (&marshal_mutex);
3056         if (!stfld_hash) 
3057                 stfld_hash = g_hash_table_new (NULL, NULL);
3058         res = g_hash_table_lookup (stfld_hash, klass);
3059         LeaveCriticalSection (&marshal_mutex);
3060         if (res)
3061                 return res;
3062
3063         name = g_strdup_printf ("__stfld_wrapper_%s.%s", klass->name_space, klass->name); 
3064         mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_STFLD);
3065         g_free (name);
3066
3067         mb->method->save_lmf = 1;
3068
3069         sig = mono_metadata_signature_alloc (mono_defaults.corlib, 5);
3070         sig->params [0] = &mono_defaults.object_class->byval_arg;
3071         sig->params [1] = &mono_defaults.int_class->byval_arg;
3072         sig->params [2] = &mono_defaults.int_class->byval_arg;
3073         sig->params [3] = &mono_defaults.int_class->byval_arg;
3074         sig->params [4] = &klass->byval_arg;
3075         sig->ret = &mono_defaults.void_class->byval_arg;
3076
3077         mono_mb_emit_ldarg (mb, 0);
3078         pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
3079
3080         mono_mb_emit_ldarg (mb, 0);
3081         mono_mb_emit_ldarg (mb, 1);
3082         mono_mb_emit_ldarg (mb, 2);
3083         mono_mb_emit_ldarg (mb, 4);
3084
3085         if (klass->valuetype) {
3086                 mono_mb_emit_byte (mb, CEE_BOX);
3087                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));             
3088         }
3089
3090         csig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
3091         csig->params [0] = &mono_defaults.object_class->byval_arg;
3092         csig->params [1] = &mono_defaults.int_class->byval_arg;
3093         csig->params [2] = &mono_defaults.int_class->byval_arg;
3094         csig->params [3] = &klass->this_arg;
3095         csig->ret = &mono_defaults.void_class->byval_arg;
3096         csig->pinvoke = 1;
3097
3098         mono_mb_emit_native_call (mb, csig, mono_store_remote_field_new);
3099         emit_thread_interrupt_checkpoint (mb);
3100
3101         mono_mb_emit_byte (mb, CEE_RET);
3102
3103         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3104
3105         mono_mb_emit_ldarg (mb, 0);
3106         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3107         mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
3108         mono_mb_emit_ldarg (mb, 3);
3109         mono_mb_emit_byte (mb, CEE_ADD);
3110         mono_mb_emit_ldarg (mb, 4);
3111
3112         switch (t) {
3113         case MONO_TYPE_I1:
3114         case MONO_TYPE_U1:
3115         case MONO_TYPE_BOOLEAN:
3116                 mono_mb_emit_byte (mb, CEE_STIND_I1);
3117                 break;
3118         case MONO_TYPE_CHAR:
3119         case MONO_TYPE_I2:
3120         case MONO_TYPE_U2:
3121                 mono_mb_emit_byte (mb, CEE_STIND_I2);
3122                 break;
3123         case MONO_TYPE_I4:
3124         case MONO_TYPE_U4:
3125                 mono_mb_emit_byte (mb, CEE_STIND_I4);
3126                 break;
3127         case MONO_TYPE_I8:
3128         case MONO_TYPE_U8:
3129                 mono_mb_emit_byte (mb, CEE_STIND_I8);
3130                 break;
3131         case MONO_TYPE_R4:
3132                 mono_mb_emit_byte (mb, CEE_STIND_R4);
3133                 break;
3134         case MONO_TYPE_R8:
3135                 mono_mb_emit_byte (mb, CEE_STIND_R8);
3136                 break;
3137         case MONO_TYPE_ARRAY:
3138         case MONO_TYPE_PTR:
3139         case MONO_TYPE_FNPTR:
3140         case MONO_TYPE_SZARRAY:
3141         case MONO_TYPE_OBJECT:
3142         case MONO_TYPE_CLASS:
3143         case MONO_TYPE_STRING:
3144         case MONO_TYPE_I:
3145         case MONO_TYPE_U:
3146                 mono_mb_emit_byte (mb, CEE_STIND_I);
3147                 break;
3148         case MONO_TYPE_VALUETYPE:
3149                 g_assert (!klass->enumtype);
3150                 mono_mb_emit_byte (mb, CEE_STOBJ);
3151                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3152                 break;
3153         default:
3154                 g_warning ("type %x not implemented", type->type);
3155                 g_assert_not_reached ();
3156         }
3157
3158         mono_mb_emit_byte (mb, CEE_RET);
3159        
3160         res = mono_mb_create_and_cache (stfld_hash, klass,
3161                                                                         mb, sig, sig->param_count + 16);
3162         mono_mb_free (mb);
3163         
3164         return res;
3165 }
3166
3167 /*
3168  * generates IL code for the icall wrapper (the generated method
3169  * calls the unmanaged code in func)
3170  */
3171 MonoMethod *
3172 mono_marshal_get_icall_wrapper (MonoMethodSignature *sig, const char *name, gconstpointer func)
3173 {
3174         MonoMethodSignature *csig;
3175         MonoMethodBuilder *mb;
3176         MonoMethod *res;
3177         int i;
3178         
3179         g_assert (sig->pinvoke);
3180
3181         mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_MANAGED_TO_NATIVE);
3182
3183         mb->method->save_lmf = 1;
3184
3185         /* we copy the signature, so that we can modify it */
3186
3187         if (sig->hasthis)
3188                 mono_mb_emit_byte (mb, CEE_LDARG_0);
3189
3190         for (i = 0; i < sig->param_count; i++)
3191                 mono_mb_emit_ldarg (mb, i + sig->hasthis);
3192
3193         mono_mb_emit_native_call (mb, sig, (gpointer) func);
3194         emit_thread_interrupt_checkpoint (mb);
3195         mono_mb_emit_byte (mb, CEE_RET);
3196
3197         csig = mono_metadata_signature_dup (sig);
3198         csig->pinvoke = 0;
3199
3200         res = mono_mb_create_method (mb, csig, csig->param_count + 16);
3201         mono_mb_free (mb);
3202         
3203         return res;
3204 }
3205
3206 /**
3207  * mono_marshal_get_native_wrapper:
3208  * @method: The MonoMethod to wrap.
3209  *
3210  * generates IL code for the pinvoke wrapper (the generated method
3211  * calls the unmanaged code in method->addr)
3212  */
3213 MonoMethod *
3214 mono_marshal_get_native_wrapper (MonoMethod *method)
3215 {
3216         MonoMethodSignature *sig, *csig;
3217         MonoMethodPInvoke *piinfo;
3218         MonoMethodBuilder *mb;
3219         MonoMarshalSpec **mspecs;
3220         MonoMethod *res;
3221         GHashTable *cache;
3222         MonoClass *klass;
3223         gboolean pinvoke = FALSE;
3224         int i, pos, argnum, *tmp_locals;
3225         int type;
3226         const char *exc_class = "MissingMethodException";
3227         const char *exc_arg = NULL;
3228
3229         g_assert (method != NULL);
3230         g_assert (method->signature->pinvoke);
3231
3232         cache = method->klass->image->native_wrapper_cache;
3233         if ((res = mono_marshal_find_in_cache (cache, method)))
3234                 return res;
3235
3236         sig = method->signature;
3237
3238         if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
3239             (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
3240                 pinvoke = TRUE;
3241
3242         if (!method->addr) {
3243                 if (pinvoke)
3244                         mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
3245                 else
3246                         method->addr = mono_lookup_internal_call (method);
3247         }
3248
3249         mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_MANAGED_TO_NATIVE);
3250
3251         mb->method->save_lmf = 1;
3252
3253         piinfo = (MonoMethodPInvoke *)method;
3254
3255         if (!method->addr) {
3256                 mono_mb_emit_exception (mb, exc_class, exc_arg);
3257                 csig = mono_metadata_signature_dup (sig);
3258                 csig->pinvoke = 0;
3259                 res = mono_mb_create_and_cache (cache, method,
3260                                                                                 mb, csig, csig->param_count + 16);
3261                 mono_mb_free (mb);
3262                 return res;
3263         }
3264
3265         /* internal calls: we simply push all arguments and call the method (no conversions) */
3266         if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
3267
3268                 /* hack - string constructors returns a value */
3269                 if (method->string_ctor) {
3270                         csig = mono_metadata_signature_dup (sig);
3271                         csig->ret = &mono_defaults.string_class->byval_arg;
3272                 } else
3273                         csig = sig;
3274
3275                 if (sig->hasthis)
3276                         mono_mb_emit_byte (mb, CEE_LDARG_0);
3277
3278                 for (i = 0; i < sig->param_count; i++)
3279                         mono_mb_emit_ldarg (mb, i + sig->hasthis);
3280
3281                 g_assert (method->addr);
3282                 mono_mb_emit_native_call (mb, csig, method->addr);
3283                 emit_thread_interrupt_checkpoint (mb);
3284                 mono_mb_emit_byte (mb, CEE_RET);
3285
3286                 csig = mono_metadata_signature_dup (csig);
3287                 csig->pinvoke = 0;
3288                 res = mono_mb_create_and_cache (cache, method,
3289                                                                                 mb, csig, csig->param_count + 16);
3290                 mono_mb_free (mb);
3291                 return res;
3292         }
3293
3294         g_assert (pinvoke);
3295
3296         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
3297         mono_method_get_marshal_info (method, mspecs);
3298
3299         /* pinvoke: we need to convert the arguments if necessary */
3300
3301         /* we copy the signature, so that we can set pinvoke to 0 */
3302         csig = mono_metadata_signature_dup (sig);
3303         csig->pinvoke = 1;
3304
3305         /* we allocate local for use with emit_struct_conv() */
3306         /* allocate local 0 (pointer) src_ptr */
3307         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3308         /* allocate local 1 (pointer) dst_ptr */
3309         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3310         /* allocate local 2 (boolean) delete_old */
3311         mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
3312
3313         /* delete_old = FALSE */
3314         mono_mb_emit_icon (mb, 0);
3315         mono_mb_emit_byte (mb, CEE_STLOC_2);
3316
3317         if (!MONO_TYPE_IS_VOID(sig->ret)) {
3318                 /* allocate local 3 to store the return value */
3319                 mono_mb_add_local (mb, sig->ret);
3320         }
3321
3322         if (mspecs [0] && mspecs [0]->native == MONO_NATIVE_CUSTOM) {
3323                 /* Return type custom marshaling */
3324                 /*
3325                  * Since we can't determine the return type of the unmanaged function,
3326                  * we assume it returns a pointer, and pass that pointer to
3327                  * MarshalNativeToManaged.
3328                  */
3329                 csig->ret = &mono_defaults.int_class->byval_arg;
3330         }
3331
3332         /* we first do all conversions */
3333         tmp_locals = alloca (sizeof (int) * sig->param_count);
3334
3335         for (i = 0; i < sig->param_count; i ++) {
3336                 MonoType *t = sig->params [i];
3337                 MonoMarshalSpec *spec = mspecs [i + 1];
3338
3339                 argnum = i + sig->hasthis;
3340                 tmp_locals [i] = 0;
3341
3342                 /* Ensure that we have marshalling info for this param */
3343                 mono_marshal_load_type_info (mono_class_from_mono_type (t));
3344
3345                 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
3346                         MonoType *mtype;
3347                         MonoClass *mklass;
3348                         MonoMethod *marshal_managed_to_native;
3349                         MonoMethod *get_instance;
3350
3351                         /* FIXME: Call CleanUpNativeData after the call */
3352
3353                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
3354                         g_assert (mtype != NULL);
3355                         mklass = mono_class_from_mono_type (mtype);
3356                         g_assert (mklass != NULL);
3357
3358                         marshal_managed_to_native = mono_find_method_by_name (mklass, "MarshalManagedToNative", 1);
3359                         g_assert (marshal_managed_to_native);
3360                         get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
3361                         g_assert (get_instance);
3362                         
3363                         switch (t->type) {
3364                         case MONO_TYPE_CLASS:
3365                         case MONO_TYPE_OBJECT:
3366                         case MONO_TYPE_STRING:
3367                         case MONO_TYPE_ARRAY:
3368                         case MONO_TYPE_SZARRAY:
3369                         case MONO_TYPE_VALUETYPE:
3370                                 if (t->byref)
3371                                         break;
3372
3373                                 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3374
3375                                 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
3376
3377                                 mono_mb_emit_byte (mb, CEE_CALL);
3378                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
3379                                 
3380                                 mono_mb_emit_ldarg (mb, argnum);
3381
3382                                 if (t->type == MONO_TYPE_VALUETYPE) {
3383                                         /*
3384                                          * Since we can't determine the type of the argument, we
3385                                          * will assume the unmanaged function takes a pointer.
3386                                          */
3387                                         csig->params [i] = &mono_defaults.int_class->byval_arg;
3388
3389                                         mono_mb_emit_byte (mb, CEE_BOX);
3390                                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (t)));
3391                                 }
3392
3393                                 mono_mb_emit_byte (mb, CEE_CALLVIRT);
3394                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_managed_to_native));
3395
3396                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
3397                                 break;
3398
3399                         default:
3400                                 g_warning ("custom marshalling of type %x is currently not supported", t->type);
3401                                 g_assert_not_reached ();
3402                                 break;
3403                         }
3404                         continue;
3405                 }
3406
3407                 if (spec && spec->native == MONO_NATIVE_ASANY) {
3408                         MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, NULL);
3409
3410                         g_assert (t->type == MONO_TYPE_OBJECT);
3411                         g_assert (!t->byref);
3412
3413                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3414                         mono_mb_emit_ldarg (mb, argnum);
3415                         mono_mb_emit_icon (mb, encoding);
3416                         mono_mb_emit_icall (mb, mono_marshal_asany);
3417                         mono_mb_emit_stloc (mb, tmp_locals [i]);
3418                         continue;
3419                 }
3420                         
3421                 switch (t->type) {
3422                 case MONO_TYPE_VALUETYPE:                       
3423                         klass = t->data.klass;
3424
3425                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3426                             klass->blittable || klass->enumtype)
3427                                 break;
3428
3429                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3430                         
3431                         /* store the address of the source into local variable 0 */
3432                         if (t->byref)
3433                                 mono_mb_emit_ldarg (mb, argnum);
3434                         else
3435                                 mono_mb_emit_ldarg_addr (mb, argnum);
3436
3437                         mono_mb_emit_byte (mb, CEE_STLOC_0);
3438                         
3439                         /* allocate space for the native struct and
3440                          * store the address into local variable 1 (dest) */
3441                         mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
3442                         mono_mb_emit_byte (mb, CEE_PREFIX1);
3443                         mono_mb_emit_byte (mb, CEE_LOCALLOC);
3444                         mono_mb_emit_stloc (mb, tmp_locals [i]);
3445
3446                         if (t->byref) {
3447                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3448                                 mono_mb_emit_byte (mb, CEE_BRFALSE);
3449                                 pos = mb->pos;
3450                                 mono_mb_emit_i4 (mb, 0);
3451                         }
3452
3453                         /* set dst_ptr */
3454                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
3455                         mono_mb_emit_byte (mb, CEE_STLOC_1);
3456
3457                         /* emit valuetype conversion code */
3458                         emit_struct_conv (mb, klass, FALSE);
3459                         
3460                         if (t->byref)
3461                                 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3462                         break;
3463                 case MONO_TYPE_STRING: {
3464                         MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, spec);
3465
3466                         csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3467                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3468
3469                         if (t->byref) {
3470                                 if (t->attrs & PARAM_ATTRIBUTE_OUT)
3471                                         break;
3472
3473                                 mono_mb_emit_ldarg (mb, argnum);
3474                                 mono_mb_emit_byte (mb, CEE_LDIND_I);                            
3475                         } else {
3476                                 mono_mb_emit_ldarg (mb, argnum);
3477                         }
3478
3479                         switch (encoding) {
3480                         case MONO_NATIVE_LPWSTR:
3481                                 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_STR_LPWSTR));
3482                                 break;
3483                         case MONO_NATIVE_LPSTR:
3484                                 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_STR_LPSTR));
3485                                 break;
3486                         case MONO_NATIVE_LPTSTR:
3487                                 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_STR_LPTSTR));
3488                                 break;
3489                         default: {
3490                                         char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding);
3491                                         MonoException *exc = mono_get_exception_not_implemented (msg);
3492                                         g_warning (msg);
3493                                         g_free (msg);
3494                                         mono_raise_exception (exc);
3495                                 }
3496                         }
3497
3498                         mono_mb_emit_stloc (mb, tmp_locals [i]);
3499                         break;
3500                 }
3501                 case MONO_TYPE_CLASS:
3502                 case MONO_TYPE_OBJECT:
3503                         klass = t->data.klass;
3504
3505                         csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3506                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3507
3508                         if (klass->delegate) {
3509                                 g_assert (!t->byref);
3510                                 mono_mb_emit_ldarg (mb, argnum);
3511                                 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN));
3512                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
3513                         } else if (klass == mono_defaults.stringbuilder_class) {
3514                                 MonoMarshalNative encoding = mono_marshal_get_stringbuilder_to_ptr_encoding (piinfo, spec);
3515
3516                                 g_assert (!t->byref);
3517                                 mono_mb_emit_ldarg (mb, argnum);
3518
3519                                 if (encoding != -1)
3520                                         mono_mb_emit_icall (mb, conv_to_icall (encoding));
3521                                 else {
3522                                         char *msg = g_strdup_printf ("stringbuilder marshalling conversion %d not implemented", encoding);
3523                                         MonoException *exc = mono_get_exception_not_implemented (msg);
3524                                         g_warning (msg);
3525                                         g_free (msg);
3526                                         mono_raise_exception (exc);
3527                                 }
3528
3529                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
3530                         } else {
3531                                 mono_mb_emit_byte (mb, CEE_LDNULL);
3532                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
3533
3534                                 if (t->byref) {
3535                                         /* we dont need any conversions for out parameters */
3536                                         if (t->attrs & PARAM_ATTRIBUTE_OUT)
3537                                                 break;
3538
3539                                         mono_mb_emit_ldarg (mb, argnum);                                
3540                                         mono_mb_emit_byte (mb, CEE_LDIND_I);
3541
3542                                 } else {
3543                                         mono_mb_emit_ldarg (mb, argnum);
3544                                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3545                                         mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
3546                                 }
3547                                 
3548                                 /* store the address of the source into local variable 0 */
3549                                 mono_mb_emit_byte (mb, CEE_STLOC_0);
3550                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3551                                 mono_mb_emit_byte (mb, CEE_BRFALSE);
3552                                 pos = mb->pos;
3553                                 mono_mb_emit_i4 (mb, 0);
3554
3555                                 /* allocate space for the native struct and store the address */
3556                                 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
3557                                 mono_mb_emit_byte (mb, CEE_PREFIX1);
3558                                 mono_mb_emit_byte (mb, CEE_LOCALLOC);
3559                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
3560                                 
3561                                 /* set the src_ptr */
3562                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3563                                 mono_mb_emit_icon (mb, sizeof (MonoObject));
3564                                 mono_mb_emit_byte (mb, CEE_ADD);
3565                                 mono_mb_emit_byte (mb, CEE_STLOC_0);
3566
3567                                 /* set dst_ptr */
3568                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3569                                 mono_mb_emit_byte (mb, CEE_STLOC_1);
3570
3571                                 /* emit valuetype conversion code */
3572                                 emit_struct_conv (mb, klass, FALSE);
3573
3574                                 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3575                         }
3576
3577                         break;
3578                 case MONO_TYPE_ARRAY:
3579                 case MONO_TYPE_SZARRAY:
3580                         if (t->byref)
3581                                 continue;
3582
3583                         klass = mono_class_from_mono_type (t);
3584
3585                         csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3586                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3587
3588                         if (klass->element_class == mono_defaults.string_class) {
3589                                 MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, spec);
3590
3591                                 mono_mb_emit_ldarg (mb, argnum);
3592
3593                                 switch (encoding) {
3594                                 case MONO_NATIVE_LPSTR:
3595                                         mono_mb_emit_icall (mb, mono_marshal_string_array);
3596                                         break;
3597                                 case MONO_NATIVE_LPWSTR:
3598                                         mono_mb_emit_icall (mb, mono_marshal_string_array_to_unicode);
3599                                         break;
3600                                 default: {
3601                                         char *msg = g_strdup_printf ("string array marshalling conversion %d not implemented", encoding);
3602                                         MonoException *exc = mono_get_exception_not_implemented (msg);
3603                                         g_warning (msg);
3604                                         g_free (msg);
3605                                         mono_raise_exception (exc);
3606                                 }
3607                                 }
3608                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
3609                         }
3610                         else if (klass->element_class->blittable) {
3611                                 mono_mb_emit_ldarg (mb, argnum);
3612                                 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_ARRAY_LPARRAY));
3613                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
3614                         }
3615                         else {
3616                                 MonoClass *eklass;
3617                                 guint32 label1, label2, label3;
3618                                 int index_var, dest_ptr, esize;
3619                                 MonoMarshalNative encoding = mono_marshal_get_stringbuilder_to_ptr_encoding (piinfo, spec);
3620
3621                                 dest_ptr = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3622
3623                                 eklass = klass->element_class;
3624
3625                                 /* Check null */
3626                                 mono_mb_emit_ldarg (mb, argnum);
3627                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
3628                                 mono_mb_emit_ldarg (mb, argnum);
3629                                 mono_mb_emit_byte (mb, CEE_BRFALSE);
3630                                 label1 = mb->pos;
3631                                 mono_mb_emit_i4 (mb, 0);
3632
3633                                 if (eklass == mono_defaults.stringbuilder_class) {
3634                                         if (encoding == -1) {
3635                                                 char *msg = g_strdup_printf ("stringbuilder marshalling conversion %d not implemented", encoding);
3636                                                 MonoException *exc = mono_get_exception_not_implemented (msg);
3637                                                 g_warning (msg);
3638                                                 g_free (msg);
3639                                                 mono_raise_exception (exc);
3640                                         }
3641                                 }
3642
3643                                 if (eklass == mono_defaults.stringbuilder_class)
3644                                         esize = sizeof (gpointer);
3645                                 else
3646                                         esize = mono_class_native_size (eklass, NULL);
3647
3648                                 /* allocate space for the native struct and store the address */
3649                                 mono_mb_emit_icon (mb, esize);
3650                                 mono_mb_emit_ldarg (mb, argnum);
3651                                 mono_mb_emit_byte (mb, CEE_LDLEN);
3652                                 mono_mb_emit_byte (mb, CEE_MUL);
3653                                 mono_mb_emit_byte (mb, CEE_PREFIX1);
3654                                 mono_mb_emit_byte (mb, CEE_LOCALLOC);
3655                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
3656
3657                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3658                                 mono_mb_emit_stloc (mb, dest_ptr);
3659
3660                                 /* Emit marshalling loop */
3661                                 index_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);                                
3662                                 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
3663                                 mono_mb_emit_stloc (mb, index_var);
3664                                 label2 = mb->pos;
3665                                 mono_mb_emit_ldloc (mb, index_var);
3666                                 mono_mb_emit_ldarg (mb, argnum);
3667                                 mono_mb_emit_byte (mb, CEE_LDLEN);
3668                                 mono_mb_emit_byte (mb, CEE_BGE);
3669                                 label3 = mb->pos;
3670                                 mono_mb_emit_i4 (mb, 0);
3671
3672                                 /* Emit marshalling code */
3673
3674                                 if (eklass == mono_defaults.stringbuilder_class) {
3675                                         mono_mb_emit_ldloc (mb, dest_ptr);
3676                                         mono_mb_emit_ldarg (mb, argnum);
3677                                         mono_mb_emit_ldloc (mb, index_var);
3678                                         mono_mb_emit_byte (mb, CEE_LDELEM_REF);
3679                                         mono_mb_emit_icall (mb, conv_to_icall (encoding));
3680                                         mono_mb_emit_byte (mb, CEE_STIND_I);
3681                                 }
3682                                 else {
3683                                         /* set the src_ptr */
3684                                         mono_mb_emit_ldarg (mb, argnum);
3685                                         mono_mb_emit_ldloc (mb, index_var);
3686                                         mono_mb_emit_byte (mb, CEE_LDELEMA);
3687                                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eklass));
3688                                         mono_mb_emit_byte (mb, CEE_STLOC_0);
3689
3690                                         /* set dst_ptr */
3691                                         mono_mb_emit_ldloc (mb, dest_ptr);
3692                                         mono_mb_emit_byte (mb, CEE_STLOC_1);
3693
3694                                         /* emit valuetype conversion code */
3695                                         emit_struct_conv (mb, eklass, FALSE);
3696                                 }
3697
3698                                 mono_mb_emit_add_to_local (mb, index_var, 1);
3699                                 mono_mb_emit_add_to_local (mb, dest_ptr, esize);
3700
3701                                 mono_mb_emit_byte (mb, CEE_BR);
3702                                 mono_mb_emit_i4 (mb, label2 - (mb->pos + 4));
3703
3704                                 mono_mb_patch_addr (mb, label1, mb->pos - (label1 + 4));
3705                                 mono_mb_patch_addr (mb, label3, mb->pos - (label3 + 4));
3706                         }
3707
3708                         break;
3709                 case MONO_TYPE_BOOLEAN: {
3710                         MonoType *local_type;
3711                         int variant_bool = 0;
3712                         if (!t->byref)
3713                                 continue;
3714                         if (spec == NULL) {
3715                                 local_type = &mono_defaults.int32_class->byval_arg;
3716                         } else {
3717                                 switch (spec->native) {
3718                                 case MONO_NATIVE_I1:
3719                                         local_type = &mono_defaults.byte_class->byval_arg;
3720                                         break;
3721                                 case MONO_NATIVE_VARIANTBOOL:
3722                                         local_type = &mono_defaults.int16_class->byval_arg;
3723                                         variant_bool = 1;
3724                                         break;
3725                                 default:
3726                                         g_warning ("marshalling bool as native type %x is currently not supported", spec->native);
3727                                 break;
3728                                 }
3729                         }
3730                         csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3731                         tmp_locals [i] = mono_mb_add_local (mb, local_type);
3732                         mono_mb_emit_ldarg (mb, argnum);
3733                         mono_mb_emit_byte (mb, CEE_LDIND_I1);
3734                         if (variant_bool)
3735                                 mono_mb_emit_byte (mb, CEE_NEG);
3736                         mono_mb_emit_stloc (mb, tmp_locals [i]);
3737                         break;
3738                 }
3739                 }
3740         }
3741
3742         /* push all arguments */
3743
3744         if (sig->hasthis)
3745                 mono_mb_emit_byte (mb, CEE_LDARG_0);
3746
3747         for (i = 0; i < sig->param_count; i++) {
3748                 MonoType *t = sig->params [i];
3749                 MonoMarshalSpec *spec = mspecs [i + 1];
3750
3751                 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
3752                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
3753                 }
3754                 else
3755                 if (spec && spec->native == MONO_NATIVE_ASANY) {
3756                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
3757                 }
3758                 else {
3759                         argnum = i + sig->hasthis;
3760
3761                         switch (t->type) {
3762                         case MONO_TYPE_BOOLEAN:
3763                                 if (t->byref) {
3764                                         g_assert (tmp_locals [i]);
3765                                         mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
3766                                 } else
3767                                         mono_mb_emit_ldarg (mb, argnum);
3768                                 break;
3769                         case MONO_TYPE_I1:
3770                         case MONO_TYPE_U1:
3771                         case MONO_TYPE_I2:
3772                         case MONO_TYPE_U2:
3773                         case MONO_TYPE_I4:
3774                         case MONO_TYPE_U4:
3775                         case MONO_TYPE_I:
3776                         case MONO_TYPE_U:
3777                         case MONO_TYPE_PTR:
3778                         case MONO_TYPE_R4:
3779                         case MONO_TYPE_R8:
3780                         case MONO_TYPE_I8:
3781                         case MONO_TYPE_U8:
3782                                 mono_mb_emit_ldarg (mb, argnum);
3783                                 break;
3784                         case MONO_TYPE_VALUETYPE:
3785                                 klass = sig->params [i]->data.klass;
3786                                 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3787                                         klass->blittable || klass->enumtype) {
3788                                         mono_mb_emit_ldarg (mb, argnum);
3789                                         break;
3790                                 }                       
3791                                 g_assert (tmp_locals [i]);
3792                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3793                                 if (!t->byref) {
3794                                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3795                                         mono_mb_emit_byte (mb, CEE_MONO_LDNATIVEOBJ);
3796                                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3797                                 }
3798                                 break;
3799                         case MONO_TYPE_STRING:
3800                         case MONO_TYPE_CLASS:
3801                         case MONO_TYPE_OBJECT:
3802                                 g_assert (tmp_locals [i]);
3803                                 if (t->byref) 
3804                                         mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
3805                                 else
3806                                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
3807                                 break;
3808                         case MONO_TYPE_CHAR:
3809                                 /* fixme: dont know how to marshal that. We cant simply
3810                                  * convert it to a one byte UTF8 character, because an
3811                                  * unicode character may need more that one byte in UTF8 */
3812                                 mono_mb_emit_ldarg (mb, argnum);
3813                                 break;
3814                         case MONO_TYPE_ARRAY:
3815                         case MONO_TYPE_SZARRAY:
3816                                 if (t->byref) {
3817                                         mono_mb_emit_ldarg (mb, argnum);
3818                                 } else {
3819                                         g_assert (tmp_locals [i]);
3820                                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
3821                                 }
3822                                 break;
3823                         case MONO_TYPE_TYPEDBYREF:
3824                         case MONO_TYPE_FNPTR:
3825                         default:
3826                                 g_warning ("type 0x%02x unknown", t->type);     
3827                                 g_assert_not_reached ();
3828                         }
3829                 }
3830         }                       
3831
3832         /* call the native method */
3833         mono_mb_emit_native_call (mb, csig, method->addr);
3834
3835         /* Set LastError if needed */
3836         if (piinfo->piflags & PINVOKE_ATTRIBUTE_SUPPORTS_LAST_ERROR) {
3837                 MonoMethodSignature *lasterr_sig;
3838
3839                 lasterr_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
3840                 lasterr_sig->ret = &mono_defaults.void_class->byval_arg;
3841                 lasterr_sig->pinvoke = 1;
3842
3843                 mono_mb_emit_native_call (mb, lasterr_sig, mono_marshal_set_last_error);
3844         }               
3845
3846         /* Ensure that we have marshalling info for the return */
3847         mono_marshal_load_type_info (mono_class_from_mono_type (sig->ret));
3848
3849         /* convert the result */
3850         if (!sig->ret->byref) {
3851                 MonoMarshalSpec *spec = mspecs [0];
3852                 type = sig->ret->type;
3853
3854                 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
3855                         MonoType *mtype;
3856                         MonoClass *mklass;
3857                         MonoMethod *marshal_native_to_managed;
3858                         MonoMethod *get_instance;
3859
3860                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
3861                         g_assert (mtype != NULL);
3862                         mklass = mono_class_from_mono_type (mtype);
3863                         g_assert (mklass != NULL);
3864
3865                         marshal_native_to_managed = mono_find_method_by_name (mklass, "MarshalNativeToManaged", 1);
3866                         g_assert (marshal_native_to_managed);
3867                         get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
3868                         g_assert (get_instance);
3869                         
3870                         switch (type) {
3871                         case MONO_TYPE_CLASS:
3872                         case MONO_TYPE_OBJECT:
3873                         case MONO_TYPE_STRING:
3874                         case MONO_TYPE_ARRAY:
3875                         case MONO_TYPE_SZARRAY:
3876                         case MONO_TYPE_VALUETYPE:
3877                                 if (type == MONO_TYPE_VALUETYPE) {
3878                                         /* local 3 can't hold a pointer */
3879                                         mono_mb_emit_byte (mb, CEE_STLOC_0);
3880                                 }
3881                                 else
3882                                         mono_mb_emit_byte (mb, CEE_STLOC_3);
3883
3884                                 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
3885
3886                                 mono_mb_emit_byte (mb, CEE_CALL);
3887                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
3888
3889                                 if (type == MONO_TYPE_VALUETYPE)
3890                                         mono_mb_emit_byte (mb, CEE_LDLOC_0);
3891                                 else
3892                                         mono_mb_emit_byte (mb, CEE_LDLOC_3);
3893                                 
3894                                 mono_mb_emit_byte (mb, CEE_CALLVIRT);
3895                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_native_to_managed));
3896                                 
3897                                 if (type == MONO_TYPE_VALUETYPE) {
3898                                         mono_mb_emit_byte (mb, CEE_UNBOX);
3899                                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (sig->ret)));
3900                                 }
3901                                 mono_mb_emit_byte (mb, CEE_STLOC_3);
3902                                 break;
3903                         default:
3904                                 g_warning ("custom marshalling of type %x is currently not supported", type);
3905                                 g_assert_not_reached ();
3906                                 break;
3907                         }
3908                 } else {
3909
3910                 handle_enum:
3911                         switch (type) {
3912                         case MONO_TYPE_VOID:
3913                                 break;
3914                         case MONO_TYPE_I1:
3915                         case MONO_TYPE_U1:
3916                         case MONO_TYPE_I2:
3917                         case MONO_TYPE_U2:
3918                         case MONO_TYPE_I4:
3919                         case MONO_TYPE_U4:
3920                         case MONO_TYPE_I:
3921                         case MONO_TYPE_U:
3922                         case MONO_TYPE_PTR:
3923                         case MONO_TYPE_R4:
3924                         case MONO_TYPE_R8:
3925                         case MONO_TYPE_I8:
3926                         case MONO_TYPE_U8:
3927                                 /* no conversions necessary */
3928                                 mono_mb_emit_byte (mb, CEE_STLOC_3);
3929                                 break;
3930                         case MONO_TYPE_BOOLEAN:
3931                                 /* maybe we need to make sure that it fits within 8 bits */
3932                                 mono_mb_emit_byte (mb, CEE_STLOC_3);
3933                                 break;
3934                         case MONO_TYPE_VALUETYPE:
3935                                 klass = sig->ret->data.klass;
3936                                 if (klass->enumtype) {
3937                                         type = sig->ret->data.klass->enum_basetype->type;
3938                                         goto handle_enum;
3939                                 }
3940
3941                                 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3942                                     klass->blittable) {
3943                                         mono_mb_emit_byte (mb, CEE_STLOC_3);
3944                                         break;
3945                                 }
3946                                 /* load pointer to returned value type */
3947                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3948                                 mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
3949                                 /* store the address of the source into local variable 0 */
3950                                 mono_mb_emit_byte (mb, CEE_STLOC_0);
3951                                 /* set dst_ptr */
3952                                 mono_mb_emit_ldloc_addr (mb, 3);
3953                                 mono_mb_emit_byte (mb, CEE_STLOC_1);
3954                                 
3955                                 /* emit valuetype conversion code */
3956                                 emit_struct_conv (mb, sig->ret->data.klass, TRUE);
3957                                 break;
3958                         case MONO_TYPE_STRING:
3959                                 mono_mb_emit_byte (mb, CEE_STLOC_0);
3960                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3961                                 
3962                                 if (spec) {
3963                                         switch (spec->native) {
3964                                         case MONO_NATIVE_LPWSTR:
3965                                                 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_LPWSTR_STR));
3966                                                 break;
3967                                         default:
3968                                                 g_warning ("marshalling conversion not implemented");
3969                                                 g_assert_not_reached ();
3970                                         }
3971                                 } else {
3972                                         mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_LPSTR_STR));
3973                                 }
3974                                 mono_mb_emit_byte (mb, CEE_STLOC_3);
3975
3976                                 /* free the string */
3977                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3978                                 mono_mb_emit_icall (mb, g_free);
3979                                 break;
3980                         case MONO_TYPE_CLASS:
3981                         case MONO_TYPE_OBJECT:
3982                                 klass = sig->ret->data.klass;
3983
3984                                 /* set src */
3985                                 mono_mb_emit_byte (mb, CEE_STLOC_0);
3986
3987                                 mono_mb_emit_byte (mb, CEE_LDNULL);
3988                                 mono_mb_emit_byte (mb, CEE_STLOC_3);
3989
3990
3991                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3992                                 mono_mb_emit_byte (mb, CEE_BRFALSE);
3993                                 pos = mb->pos;
3994                                 mono_mb_emit_i4 (mb, 0);
3995
3996                                 /* allocate result object */
3997
3998                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3999                                 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);        
4000                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
4001                                 mono_mb_emit_byte (mb, CEE_STLOC_3);
4002                                 
4003                                 /* set dst  */
4004
4005                                 mono_mb_emit_byte (mb, CEE_LDLOC_3);
4006                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4007                                 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
4008                                 mono_mb_emit_icon (mb, sizeof (MonoObject));
4009                                 mono_mb_emit_byte (mb, CEE_ADD);
4010                                 mono_mb_emit_byte (mb, CEE_STLOC_1);
4011                                                         
4012                                 /* emit conversion code */
4013                                 emit_struct_conv (mb, klass, TRUE);
4014
4015                                 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
4016                                 break;
4017                         case MONO_TYPE_ARRAY:
4018                         case MONO_TYPE_SZARRAY:
4019                                 /* fixme: we need conversions here */
4020                                 mono_mb_emit_byte (mb, CEE_STLOC_3);
4021                                 break;
4022                         case MONO_TYPE_CHAR:
4023                                 /* fixme: we need conversions here */
4024                                 mono_mb_emit_byte (mb, CEE_STLOC_3);
4025                                 break;
4026                         case MONO_TYPE_TYPEDBYREF:
4027                         case MONO_TYPE_FNPTR:
4028                         default:
4029                                 g_warning ("return type 0x%02x unknown", sig->ret->type);       
4030                                 g_assert_not_reached ();
4031                         }
4032                 }
4033         } else {
4034                 mono_mb_emit_byte (mb, CEE_STLOC_3);
4035         }
4036
4037         /* 
4038          * Need to call this after converting the result since MONO_VTADDR needs 
4039          * to be adjacent to the call instruction.
4040          */
4041         emit_thread_interrupt_checkpoint (mb);
4042
4043         /* we need to convert byref arguments back and free string arrays */
4044         for (i = 0; i < sig->param_count; i++) {
4045                 MonoType *t = sig->params [i];
4046                 MonoMarshalSpec *spec = mspecs [i + 1];
4047
4048                 argnum = i + sig->hasthis;
4049
4050                 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
4051                         MonoType *mtype;
4052                         MonoClass *mklass;
4053                         MonoMethod *get_instance;
4054                         MonoMethod *cleanup_native;
4055
4056                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
4057                         g_assert (mtype != NULL);
4058                         mklass = mono_class_from_mono_type (mtype);
4059                         g_assert (mklass != NULL);
4060
4061                         get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
4062                         g_assert (get_instance);
4063                         cleanup_native = mono_find_method_by_name (mklass, "CleanUpNativeData", 1);
4064                         g_assert (get_instance);
4065                         
4066                         switch (t->type) {
4067                         case MONO_TYPE_CLASS:
4068                         case MONO_TYPE_OBJECT:
4069                         case MONO_TYPE_STRING:
4070                         case MONO_TYPE_ARRAY:
4071                         case MONO_TYPE_SZARRAY:
4072                         case MONO_TYPE_VALUETYPE:
4073                                 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
4074
4075                                 mono_mb_emit_byte (mb, CEE_CALL);
4076                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
4077                                 
4078                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4079
4080                                 mono_mb_emit_byte (mb, CEE_CALLVIRT);
4081                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, cleanup_native));
4082
4083                                 break;
4084
4085                         default:
4086                                 g_warning ("custom marshalling of type %x is currently not supported", t->type);
4087                                 g_assert_not_reached ();
4088                                 break;
4089                         }
4090                         continue;
4091                 }
4092
4093                 if (spec && spec->native == MONO_NATIVE_ASANY) {
4094                         MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, NULL);
4095
4096                         mono_mb_emit_ldarg (mb, argnum);
4097                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
4098                         mono_mb_emit_icon (mb, encoding);
4099                         mono_mb_emit_icall (mb, mono_marshal_free_asany);
4100                         continue;
4101                 }
4102                 
4103                 switch (t->type) {
4104                 case MONO_TYPE_STRING:
4105                         if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT)) {
4106                                 mono_mb_emit_ldarg (mb, argnum);
4107                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4108                                 mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_CONV_LPSTR_STR));
4109                                 mono_mb_emit_byte (mb, CEE_STIND_I);            
4110                         } else {
4111                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4112                                 mono_mb_emit_icall (mb, g_free);
4113                         }
4114                         break;
4115                 case MONO_TYPE_CLASS:
4116                 case MONO_TYPE_OBJECT:                  
4117                         if (t->data.klass == mono_defaults.stringbuilder_class) {
4118                                 gboolean need_free;
4119                                 MonoMarshalNative encoding;
4120
4121                                 encoding = mono_marshal_get_ptr_to_stringbuilder_encoding (piinfo, spec, &need_free);
4122
4123                                 g_assert (!t->byref);
4124                                 g_assert (encoding != -1);
4125
4126                                 mono_mb_emit_ldarg (mb, argnum);
4127                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4128
4129                                 mono_mb_emit_icall (mb, conv_to_icall (encoding));
4130
4131                                 if (need_free) {
4132                                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
4133                                         mono_mb_emit_icall (mb, g_free);
4134                                 }
4135                                 break;
4136                         }
4137                         
4138                         if (!(t->byref || (t->attrs & PARAM_ATTRIBUTE_OUT)))
4139                                 continue;
4140
4141                         if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT)) {
4142                                 /* allocate a new object new object */
4143                                 mono_mb_emit_ldarg (mb, argnum);
4144                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4145                                 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);        
4146                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
4147                                 mono_mb_emit_byte (mb, CEE_STIND_I);
4148                         }
4149
4150                         /* dst = *argument */
4151                         mono_mb_emit_ldarg (mb, argnum);
4152
4153                         if (t->byref)
4154                                 mono_mb_emit_byte (mb, CEE_LDIND_I);
4155
4156                         mono_mb_emit_byte (mb, CEE_STLOC_1);
4157
4158                         mono_mb_emit_byte (mb, CEE_LDLOC_1);
4159                         mono_mb_emit_byte (mb, CEE_BRFALSE);
4160                         pos = mb->pos;
4161                         mono_mb_emit_i4 (mb, 0);
4162
4163                         mono_mb_emit_byte (mb, CEE_LDLOC_1);
4164                         mono_mb_emit_icon (mb, sizeof (MonoObject));
4165                         mono_mb_emit_byte (mb, CEE_ADD);
4166                         mono_mb_emit_byte (mb, CEE_STLOC_1);
4167                         
4168                         /* src = tmp_locals [i] */
4169                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
4170                         mono_mb_emit_byte (mb, CEE_STLOC_0);
4171
4172                         /* emit valuetype conversion code */
4173                         emit_struct_conv (mb, klass, TRUE);
4174
4175                         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
4176                         break;
4177                 case MONO_TYPE_VALUETYPE:
4178                         if (!t->byref)
4179                                 continue;
4180         
4181                         klass = t->data.klass;
4182                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
4183                             klass->blittable || klass->enumtype)
4184                                 break;
4185
4186                         /* dst = argument */
4187                         mono_mb_emit_ldarg (mb, argnum);
4188                         mono_mb_emit_byte (mb, CEE_STLOC_1);
4189
4190                         mono_mb_emit_byte (mb, CEE_LDLOC_1);
4191                         mono_mb_emit_byte (mb, CEE_BRFALSE);
4192                         pos = mb->pos;
4193                         mono_mb_emit_i4 (mb, 0);
4194
4195                         /* src = tmp_locals [i] */
4196                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
4197                         mono_mb_emit_byte (mb, CEE_STLOC_0);
4198
4199                         /* emit valuetype conversion code */
4200                         emit_struct_conv (mb, klass, TRUE);
4201                         
4202                         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
4203                         break;
4204                 case MONO_TYPE_SZARRAY:
4205                         if (t->byref)
4206                                 continue;
4207  
4208                         klass = mono_class_from_mono_type (t);
4209
4210                         if (klass->element_class == mono_defaults.string_class) {
4211                                 MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, spec);
4212                                 g_assert (tmp_locals [i]);
4213
4214                                 mono_mb_emit_ldarg (mb, argnum);
4215                                 mono_mb_emit_byte (mb, CEE_BRFALSE);
4216                                 pos = mb->pos;
4217                                 mono_mb_emit_i4 (mb, 0);
4218
4219                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4220
4221                                 switch (encoding) {
4222                                 case MONO_NATIVE_LPWSTR:
4223                                         /* 
4224                                          * The array elements point to the managed string data so 
4225                                          * they don't need to be freed.
4226                                          */
4227                                         mono_mb_emit_icall (mb, g_free);
4228                                         break;
4229                                 default:
4230                                         mono_mb_emit_ldarg (mb, argnum);
4231                                         mono_mb_emit_byte (mb, CEE_LDLEN);                              
4232                                         mono_mb_emit_icall (mb, conv_to_icall (MONO_MARSHAL_FREE_ARRAY));
4233                                         break;                                  
4234                                 }
4235
4236                                 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
4237                         }
4238
4239                         /* Character arrays are implicitly marshalled as [Out] */
4240                         if ((klass->element_class == mono_defaults.char_class) || (klass->element_class == mono_defaults.stringbuilder_class) || (t->attrs & PARAM_ATTRIBUTE_OUT)) {
4241                                 /* FIXME: Optimize blittable case */
4242                                 MonoClass *eklass;
4243                                 guint32 label1, label2, label3;
4244                                 int index_var, src_ptr, esize;
4245
4246                                 eklass = klass->element_class;
4247                                 if (eklass == mono_defaults.stringbuilder_class)
4248                                         esize = sizeof (gpointer);
4249                                 else
4250                                         esize = mono_class_native_size (eklass, NULL);
4251                                 src_ptr = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
4252
4253                                 /* Check null */
4254                                 mono_mb_emit_ldarg (mb, argnum);
4255                                 mono_mb_emit_byte (mb, CEE_BRFALSE);
4256                                 label1 = mb->pos;
4257                                 mono_mb_emit_i4 (mb, 0);
4258
4259                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4260                                 mono_mb_emit_stloc (mb, src_ptr);
4261
4262                                 /* Emit marshalling loop */
4263                                 index_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);                                
4264                                 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
4265                                 mono_mb_emit_stloc (mb, index_var);
4266                                 label2 = mb->pos;
4267                                 mono_mb_emit_ldloc (mb, index_var);
4268                                 mono_mb_emit_ldarg (mb, argnum);
4269                                 mono_mb_emit_byte (mb, CEE_LDLEN);
4270                                 mono_mb_emit_byte (mb, CEE_BGE);
4271                                 label3 = mb->pos;
4272                                 mono_mb_emit_i4 (mb, 0);
4273
4274                                 /* Emit marshalling code */
4275
4276                                 if (eklass == mono_defaults.stringbuilder_class) {
4277                                         gboolean need_free;
4278                                         MonoMarshalNative encoding = mono_marshal_get_ptr_to_stringbuilder_encoding (piinfo, spec, &need_free);
4279
4280                                         g_assert (encoding != -1);
4281
4282                                         /* dest */
4283                                         mono_mb_emit_ldarg (mb, argnum);
4284                                         mono_mb_emit_ldloc (mb, index_var);
4285                                         mono_mb_emit_byte (mb, CEE_LDELEM_REF);
4286
4287                                         /* src */
4288                                         mono_mb_emit_ldloc (mb, src_ptr);
4289                                         mono_mb_emit_byte (mb, CEE_LDIND_I);
4290
4291                                         mono_mb_emit_icall (mb, conv_to_icall (encoding));
4292
4293                                         if (need_free) {
4294                                                 /* src */
4295                                                 mono_mb_emit_ldloc (mb, src_ptr);
4296                                                 mono_mb_emit_byte (mb, CEE_LDIND_I);
4297
4298                                                 mono_mb_emit_icall (mb, g_free);
4299                                         }
4300                                 }
4301                                 else {
4302                                         /* set the src_ptr */
4303                                         mono_mb_emit_ldloc (mb, src_ptr);
4304                                         mono_mb_emit_byte (mb, CEE_STLOC_0);
4305
4306                                         /* set dst_ptr */
4307                                         mono_mb_emit_ldarg (mb, argnum);
4308                                         mono_mb_emit_ldloc (mb, index_var);
4309                                         mono_mb_emit_byte (mb, CEE_LDELEMA);
4310                                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eklass));
4311                                         mono_mb_emit_byte (mb, CEE_STLOC_1);
4312
4313                                         /* emit valuetype conversion code */
4314                                         emit_struct_conv (mb, eklass, TRUE);
4315                                 }
4316
4317                                 mono_mb_emit_add_to_local (mb, index_var, 1);
4318                                 mono_mb_emit_add_to_local (mb, src_ptr, esize);
4319
4320                                 mono_mb_emit_byte (mb, CEE_BR);
4321                                 mono_mb_emit_i4 (mb, label2 - (mb->pos + 4));
4322
4323                                 mono_mb_patch_addr (mb, label1, mb->pos - (label1 + 4));
4324                                 mono_mb_patch_addr (mb, label3, mb->pos - (label3 + 4));
4325                         }
4326                         break;
4327                 case MONO_TYPE_BOOLEAN:
4328                         if (!t->byref)
4329                                 continue;
4330                         mono_mb_emit_ldarg (mb, argnum);
4331                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
4332                         if (mspecs [i + 1] != NULL && mspecs [i + 1]->native == MONO_NATIVE_VARIANTBOOL)
4333                                 mono_mb_emit_byte (mb, CEE_NEG);
4334                         mono_mb_emit_byte (mb, CEE_STIND_I1);
4335                 }
4336         }
4337
4338         if (!MONO_TYPE_IS_VOID(sig->ret))
4339                 mono_mb_emit_byte (mb, CEE_LDLOC_3);
4340
4341         mono_mb_emit_byte (mb, CEE_RET);
4342
4343         csig = mono_metadata_signature_dup (sig);
4344         csig->pinvoke = 0;
4345         res = mono_mb_create_and_cache (cache, method,
4346                                                                         mb, csig, csig->param_count + 16);
4347         mono_mb_free (mb);
4348
4349         for (i = sig->param_count; i >= 0; i--)
4350                 g_free (mspecs [i]);
4351         g_free (mspecs);
4352
4353         /* 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)); */
4354
4355         return res;
4356 }
4357
4358 void
4359 mono_upgrade_remote_class_wrapper (MonoReflectionType *rtype, MonoTransparentProxy *tproxy);
4360
4361 static MonoReflectionType *
4362 type_from_handle (MonoType *handle)
4363 {
4364         MonoDomain *domain = mono_domain_get (); 
4365         MonoClass *klass = mono_class_from_mono_type (handle);
4366
4367         MONO_ARCH_SAVE_REGS;
4368
4369         mono_class_init (klass);
4370         return mono_type_get_object (domain, handle);
4371 }
4372
4373 /*
4374  * mono_marshal_get_isinst:
4375  * @klass: the type of the field
4376  *
4377  * This method generates a function which can be used to check if an object is
4378  * an instance of the given type, icluding the case where the object is a proxy.
4379  * The generated function has the following signature:
4380  * MonoObject* __isinst_wrapper_ (MonoObject *obj)
4381  */
4382 MonoMethod *
4383 mono_marshal_get_isinst (MonoClass *klass)
4384 {
4385         static MonoMethodSignature *isint_sig = NULL;
4386         static GHashTable *isinst_hash = NULL; 
4387         MonoMethod *res;
4388         int pos_was_ok, pos_failed, pos_end, pos_end2;
4389         char *name;
4390         MonoMethodBuilder *mb;
4391
4392         EnterCriticalSection (&marshal_mutex);
4393         if (!isinst_hash) 
4394                 isinst_hash = g_hash_table_new (NULL, NULL);
4395         
4396         res = g_hash_table_lookup (isinst_hash, klass);
4397         LeaveCriticalSection (&marshal_mutex);
4398         if (res)
4399                 return res;
4400
4401         if (!isint_sig) {
4402                 isint_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
4403                 isint_sig->params [0] = &mono_defaults.object_class->byval_arg;
4404                 isint_sig->ret = &mono_defaults.object_class->byval_arg;
4405                 isint_sig->pinvoke = 0;
4406         }
4407         
4408         name = g_strdup_printf ("__isinst_wrapper_%s", klass->name); 
4409         mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_ISINST);
4410         g_free (name);
4411         
4412         mb->method->save_lmf = 1;
4413
4414         /* check if the object is a proxy that needs special cast */
4415         mono_mb_emit_ldarg (mb, 0);
4416         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4417         mono_mb_emit_byte (mb, CEE_MONO_CISINST);
4418         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
4419
4420         /* The result of MONO_ISINST can be:
4421                 0) the type check succeeded
4422                 1) the type check did not succeed
4423                 2) a CanCastTo call is needed */
4424         
4425         mono_mb_emit_byte (mb, CEE_DUP);
4426         pos_was_ok = mono_mb_emit_branch (mb, CEE_BRFALSE);
4427
4428         mono_mb_emit_byte (mb, CEE_LDC_I4_2);
4429         pos_failed = mono_mb_emit_branch (mb, CEE_BNE_UN);
4430         
4431         /* get the real proxy from the transparent proxy*/
4432
4433         mono_mb_emit_ldarg (mb, 0);
4434         mono_mb_emit_managed_call (mb, mono_marshal_get_proxy_cancast (klass), NULL);
4435         pos_end = mono_mb_emit_branch (mb, CEE_BR);
4436         
4437         /* fail */
4438         
4439         mono_mb_patch_addr (mb, pos_failed, mb->pos - (pos_failed + 4));
4440         mono_mb_emit_byte (mb, CEE_LDNULL);
4441         pos_end2 = mono_mb_emit_branch (mb, CEE_BR);
4442         
4443         /* success */
4444         
4445         mono_mb_patch_addr (mb, pos_was_ok, mb->pos - (pos_was_ok + 4));
4446         mono_mb_emit_byte (mb, CEE_POP);
4447         mono_mb_emit_ldarg (mb, 0);
4448         
4449         /* the end */
4450         
4451         mono_mb_patch_addr (mb, pos_end, mb->pos - (pos_end + 4));
4452         mono_mb_patch_addr (mb, pos_end2, mb->pos - (pos_end2 + 4));
4453         mono_mb_emit_byte (mb, CEE_RET);
4454
4455         res = mono_mb_create_and_cache (isinst_hash, klass, mb, isint_sig, isint_sig->param_count + 16);
4456         mono_mb_free (mb);
4457
4458         return res;
4459 }
4460
4461 /*
4462  * mono_marshal_get_castclass:
4463  * @klass: the type of the field
4464  *
4465  * This method generates a function which can be used to cast an object to
4466  * an instance of the given type, icluding the case where the object is a proxy.
4467  * The generated function has the following signature:
4468  * MonoObject* __castclass_wrapper_ (MonoObject *obj)
4469  */
4470 MonoMethod *
4471 mono_marshal_get_castclass (MonoClass *klass)
4472 {
4473         static MonoMethodSignature *castclass_sig = NULL;
4474         static GHashTable *castclass_hash = NULL; 
4475         MonoMethod *res;
4476         int pos_was_ok, pos_was_ok2;
4477         char *name;
4478         MonoMethodBuilder *mb;
4479
4480         EnterCriticalSection (&marshal_mutex);
4481         if (!castclass_hash) 
4482                 castclass_hash = g_hash_table_new (NULL, NULL);
4483         
4484         res = g_hash_table_lookup (castclass_hash, klass);
4485         LeaveCriticalSection (&marshal_mutex);
4486         if (res)
4487                 return res;
4488
4489         if (!castclass_sig) {
4490                 castclass_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
4491                 castclass_sig->params [0] = &mono_defaults.object_class->byval_arg;
4492                 castclass_sig->ret = &mono_defaults.object_class->byval_arg;
4493                 castclass_sig->pinvoke = 0;
4494         }
4495         
4496         name = g_strdup_printf ("__castclass_wrapper_%s", klass->name); 
4497         mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_CASTCLASS);
4498         g_free (name);
4499         
4500         mb->method->save_lmf = 1;
4501
4502         /* check if the object is a proxy that needs special cast */
4503         mono_mb_emit_ldarg (mb, 0);
4504         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4505         mono_mb_emit_byte (mb, CEE_MONO_CCASTCLASS);
4506         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
4507
4508         /* The result of MONO_ISINST can be:
4509                 0) the cast is valid
4510                 1) cast of unknown proxy type
4511                 or an exception if the cast is is invalid
4512         */
4513         
4514         pos_was_ok = mono_mb_emit_branch (mb, CEE_BRFALSE);
4515
4516         /* get the real proxy from the transparent proxy*/
4517
4518         mono_mb_emit_ldarg (mb, 0);
4519         mono_mb_emit_managed_call (mb, mono_marshal_get_proxy_cancast (klass), NULL);
4520         pos_was_ok2 = mono_mb_emit_branch (mb, CEE_BRTRUE);
4521         
4522         /* fail */
4523         mono_mb_emit_exception (mb, "InvalidCastException", NULL);
4524         
4525         /* success */
4526         mono_mb_patch_addr (mb, pos_was_ok, mb->pos - (pos_was_ok + 4));
4527         mono_mb_patch_addr (mb, pos_was_ok2, mb->pos - (pos_was_ok2 + 4));
4528         mono_mb_emit_ldarg (mb, 0);
4529         
4530         /* the end */
4531         mono_mb_emit_byte (mb, CEE_RET);
4532
4533         res = mono_mb_create_and_cache (castclass_hash, klass, mb, castclass_sig, castclass_sig->param_count + 16);
4534         mono_mb_free (mb);
4535
4536         return res;
4537 }
4538
4539 MonoMethod *
4540 mono_marshal_get_proxy_cancast (MonoClass *klass)
4541 {
4542         static MonoMethodSignature *from_handle_sig = NULL;
4543         static MonoMethodSignature *upgrade_proxy_sig = NULL;
4544         static MonoMethodSignature *isint_sig = NULL;
4545         static GHashTable *proxy_isinst_hash = NULL; 
4546         MonoMethod *res;
4547         int pos_failed, pos_end;
4548         char *name;
4549         MonoMethod *can_cast_to;
4550         MonoMethodDesc *desc;
4551         MonoMethodBuilder *mb;
4552
4553         EnterCriticalSection (&marshal_mutex);
4554         if (!proxy_isinst_hash) 
4555                 proxy_isinst_hash = g_hash_table_new (NULL, NULL);
4556         
4557         res = g_hash_table_lookup (proxy_isinst_hash, klass);
4558         LeaveCriticalSection (&marshal_mutex);
4559         if (res)
4560                 return res;
4561
4562         if (!isint_sig) {
4563                 upgrade_proxy_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
4564                 upgrade_proxy_sig->params [0] = &mono_defaults.object_class->byval_arg;
4565                 upgrade_proxy_sig->params [1] = &mono_defaults.object_class->byval_arg;
4566                 upgrade_proxy_sig->ret = &mono_defaults.void_class->byval_arg;
4567                 upgrade_proxy_sig->pinvoke = 1;
4568
4569                 from_handle_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
4570                 from_handle_sig->params [0] = &mono_defaults.object_class->byval_arg;
4571                 from_handle_sig->ret = &mono_defaults.object_class->byval_arg;
4572         
4573                 isint_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
4574                 isint_sig->params [0] = &mono_defaults.object_class->byval_arg;
4575                 isint_sig->ret = &mono_defaults.object_class->byval_arg;
4576                 isint_sig->pinvoke = 0;
4577         }
4578         
4579         name = g_strdup_printf ("__proxy_isinst_wrapper_%s", klass->name); 
4580         mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_PROXY_ISINST);
4581         g_free (name);
4582         
4583         mb->method->save_lmf = 1;
4584
4585         /* get the real proxy from the transparent proxy*/
4586         mono_mb_emit_ldarg (mb, 0);
4587         mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoTransparentProxy, rp));
4588         mono_mb_emit_byte (mb, CEE_LDIND_I);
4589         
4590         /* get the refletion type from the type handle */
4591         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4592         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
4593         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, &klass->byval_arg));
4594         mono_mb_emit_native_call (mb, from_handle_sig, type_from_handle);
4595         
4596         mono_mb_emit_ldarg (mb, 0);
4597         
4598         /* make the call to CanCastTo (type, ob) */
4599         desc = mono_method_desc_new ("IRemotingTypeInfo:CanCastTo", FALSE);
4600         can_cast_to = mono_method_desc_search_in_class (desc, mono_defaults.iremotingtypeinfo_class);
4601         g_assert (can_cast_to);
4602         mono_method_desc_free (desc);
4603         mono_mb_emit_byte (mb, CEE_CALLVIRT);
4604         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, can_cast_to));
4605
4606         
4607         pos_failed = mono_mb_emit_branch (mb, CEE_BRFALSE);
4608
4609         /* Upgrade the proxy vtable by calling: mono_upgrade_remote_class_wrapper (type, ob)*/
4610         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4611         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
4612         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, &klass->byval_arg));
4613         mono_mb_emit_native_call (mb, from_handle_sig, type_from_handle);
4614         mono_mb_emit_ldarg (mb, 0);
4615         
4616         mono_mb_emit_native_call (mb, upgrade_proxy_sig, mono_upgrade_remote_class_wrapper);
4617         emit_thread_interrupt_checkpoint (mb);
4618         
4619         mono_mb_emit_ldarg (mb, 0);
4620         pos_end = mono_mb_emit_branch (mb, CEE_BR);
4621         
4622         /* fail */
4623         
4624         mono_mb_patch_addr (mb, pos_failed, mb->pos - (pos_failed + 4));
4625         mono_mb_emit_byte (mb, CEE_LDNULL);
4626         
4627         /* the end */
4628         
4629         mono_mb_patch_addr (mb, pos_end, mb->pos - (pos_end + 4));
4630         mono_mb_emit_byte (mb, CEE_RET);
4631
4632         res = mono_mb_create_and_cache (proxy_isinst_hash, klass, mb, isint_sig, isint_sig->param_count + 16);
4633         mono_mb_free (mb);
4634
4635         return res;
4636 }
4637
4638 void
4639 mono_upgrade_remote_class_wrapper (MonoReflectionType *rtype, MonoTransparentProxy *tproxy)
4640 {
4641         MonoClass *klass;
4642         klass = mono_class_from_mono_type (rtype->type);
4643         mono_upgrade_remote_class (((MonoObject*)tproxy)->vtable->domain, tproxy->remote_class, klass);
4644         ((MonoObject*)tproxy)->vtable = tproxy->remote_class->vtable;
4645 }
4646
4647 /**
4648  * mono_marshal_get_struct_to_ptr:
4649  * @klass:
4650  *
4651  * generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld)
4652  */
4653 MonoMethod *
4654 mono_marshal_get_struct_to_ptr (MonoClass *klass)
4655 {
4656         MonoMethodBuilder *mb;
4657         static MonoMethod *stoptr = NULL;
4658         MonoMethod *res;
4659
4660         g_assert (klass != NULL);
4661
4662         if (klass->str_to_ptr)
4663                 return klass->str_to_ptr;
4664
4665         if (!stoptr) 
4666                 stoptr = mono_find_method_by_name (mono_defaults.marshal_class, "StructureToPtr", 3);
4667         g_assert (stoptr);
4668
4669         mb = mono_mb_new (klass, stoptr->name, MONO_WRAPPER_UNKNOWN);
4670
4671         if (klass->blittable) {
4672                 mono_mb_emit_byte (mb, CEE_LDARG_1);
4673                 mono_mb_emit_byte (mb, CEE_LDARG_0);
4674                 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
4675                 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
4676                 mono_mb_emit_byte (mb, CEE_PREFIX1);
4677                 mono_mb_emit_byte (mb, CEE_CPBLK);
4678         } else {
4679
4680                 /* allocate local 0 (pointer) src_ptr */
4681                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
4682                 /* allocate local 1 (pointer) dst_ptr */
4683                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
4684                 /* allocate local 2 (boolean) delete_old */
4685                 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
4686                 mono_mb_emit_byte (mb, CEE_LDARG_2);
4687                 mono_mb_emit_byte (mb, CEE_STLOC_2);
4688
4689                 /* initialize src_ptr to point to the start of object data */
4690                 mono_mb_emit_byte (mb, CEE_LDARG_0);
4691                 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
4692                 mono_mb_emit_byte (mb, CEE_STLOC_0);
4693
4694                 /* initialize dst_ptr */
4695                 mono_mb_emit_byte (mb, CEE_LDARG_1);
4696                 mono_mb_emit_byte (mb, CEE_STLOC_1);
4697
4698                 emit_struct_conv (mb, klass, FALSE);
4699         }
4700
4701         mono_mb_emit_byte (mb, CEE_RET);
4702
4703         res = mono_mb_create_method (mb, stoptr->signature, 0);
4704         mono_mb_free (mb);
4705
4706         klass->str_to_ptr = res;
4707         return res;
4708 }
4709
4710 /**
4711  * mono_marshal_get_ptr_to_struct:
4712  * @klass:
4713  *
4714  * generates IL code for PtrToStructure (IntPtr src, object structure)
4715  */
4716 MonoMethod *
4717 mono_marshal_get_ptr_to_struct (MonoClass *klass)
4718 {
4719         MonoMethodBuilder *mb;
4720         static MonoMethod *ptostr = NULL;
4721         MonoMethod *res;
4722
4723         g_assert (klass != NULL);
4724
4725         if (klass->ptr_to_str)
4726                 return klass->ptr_to_str;
4727
4728         if (!ptostr) 
4729                 ptostr = mono_find_method_by_name (mono_defaults.marshal_class, "PtrToStructure", 2);
4730         g_assert (ptostr);
4731
4732         mb = mono_mb_new (klass, ptostr->name, MONO_WRAPPER_UNKNOWN);
4733
4734         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable) {
4735                 mono_mb_emit_byte (mb, CEE_LDARG_1);
4736                 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
4737                 mono_mb_emit_byte (mb, CEE_LDARG_0);
4738                 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
4739                 mono_mb_emit_byte (mb, CEE_PREFIX1);
4740                 mono_mb_emit_byte (mb, CEE_CPBLK);
4741         } else {
4742
4743                 /* allocate local 0 (pointer) src_ptr */
4744                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
4745                 /* allocate local 1 (pointer) dst_ptr */
4746                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
4747                 
4748                 /* initialize src_ptr to point to the start of object data */
4749                 mono_mb_emit_byte (mb, CEE_LDARG_0);
4750                 mono_mb_emit_byte (mb, CEE_STLOC_0);
4751
4752                 /* initialize dst_ptr */
4753                 mono_mb_emit_byte (mb, CEE_LDARG_1);
4754                 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
4755                 mono_mb_emit_byte (mb, CEE_STLOC_1);
4756
4757                 emit_struct_conv (mb, klass, TRUE);
4758         }
4759
4760         mono_mb_emit_byte (mb, CEE_RET);
4761
4762         res = mono_mb_create_method (mb, ptostr->signature, 0);
4763         mono_mb_free (mb);
4764
4765         klass->ptr_to_str = res;
4766         return res;
4767 }
4768
4769 /*
4770  * generates IL code for the synchronized wrapper: the generated method
4771  * calls METHOD while locking 'this' or the parent type.
4772  */
4773 MonoMethod *
4774 mono_marshal_get_synchronized_wrapper (MonoMethod *method)
4775 {
4776         static MonoMethodSignature *from_handle_sig = NULL;
4777         static MonoMethod *enter_method, *exit_method;
4778         MonoMethodSignature *sig;
4779         MonoExceptionClause *clause;
4780         MonoMethodHeader *header;
4781         MonoMethodBuilder *mb;
4782         MonoMethod *res;
4783         GHashTable *cache;
4784         int i, pos, this_local, ret_local;
4785
4786         g_assert (method);
4787
4788         if (method->wrapper_type == MONO_WRAPPER_SYNCHRONIZED)
4789                 return method;
4790
4791         cache = method->klass->image->synchronized_cache;
4792         if ((res = mono_marshal_find_in_cache (cache, method)))
4793                 return res;
4794
4795         sig = method->signature;
4796
4797         mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_SYNCHRONIZED);
4798
4799         /* result */
4800         if (!MONO_TYPE_IS_VOID (sig->ret))
4801                 ret_local = mono_mb_add_local (mb, sig->ret);
4802
4803         /* this */
4804         this_local = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
4805
4806         clause = g_new0 (MonoExceptionClause, 1);
4807         clause->flags = MONO_EXCEPTION_CLAUSE_FINALLY;
4808
4809         if (!enter_method) {
4810                 MonoMethodDesc *desc;
4811
4812                 desc = mono_method_desc_new ("Monitor:Enter", FALSE);
4813                 enter_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
4814                 g_assert (enter_method);
4815                 mono_method_desc_free (desc);
4816                 desc = mono_method_desc_new ("Monitor:Exit", FALSE);
4817                 exit_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
4818                 g_assert (exit_method);
4819                 mono_method_desc_free (desc);
4820
4821                 /*
4822                  * GetTypeFromHandle isn't called as a managed method because it has
4823                  * a funky calling sequence, e.g. ldtoken+GetTypeFromHandle gets
4824                  * transformed into something else by the JIT.
4825                  */
4826                 from_handle_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
4827                 from_handle_sig->params [0] = &mono_defaults.object_class->byval_arg;
4828                 from_handle_sig->ret = &mono_defaults.object_class->byval_arg;
4829         }
4830
4831         /* Push this or the type object */
4832         if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4833                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4834                 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
4835                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, &method->klass->byval_arg));
4836                 mono_mb_emit_native_call (mb, from_handle_sig, type_from_handle);
4837         }
4838         else
4839                 mono_mb_emit_ldarg (mb, 0);
4840         mono_mb_emit_stloc (mb, this_local);
4841
4842         /* Call Monitor::Enter() */
4843         mono_mb_emit_ldloc (mb, this_local);
4844         mono_mb_emit_managed_call (mb, enter_method, NULL);
4845
4846         clause->try_offset = mb->pos;
4847
4848         /* Call the method */
4849         if (sig->hasthis)
4850                 mono_mb_emit_ldarg (mb, 0);
4851         for (i = 0; i < sig->param_count; i++)
4852                 mono_mb_emit_ldarg (mb, i + (sig->hasthis == TRUE));
4853         mono_mb_emit_managed_call (mb, method, method->signature);
4854         if (!MONO_TYPE_IS_VOID (sig->ret))
4855                 mono_mb_emit_stloc (mb, ret_local);
4856
4857         mono_mb_emit_byte (mb, CEE_LEAVE);
4858         pos = mb->pos;
4859         mono_mb_emit_i4 (mb, 0);
4860
4861         clause->try_len = mb->pos - clause->try_offset;
4862         clause->handler_offset = mb->pos;
4863
4864         /* Call Monitor::Exit() */
4865         mono_mb_emit_ldloc (mb, this_local);
4866 /*      mono_mb_emit_native_call (mb, exit_sig, mono_monitor_exit); */
4867         mono_mb_emit_managed_call (mb, exit_method, NULL);
4868         mono_mb_emit_byte (mb, CEE_ENDFINALLY);
4869
4870         clause->handler_len = mb->pos - clause->handler_offset;
4871
4872         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
4873         if (!MONO_TYPE_IS_VOID (sig->ret))
4874                 mono_mb_emit_ldloc (mb, ret_local);
4875         mono_mb_emit_byte (mb, CEE_RET);
4876
4877         res = mono_mb_create_and_cache (cache, method,
4878                                                                         mb, sig, sig->param_count + 16);
4879         mono_mb_free (mb);
4880
4881         header = ((MonoMethodNormal *)res)->header;
4882         header->num_clauses = 1;
4883         header->clauses = clause;
4884
4885         return res;     
4886 }
4887
4888 /* FIXME: on win32 we should probably use GlobalAlloc(). */
4889 void*
4890 mono_marshal_alloc (gpointer size) 
4891 {
4892         MONO_ARCH_SAVE_REGS;
4893
4894         return g_try_malloc ((gulong)size);
4895 }
4896
4897 void
4898 mono_marshal_free (gpointer ptr) 
4899 {
4900         MONO_ARCH_SAVE_REGS;
4901
4902         g_free (ptr);
4903 }
4904
4905 void
4906 mono_marshal_free_array (gpointer *ptr, int size) 
4907 {
4908         int i;
4909
4910         if (!ptr)
4911                 return;
4912
4913         for (i = 0; i < size; i++)
4914                 if (ptr [i])
4915                         g_free (ptr [i]);
4916 }
4917
4918 void *
4919 mono_marshal_realloc (gpointer ptr, gpointer size) 
4920 {
4921         MONO_ARCH_SAVE_REGS;
4922
4923         return g_try_realloc (ptr, (gulong)size);
4924 }
4925
4926 void *
4927 mono_marshal_string_array (MonoArray *array)
4928 {
4929         char **result;
4930         int i, len;
4931
4932         if (!array)
4933                 return NULL;
4934
4935         len = mono_array_length (array);
4936
4937         result = g_malloc (sizeof (char *) * (len + 1));
4938         for (i = 0; i < len; ++i) {
4939                 MonoString *s = (MonoString *)mono_array_get (array, gpointer, i);
4940                 result [i] = s ? mono_string_to_utf8 (s): NULL;
4941         }
4942         /* null terminate the array */
4943         result [i] = NULL;
4944
4945         return result;
4946 }
4947
4948 void *
4949 mono_marshal_string_array_to_unicode (MonoArray *array)
4950 {
4951         gunichar2 **result;
4952         int i, len;
4953
4954         if (!array)
4955                 return NULL;
4956
4957         len = mono_array_length (array);
4958
4959         result = g_malloc (sizeof (gunichar2 *) * (len + 1));
4960         for (i = 0; i < len; ++i) {
4961                 MonoString *s = (MonoString *)mono_array_get (array, gpointer, i);
4962                 result [i] = s ? mono_string_chars (s) : NULL;
4963         }
4964         /* null terminate the array */
4965         result [i] = NULL;
4966
4967         return result;
4968 }
4969
4970 /**
4971  * mono_marshal_set_last_error:
4972  *
4973  * This function is invoked to set the last error value from a P/Invoke call
4974  * which has SetLastError set.
4975  */
4976 void
4977 mono_marshal_set_last_error (void)
4978 {
4979 #ifdef WIN32
4980         TlsSetValue (last_error_tls_id, (gpointer)GetLastError ());
4981 #else
4982         TlsSetValue (last_error_tls_id, (gpointer)errno);
4983 #endif
4984 }
4985
4986 void
4987 ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArray *src, gint32 start_index,
4988                                                                     gpointer dest, gint32 length)
4989 {
4990         int element_size;
4991         void *source_addr;
4992
4993         MONO_ARCH_SAVE_REGS;
4994
4995         MONO_CHECK_ARG_NULL (src);
4996         MONO_CHECK_ARG_NULL (dest);
4997
4998         g_assert (src->obj.vtable->klass->rank == 1);
4999         g_assert (start_index >= 0);
5000         g_assert (length >= 0);
5001         g_assert (start_index + length <= mono_array_length (src));
5002
5003         element_size = mono_array_element_size (src->obj.vtable->klass);
5004           
5005         source_addr = mono_array_addr_with_size (src, element_size, start_index);
5006
5007         memcpy (dest, source_addr, length * element_size);
5008 }
5009
5010 void
5011 ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer src, gint32 start_index,
5012                                                                       MonoArray *dest, gint32 length)
5013 {
5014         int element_size;
5015         void *dest_addr;
5016
5017         MONO_ARCH_SAVE_REGS;
5018
5019         MONO_CHECK_ARG_NULL (src);
5020         MONO_CHECK_ARG_NULL (dest);
5021
5022         g_assert (dest->obj.vtable->klass->rank == 1);
5023         g_assert (start_index >= 0);
5024         g_assert (length >= 0);
5025         g_assert (start_index + length <= mono_array_length (dest));
5026
5027         element_size = mono_array_element_size (dest->obj.vtable->klass);
5028           
5029         dest_addr = mono_array_addr_with_size (dest, element_size, start_index);
5030
5031         memcpy (dest_addr, src, length * element_size);
5032 }
5033
5034 #if NO_UNALIGNED_ACCESS
5035 #define RETURN_UNALIGNED(type, addr) \
5036         { \
5037                 type val; \
5038                 memcpy(&val, p + offset, sizeof(val)); \
5039                 return val; \
5040         }
5041 #define WRITE_UNALIGNED(type, addr, val) \
5042         memcpy(addr, &val, sizeof(type))
5043 #else
5044 #define RETURN_UNALIGNED(type, addr) \
5045         return *(type*)(p + offset);
5046 #define WRITE_UNALIGNED(type, addr, val) \
5047         (*(type *)(addr) = (val))
5048 #endif
5049
5050 gpointer
5051 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr, gint32 offset)
5052 {
5053         char *p = ptr;
5054
5055         MONO_ARCH_SAVE_REGS;
5056
5057         RETURN_UNALIGNED(gpointer, p + offset);
5058 }
5059
5060 unsigned char
5061 ves_icall_System_Runtime_InteropServices_Marshal_ReadByte (gpointer ptr, gint32 offset)
5062 {
5063         char *p = ptr;
5064
5065         MONO_ARCH_SAVE_REGS;
5066
5067         return *(unsigned char*)(p + offset);
5068 }
5069
5070 gint16
5071 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt16 (gpointer ptr, gint32 offset)
5072 {
5073         char *p = ptr;
5074
5075         MONO_ARCH_SAVE_REGS;
5076
5077         RETURN_UNALIGNED(gint16, p + offset);
5078 }
5079
5080 gint32
5081 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt32 (gpointer ptr, gint32 offset)
5082 {
5083         char *p = ptr;
5084
5085         MONO_ARCH_SAVE_REGS;
5086
5087         RETURN_UNALIGNED(gint32, p + offset);
5088 }
5089
5090 gint64
5091 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt64 (gpointer ptr, gint32 offset)
5092 {
5093         char *p = ptr;
5094
5095         MONO_ARCH_SAVE_REGS;
5096
5097         RETURN_UNALIGNED(gint64, p + offset);
5098 }
5099
5100 void
5101 ves_icall_System_Runtime_InteropServices_Marshal_WriteByte (gpointer ptr, gint32 offset, unsigned char val)
5102 {
5103         char *p = ptr;
5104
5105         MONO_ARCH_SAVE_REGS;
5106
5107         *(unsigned char*)(p + offset) = val;
5108 }
5109
5110 void
5111 ves_icall_System_Runtime_InteropServices_Marshal_WriteIntPtr (gpointer ptr, gint32 offset, gpointer val)
5112 {
5113         char *p = ptr;
5114
5115         MONO_ARCH_SAVE_REGS;
5116
5117         WRITE_UNALIGNED(gpointer, p + offset, val);
5118 }
5119
5120 void
5121 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt16 (gpointer ptr, gint32 offset, gint16 val)
5122 {
5123         char *p = ptr;
5124
5125         MONO_ARCH_SAVE_REGS;
5126
5127         WRITE_UNALIGNED(gint16, p + offset, val);
5128 }
5129
5130 void
5131 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt32 (gpointer ptr, gint32 offset, gint32 val)
5132 {
5133         char *p = ptr;
5134
5135         MONO_ARCH_SAVE_REGS;
5136
5137         WRITE_UNALIGNED(gint32, p + offset, val);
5138 }
5139
5140 void
5141 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt64 (gpointer ptr, gint32 offset, gint64 val)
5142 {
5143         char *p = ptr;
5144
5145         MONO_ARCH_SAVE_REGS;
5146
5147         WRITE_UNALIGNED(gint64, p + offset, val);
5148 }
5149
5150 MonoString *
5151 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (char *ptr)
5152 {
5153         MONO_ARCH_SAVE_REGS;
5154
5155         if (ptr == NULL)
5156                 return mono_string_new (mono_domain_get (), "");
5157         else
5158                 return mono_string_new (mono_domain_get (), ptr);
5159 }
5160
5161 MonoString *
5162 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len (char *ptr, gint32 len)
5163 {
5164         MONO_ARCH_SAVE_REGS;
5165
5166         if (ptr == NULL)
5167                 return mono_string_new (mono_domain_get (), "");
5168         else
5169                 return mono_string_new_len (mono_domain_get (), ptr, len);
5170 }
5171
5172 MonoString *
5173 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni (guint16 *ptr)
5174 {
5175         MonoDomain *domain = mono_domain_get (); 
5176         int len = 0;
5177         guint16 *t = ptr;
5178
5179         MONO_ARCH_SAVE_REGS;
5180
5181         if (ptr == NULL)
5182                 return mono_string_new (mono_domain_get (), "");
5183
5184         while (*t++)
5185                 len++;
5186
5187         return mono_string_new_utf16 (domain, ptr, len);
5188 }
5189
5190 MonoString *
5191 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len (guint16 *ptr, gint32 len)
5192 {
5193         MonoDomain *domain = mono_domain_get (); 
5194
5195         MONO_ARCH_SAVE_REGS;
5196
5197         if (ptr == NULL)
5198                 return mono_string_new (mono_domain_get (), "");
5199         else
5200                 return mono_string_new_utf16 (domain, ptr, len);
5201 }
5202
5203 MonoString *
5204 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR (gpointer ptr)
5205 {
5206         MONO_ARCH_SAVE_REGS;
5207
5208         g_warning ("PtrToStringBSTR not implemented");
5209         g_assert_not_reached ();
5210
5211         return NULL;
5212 }
5213
5214 guint32 
5215 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
5216 {
5217         MONO_ARCH_SAVE_REGS;
5218
5219         return ((guint32)TlsGetValue (last_error_tls_id));
5220 }
5221
5222 guint32 
5223 ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype)
5224 {
5225         MonoClass *klass;
5226         MonoType *type;
5227         guint32 layout;
5228
5229         MONO_ARCH_SAVE_REGS;
5230
5231         MONO_CHECK_ARG_NULL (rtype);
5232
5233         type = rtype->type;
5234         klass = mono_class_from_mono_type (type);
5235         layout = (klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK);
5236
5237         if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
5238                 gchar *msg;
5239                 MonoException *exc;
5240
5241                 msg = g_strdup_printf ("Type %s cannot be marshaled as an unmanaged structure.", klass->name);
5242                 exc = mono_get_exception_argument ("t", msg);
5243                 g_free (msg);
5244                 mono_raise_exception (exc);
5245         }
5246
5247
5248         return mono_class_native_size (klass, NULL);
5249 }
5250
5251 void
5252 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old)
5253 {
5254         MonoMethod *method;
5255         gpointer pa [3];
5256
5257         MONO_ARCH_SAVE_REGS;
5258
5259         MONO_CHECK_ARG_NULL (obj);
5260         MONO_CHECK_ARG_NULL (dst);
5261
5262         method = mono_marshal_get_struct_to_ptr (obj->vtable->klass);
5263
5264         pa [0] = obj;
5265         pa [1] = &dst;
5266         pa [2] = &delete_old;
5267
5268         mono_runtime_invoke (method, NULL, pa, NULL);
5269 }
5270
5271 void
5272 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, MonoObject *dst)
5273 {
5274         MonoMethod *method;
5275         gpointer pa [2];
5276
5277         MONO_ARCH_SAVE_REGS;
5278
5279         MONO_CHECK_ARG_NULL (src);
5280         MONO_CHECK_ARG_NULL (dst);
5281
5282         method = mono_marshal_get_ptr_to_struct (dst->vtable->klass);
5283
5284         pa [0] = &src;
5285         pa [1] = dst;
5286
5287         mono_runtime_invoke (method, NULL, pa, NULL);
5288 }
5289
5290 MonoObject *
5291 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer src, MonoReflectionType *type)
5292 {
5293         MonoDomain *domain = mono_domain_get (); 
5294         MonoObject *res;
5295
5296         MONO_ARCH_SAVE_REGS;
5297
5298         MONO_CHECK_ARG_NULL (src);
5299         MONO_CHECK_ARG_NULL (type);
5300
5301         res = mono_object_new (domain, mono_class_from_mono_type (type->type));
5302
5303         ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (src, res);
5304
5305         return res;
5306 }
5307
5308 int
5309 ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *type, MonoString *field_name)
5310 {
5311         MonoMarshalType *info;
5312         MonoClass *klass;
5313         char *fname;
5314         int i, match_index = -1;
5315         
5316         MONO_ARCH_SAVE_REGS;
5317
5318         MONO_CHECK_ARG_NULL (type);
5319         MONO_CHECK_ARG_NULL (field_name);
5320
5321         fname = mono_string_to_utf8 (field_name);
5322         klass = mono_class_from_mono_type (type->type);
5323
5324         while(klass && match_index == -1) {
5325                 for (i = 0; i < klass->field.count; ++i) {
5326                         if (*fname == *klass->fields [i].name && strcmp (fname, klass->fields [i].name) == 0) {
5327                                 match_index = i;
5328                                 break;
5329                         }
5330                 }
5331
5332                 if(match_index == -1)
5333                         klass = klass->parent;
5334         }
5335
5336         g_free (fname);
5337
5338         if(match_index == -1) {
5339                MonoException* exc;
5340                gchar *tmp;
5341
5342                /* Get back original class instance */
5343                klass = mono_class_from_mono_type (type->type);
5344
5345                tmp = g_strdup_printf ("Field passed in is not a marshaled member of the type %s", klass->name);
5346                exc = mono_get_exception_argument ("fieldName", tmp);
5347                g_free (tmp);
5348  
5349                mono_raise_exception ((MonoException*)exc);
5350        }
5351
5352        info = mono_marshal_load_type_info (klass);     
5353        return info->fields [match_index].offset;
5354 }
5355
5356 gpointer
5357 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString *string)
5358 {
5359         MONO_ARCH_SAVE_REGS;
5360
5361         return mono_string_to_utf8 (string);
5362 }
5363
5364 gpointer
5365 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni (MonoString *string)
5366 {
5367         MONO_ARCH_SAVE_REGS;
5368
5369         if (string == NULL)
5370                 return NULL;
5371         else
5372                 return g_memdup (mono_string_chars (string), mono_string_length (string)*2);
5373 }
5374
5375 static void
5376 mono_struct_delete_old (MonoClass *klass, char *ptr)
5377 {
5378         MonoMarshalType *info;
5379         int i;
5380
5381         info = mono_marshal_load_type_info (klass);
5382
5383         for (i = 0; i < info->num_fields; i++) {
5384                 MonoMarshalNative ntype;
5385                 MonoMarshalConv conv;
5386                 MonoType *ftype = info->fields [i].field->type;
5387                 char *cpos;
5388
5389                 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
5390                         continue;
5391
5392                 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, 
5393                                                 klass->unicode, &conv);
5394                         
5395                 cpos = ptr + info->fields [i].offset;
5396
5397                 switch (conv) {
5398                 case MONO_MARSHAL_CONV_NONE:
5399                         if (MONO_TYPE_ISSTRUCT (ftype)) {
5400                                 mono_struct_delete_old (ftype->data.klass, cpos);
5401                                 continue;
5402                         }
5403                         break;
5404                 case MONO_MARSHAL_CONV_STR_LPWSTR:
5405                 case MONO_MARSHAL_CONV_STR_LPSTR:
5406                 case MONO_MARSHAL_CONV_STR_LPTSTR:
5407                 case MONO_MARSHAL_CONV_STR_BSTR:
5408                 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
5409                 case MONO_MARSHAL_CONV_STR_TBSTR:
5410                         g_free (*(gpointer *)cpos);
5411                         break;
5412                 default:
5413                         continue;
5414                 }
5415         }
5416 }
5417
5418 void
5419 ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure (gpointer src, MonoReflectionType *type)
5420 {
5421         MonoClass *klass;
5422
5423         MONO_ARCH_SAVE_REGS;
5424
5425         MONO_CHECK_ARG_NULL (src);
5426         MONO_CHECK_ARG_NULL (type);
5427
5428         klass = mono_class_from_mono_type (type->type);
5429
5430         mono_struct_delete_old (klass, (char *)src);
5431 }
5432
5433 void*
5434 ves_icall_System_Runtime_InteropServices_Marshal_AllocCoTaskMem (int size)
5435 {
5436         /* FIXME: Call AllocCoTaskMem under windows */
5437         MONO_ARCH_SAVE_REGS;
5438
5439         return g_try_malloc ((gulong)size);
5440 }
5441
5442 void
5443 ves_icall_System_Runtime_InteropServices_Marshal_FreeCoTaskMem (void *ptr)
5444 {
5445         /* FIXME: Call FreeCoTaskMem under windows */
5446         MONO_ARCH_SAVE_REGS;
5447
5448         g_free (ptr);
5449 }
5450
5451 void*
5452 ves_icall_System_Runtime_InteropServices_Marshal_UnsafeAddrOfPinnedArrayElement (MonoArray *arrayobj, int index)
5453 {
5454         return mono_array_addr_with_size (arrayobj, mono_array_element_size (arrayobj->obj.vtable->klass), index);
5455 }
5456
5457 MonoMarshalType *
5458 mono_marshal_load_type_info (MonoClass* klass)
5459 {
5460         int i, j, count = 0, native_size = 0, min_align = 1;
5461         MonoMarshalType *info;
5462         guint32 layout;
5463
5464         g_assert (klass != NULL);
5465
5466         if (klass->marshal_info)
5467                 return klass->marshal_info;
5468
5469         if (!klass->inited)
5470                 mono_class_init (klass);
5471         
5472         for (i = 0; i < klass->field.count; ++i) {
5473                 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
5474                         continue;
5475                 if (mono_field_is_deleted (&klass->fields [i]))
5476                         continue;
5477                 count++;
5478         }
5479
5480         layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
5481
5482         klass->marshal_info = info = g_malloc0 (sizeof (MonoMarshalType) + sizeof (MonoMarshalField) * count);
5483         info->num_fields = count;
5484         
5485         /* Try to find a size for this type in metadata */
5486         mono_metadata_packing_from_typedef (klass->image, klass->type_token, NULL, &native_size);
5487
5488         if (klass->parent) {
5489                 int parent_size = mono_class_native_size (klass->parent, NULL);
5490
5491                 /* Add parent size to real size */
5492                 native_size += parent_size;
5493                 info->native_size = parent_size;
5494         }
5495  
5496         for (j = i = 0; i < klass->field.count; ++i) {
5497                 int size, align;
5498                 
5499                 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
5500                         continue;
5501
5502                 if (mono_field_is_deleted (&klass->fields [i]))
5503                         continue;
5504                 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL)
5505                         mono_metadata_field_info (klass->image, klass->field.first + i, 
5506                                                   NULL, NULL, &info->fields [j].mspec);
5507
5508                 info->fields [j].field = &klass->fields [i];
5509
5510                 if ((klass->field.count == 1) && (klass->instance_size == sizeof (MonoObject)) &&
5511                         (strcmp (klass->fields [i].name, "$PRIVATE$") == 0)) {
5512                         /* This field is a hack inserted by MCS to empty structures */
5513                         continue;
5514                 }
5515
5516                 switch (layout) {
5517                 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
5518                 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
5519                         size = mono_marshal_type_size (klass->fields [i].type, info->fields [j].mspec, 
5520                                                        &align, TRUE, klass->unicode);
5521                         align = klass->packing_size ? MIN (klass->packing_size, align): align;
5522                         min_align = MAX (align, min_align);
5523                         info->fields [j].offset = info->native_size;
5524                         info->fields [j].offset += align - 1;
5525                         info->fields [j].offset &= ~(align - 1);
5526                         info->native_size = info->fields [j].offset + size;
5527                         break;
5528                 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
5529                         size = mono_marshal_type_size (klass->fields [i].type, info->fields [j].mspec, 
5530                                                        &align, TRUE, klass->unicode);
5531                         align = klass->packing_size ? MIN (klass->packing_size, align): align;
5532                         min_align = MAX (align, min_align);
5533                         info->fields [j].offset = klass->fields [i].offset - sizeof (MonoObject);
5534                         info->native_size = MAX (info->native_size, info->fields [j].offset + size);
5535                         break;
5536                 }       
5537                 j++;
5538         }
5539
5540         if(layout != TYPE_ATTRIBUTE_AUTO_LAYOUT) {
5541                 info->native_size = MAX (native_size, info->native_size);
5542         }
5543
5544         if (info->native_size & (min_align - 1)) {
5545                 info->native_size += min_align - 1;
5546                 info->native_size &= ~(min_align - 1);
5547         }
5548
5549         /* Update the class's blittable info, if the layouts don't match */
5550         if (info->native_size != mono_class_value_size (klass, NULL))
5551                 klass->blittable = FALSE;
5552
5553         /* If this is an array type, ensure that we have element info */
5554         if (klass->element_class) {
5555                 mono_marshal_load_type_info (klass->element_class);
5556         }
5557
5558         return klass->marshal_info;
5559 }
5560
5561 /**
5562  * mono_class_native_size:
5563  * @klass: a class 
5564  * 
5565  * Returns: the native size of an object instance (when marshaled 
5566  * to unmanaged code) 
5567  */
5568 gint32
5569 mono_class_native_size (MonoClass *klass, guint32 *align)
5570 {
5571         
5572         if (!klass->marshal_info)
5573                 mono_marshal_load_type_info (klass);
5574
5575         if (align)
5576                 *align = klass->min_align;
5577
5578         return klass->marshal_info->native_size;
5579 }
5580
5581 /*
5582  * mono_type_native_stack_size:
5583  * @t: the type to return the size it uses on the stack
5584  *
5585  * Returns: the number of bytes required to hold an instance of this
5586  * type on the native stack
5587  */
5588 int
5589 mono_type_native_stack_size (MonoType *t, gint *align)
5590 {
5591         int tmp;
5592
5593         g_assert (t != NULL);
5594
5595         if (!align)
5596                 align = &tmp;
5597
5598         if (t->byref) {
5599                 *align = 4;
5600                 return 4;
5601         }
5602
5603         switch (t->type){
5604         case MONO_TYPE_BOOLEAN:
5605         case MONO_TYPE_CHAR:
5606         case MONO_TYPE_I1:
5607         case MONO_TYPE_U1:
5608         case MONO_TYPE_I2:
5609         case MONO_TYPE_U2:
5610         case MONO_TYPE_I4:
5611         case MONO_TYPE_U4:
5612         case MONO_TYPE_I:
5613         case MONO_TYPE_U:
5614         case MONO_TYPE_STRING:
5615         case MONO_TYPE_OBJECT:
5616         case MONO_TYPE_CLASS:
5617         case MONO_TYPE_SZARRAY:
5618         case MONO_TYPE_PTR:
5619         case MONO_TYPE_FNPTR:
5620         case MONO_TYPE_ARRAY:
5621         case MONO_TYPE_TYPEDBYREF:
5622                 *align = 4;
5623                 return 4;
5624         case MONO_TYPE_R4:
5625                 *align = 4;
5626                 return 4;
5627         case MONO_TYPE_I8:
5628         case MONO_TYPE_U8:
5629         case MONO_TYPE_R8:
5630                 *align = 4;
5631                 return 8;
5632         case MONO_TYPE_VALUETYPE: {
5633                 guint32 size;
5634
5635                 if (t->data.klass->enumtype)
5636                         return mono_type_native_stack_size (t->data.klass->enum_basetype, align);
5637                 else {
5638                         size = mono_class_native_size (t->data.klass, align);
5639                         *align = *align + 3;
5640                         *align &= ~3;
5641                         
5642                         size +=  3;
5643                         size &= ~3;
5644
5645                         return size;
5646                 }
5647         }
5648         default:
5649                 g_error ("type 0x%02x unknown", t->type);
5650         }
5651         return 0;
5652 }
5653
5654 /* __alignof__ returns the preferred alignment of values not the actual alignment used by
5655    the compiler so is wrong e.g. for Linux where doubles are aligned on a 4 byte boundary
5656    but __alignof__ returns 8 - using G_STRUCT_OFFSET works better */
5657 #define ALIGNMENT(type) G_STRUCT_OFFSET(struct { char c; type x; }, x)
5658
5659 gint32
5660 mono_marshal_type_size (MonoType *type, MonoMarshalSpec *mspec, gint32 *align, 
5661                         gboolean as_field, gboolean unicode)
5662 {
5663         MonoMarshalNative native_type = mono_type_to_unmanaged (type, mspec, as_field, unicode, NULL);
5664         MonoClass *klass;
5665
5666         switch (native_type) {
5667         case MONO_NATIVE_BOOLEAN:
5668                 *align = 4;
5669                 return 4;
5670         case MONO_NATIVE_I1:
5671         case MONO_NATIVE_U1:
5672                 *align = 1;
5673                 return 1;
5674         case MONO_NATIVE_I2:
5675         case MONO_NATIVE_U2:
5676         case MONO_NATIVE_VARIANTBOOL:
5677                 *align = 2;
5678                 return 2;
5679         case MONO_NATIVE_I4:
5680         case MONO_NATIVE_U4:
5681         case MONO_NATIVE_ERROR:
5682                 *align = 4;
5683                 return 4;
5684         case MONO_NATIVE_I8:
5685         case MONO_NATIVE_U8:
5686                 *align = ALIGNMENT(guint64);
5687                 return 8;
5688         case MONO_NATIVE_R4:
5689                 *align = 4;
5690                 return 4;
5691         case MONO_NATIVE_R8:
5692                 *align = ALIGNMENT(double);
5693                 return 8;
5694         case MONO_NATIVE_INT:
5695         case MONO_NATIVE_UINT:
5696         case MONO_NATIVE_LPSTR:
5697         case MONO_NATIVE_LPWSTR:
5698         case MONO_NATIVE_LPTSTR:
5699         case MONO_NATIVE_BSTR:
5700         case MONO_NATIVE_ANSIBSTR:
5701         case MONO_NATIVE_TBSTR:
5702         case MONO_NATIVE_LPARRAY:
5703         case MONO_NATIVE_SAFEARRAY:
5704         case MONO_NATIVE_IUNKNOWN:
5705         case MONO_NATIVE_IDISPATCH:
5706         case MONO_NATIVE_INTERFACE:
5707         case MONO_NATIVE_ASANY:
5708         case MONO_NATIVE_FUNC:
5709         case MONO_NATIVE_LPSTRUCT:
5710                 *align = ALIGNMENT(gpointer);
5711                 return sizeof (gpointer);
5712         case MONO_NATIVE_STRUCT: 
5713                 klass = mono_class_from_mono_type (type);
5714                 return mono_class_native_size (klass, align);
5715         case MONO_NATIVE_BYVALTSTR: {
5716                 int esize = unicode ? 2: 1;
5717                 g_assert (mspec);
5718                 *align = esize;
5719                 return mspec->data.array_data.num_elem * esize;
5720         }
5721         case MONO_NATIVE_BYVALARRAY: {
5722                 int esize;
5723                 klass = mono_class_from_mono_type (type);
5724                 esize = mono_class_native_size (klass->element_class, align);
5725                 g_assert (mspec);
5726                 return mspec->data.array_data.num_elem * esize;
5727         }
5728         case MONO_NATIVE_CUSTOM:
5729                 g_assert_not_reached ();
5730                 break;
5731         case MONO_NATIVE_CURRENCY:
5732         case MONO_NATIVE_VBBYREFSTR:
5733         default:
5734                 g_error ("native type %02x not implemented", native_type); 
5735                 break;
5736         }
5737         g_assert_not_reached ();
5738         return 0;
5739 }
5740
5741 gpointer
5742 mono_marshal_asany (MonoObject *o, MonoMarshalNative string_encoding)
5743 {
5744         MonoType *t;
5745         MonoClass *klass;
5746
5747         if (o == NULL)
5748                 return NULL;
5749
5750         t = &o->vtable->klass->byval_arg;
5751         switch (t->type) {
5752         case MONO_TYPE_I4:
5753         case MONO_TYPE_U4:
5754         case MONO_TYPE_PTR:
5755         case MONO_TYPE_I1:
5756         case MONO_TYPE_U1:
5757         case MONO_TYPE_BOOLEAN:
5758         case MONO_TYPE_I2:
5759         case MONO_TYPE_U2:
5760         case MONO_TYPE_CHAR:
5761         case MONO_TYPE_I8:
5762         case MONO_TYPE_U8:
5763         case MONO_TYPE_R4:
5764         case MONO_TYPE_R8:
5765                 return mono_object_unbox (o);
5766                 break;
5767         case MONO_TYPE_STRING:
5768                 switch (string_encoding) {
5769                 case MONO_NATIVE_LPWSTR:
5770                         return mono_string_to_utf16 ((MonoString*)o);
5771                         break;
5772                 case MONO_NATIVE_LPSTR:
5773                         return mono_string_to_utf8 ((MonoString*)o);
5774                         break;
5775                 default:
5776                         g_warning ("marshaling conversion %d not implemented", string_encoding);
5777                         g_assert_not_reached ();
5778                 }
5779                 break;
5780         case MONO_TYPE_CLASS:
5781         case MONO_TYPE_VALUETYPE: {
5782                 MonoMethod *method;
5783                 gpointer pa [3];
5784                 gpointer res;
5785                 MonoBoolean delete_old = FALSE;
5786
5787                 klass = t->data.klass;
5788
5789                 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT)
5790                         break;
5791
5792                 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
5793                         klass->blittable || klass->enumtype)
5794                         return mono_object_unbox (o);
5795
5796                 res = g_malloc0 (mono_class_native_size (klass, NULL));
5797
5798                 method = mono_marshal_get_struct_to_ptr (o->vtable->klass);
5799
5800                 pa [0] = o;
5801                 pa [1] = &res;
5802                 pa [2] = &delete_old;
5803
5804                 mono_runtime_invoke (method, NULL, pa, NULL);
5805
5806                 return res;
5807         }
5808         }
5809
5810         mono_raise_exception (mono_get_exception_argument ("", "No PInvoke conversion exists for value passed to Object-typed parameter."));
5811
5812         return NULL;
5813 }
5814
5815 void
5816 mono_marshal_free_asany (MonoObject *o, gpointer ptr, MonoMarshalNative string_encoding)
5817 {
5818         MonoType *t;
5819         MonoClass *klass;
5820
5821         /* FIXME: Free embedded data as well */
5822
5823         if (o == NULL)
5824                 return;
5825
5826         t = &o->vtable->klass->byval_arg;
5827         switch (t->type) {
5828         case MONO_TYPE_STRING:
5829                 switch (string_encoding) {
5830                 case MONO_NATIVE_LPWSTR:
5831                         g_free (ptr);
5832                         break;
5833                 case MONO_NATIVE_LPSTR:
5834                         g_free (ptr);
5835                         break;
5836                 default:
5837                         g_warning ("marshaling conversion %d not implemented", string_encoding);
5838                         g_assert_not_reached ();
5839                 }
5840                 break;
5841         case MONO_TYPE_CLASS:
5842         case MONO_TYPE_VALUETYPE: {
5843                 klass = t->data.klass;
5844
5845                 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
5846                         klass->blittable || klass->enumtype)
5847                         break;
5848
5849                 g_free (ptr);
5850                 break;
5851         }
5852         default:
5853                 break;
5854         }
5855 }