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