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