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