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 static void
2202 raise_auto_layout_exception (MonoClass *klass)
2203 {
2204         char *msg = g_strdup_printf ("The type `%s.%s' layout needs to be Sequential or Explicit",
2205                                      klass->name_space, klass->name, NULL);
2206                                 
2207         MonoException *e = mono_exception_from_name_msg (
2208                 mono_get_corlib (), "System.Runtime.InteropServices",
2209                 "MarshalDirectiveException", msg);
2210         g_free (msg);
2211         mono_raise_exception (e);
2212 }
2213                              
2214 /*
2215  * generates IL code to call managed methods from unmanaged code 
2216  */
2217 MonoMethod *
2218 mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this, MonoMarshalSpec **mspecs)
2219 {
2220         MonoMethodSignature *sig, *csig;
2221         MonoMethodBuilder *mb;
2222         MonoClass *klass = NULL;
2223         MonoMethod *res;
2224         GHashTable *cache;
2225         int i, pos = 0, *tmp_locals;
2226         static MonoMethodSignature *alloc_sig = NULL;
2227         int retobj_var = 0;
2228
2229         g_assert (method != NULL);
2230         g_assert (!method->signature->pinvoke);
2231
2232         cache = method->klass->image->managed_wrapper_cache;
2233         if (!this && (res = mono_marshal_find_in_cache (cache, method)))
2234                 return res;
2235
2236         /* Under MS, the allocation should be done using CoTaskMemAlloc */
2237         if (!alloc_sig) {
2238                 alloc_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
2239                 alloc_sig->params [0] = &mono_defaults.int_class->byval_arg;
2240                 alloc_sig->ret = &mono_defaults.int_class->byval_arg;
2241                 alloc_sig->pinvoke = 1;
2242         }
2243
2244         if (this) {
2245                 /* fime: howto free that memory ? */
2246         }
2247
2248         sig = method->signature;
2249
2250         mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_NATIVE_TO_MANAGED);
2251
2252         /* allocate local 0 (pointer) src_ptr */
2253         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2254         /* allocate local 1 (pointer) dst_ptr */
2255         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2256         /* allocate local 2 (boolean) delete_old */
2257         mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2258
2259         if (!MONO_TYPE_IS_VOID(sig->ret)) {
2260                 /* allocate local 3 to store the return value */
2261                 mono_mb_add_local (mb, sig->ret);
2262         }
2263
2264         mono_mb_emit_icon (mb, 0);
2265         mono_mb_emit_byte (mb, CEE_STLOC_2);
2266
2267         /* we copy the signature, so that we can modify it */
2268         csig = mono_metadata_signature_dup (sig);
2269         csig->hasthis = 0;
2270         csig->pinvoke = 1;
2271
2272 #ifdef PLATFORM_WIN32
2273         /* 
2274          * Under windows, delegates passed to native code must use the STDCALL
2275          * calling convention.
2276          */
2277         csig->call_convention = MONO_CALL_STDCALL;
2278 #endif
2279
2280         /* fixme: howto handle this ? */
2281         if (sig->hasthis) {
2282
2283                 if (this) {
2284                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2285                         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
2286                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, this));
2287
2288
2289                 } else {
2290                         /* fixme: */
2291                         g_assert_not_reached ();
2292                 }
2293         } 
2294
2295
2296         /* we first do all conversions */
2297         tmp_locals = alloca (sizeof (int) * sig->param_count);
2298         for (i = 0; i < sig->param_count; i ++) {
2299                 MonoType *t = sig->params [i];
2300                 MonoMarshalSpec *spec = mspecs [i + 1];
2301
2302                 tmp_locals [i] = 0;
2303                 
2304                 /* Ensure that we have marshalling info for this param */
2305                 mono_marshal_load_type_info (mono_class_from_mono_type (t));
2306                 
2307                 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
2308                         MonoType *mtype;
2309                         MonoClass *mklass;
2310                         MonoMethod *marshal_native_to_managed;
2311                         MonoMethod *get_instance;
2312
2313                         /* FIXME: Call CleanUpNativeData after the call */
2314
2315                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
2316                         g_assert (mtype != NULL);
2317                         mklass = mono_class_from_mono_type (mtype);
2318                         g_assert (mklass != NULL);
2319
2320                         marshal_native_to_managed = mono_find_method_by_name (mklass, "MarshalNativeToManaged", 1);
2321                         g_assert (marshal_native_to_managed);
2322                         get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
2323                         g_assert (get_instance);
2324                         
2325                         switch (t->type) {
2326                         case MONO_TYPE_CLASS:
2327                         case MONO_TYPE_OBJECT:
2328                         case MONO_TYPE_STRING:
2329                         case MONO_TYPE_ARRAY:
2330                         case MONO_TYPE_SZARRAY:
2331                                 if (t->byref)
2332                                         break;
2333
2334                                 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2335
2336                                 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
2337
2338                                 mono_mb_emit_byte (mb, CEE_CALL);
2339                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
2340                                 
2341                                 mono_mb_emit_ldarg (mb, i);
2342                                 
2343                                 mono_mb_emit_byte (mb, CEE_CALLVIRT);
2344                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_native_to_managed));
2345                                 
2346                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
2347                                 break;
2348                         default:
2349                                 g_warning ("custom marshalling of type %x is currently not supported", t->type);
2350                                 g_assert_not_reached ();
2351                                 break;
2352                         }
2353                         continue;
2354                 }
2355
2356                 switch (t->type) {
2357                 case MONO_TYPE_CLASS: {
2358                         klass = t->data.klass;
2359
2360                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2361
2362                         if (klass->delegate) {
2363                                 g_assert (!t->byref);
2364                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2365                                 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
2366                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2367                                 mono_mb_emit_ldarg (mb, i);
2368                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2369                                 mono_mb_emit_byte (mb, CEE_MONO_FUNC2);
2370                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_FTN_DEL);
2371                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
2372                                 break;
2373                         }
2374
2375                         /* The class can not have an automatic layout */
2376                         if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT)
2377                                 raise_auto_layout_exception (klass);
2378
2379                         if (t->attrs & PARAM_ATTRIBUTE_OUT) {
2380                                 mono_mb_emit_byte (mb, CEE_LDNULL);
2381                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
2382                                 break;
2383                         }
2384
2385                         /* Set src */
2386                         mono_mb_emit_ldarg (mb, i);
2387                         if (t->byref) {
2388                                 int pos2;
2389
2390                                 /* Check for NULL and raise an exception */
2391                                 mono_mb_emit_byte (mb, CEE_BRTRUE);
2392                                 pos2 = mb->pos;
2393                                 mono_mb_emit_i4 (mb, 0);
2394
2395                                 mono_mb_emit_exception (mb, "ArgumentNullException", NULL);
2396
2397                                 mono_mb_patch_addr (mb, pos2, mb->pos - (pos2 + 4));
2398                                 mono_mb_emit_ldarg (mb, i);
2399                                 mono_mb_emit_byte (mb, CEE_LDIND_I);
2400                         }                               
2401
2402                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2403
2404                         mono_mb_emit_byte (mb, CEE_LDC_I4_0);
2405                         mono_mb_emit_stloc (mb, tmp_locals [i]);
2406
2407                         mono_mb_emit_byte (mb, CEE_LDLOC_0);
2408                         mono_mb_emit_byte (mb, CEE_BRFALSE);
2409                         pos = mb->pos;
2410                         mono_mb_emit_i4 (mb, 0);
2411
2412                         /* Create and set dst */
2413                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2414                         mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);        
2415                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2416                         mono_mb_emit_stloc (mb, tmp_locals [i]);
2417                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
2418                         mono_mb_emit_icon (mb, sizeof (MonoObject));
2419                         mono_mb_emit_byte (mb, CEE_ADD);
2420                         mono_mb_emit_byte (mb, CEE_STLOC_1); 
2421
2422                         /* emit valuetype conversion code */
2423                         emit_struct_conv (mb, klass, TRUE);
2424
2425                         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2426                         break;
2427                 }
2428                 case MONO_TYPE_VALUETYPE:
2429                         
2430                         klass = sig->params [i]->data.klass;
2431                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2432                             klass->blittable || klass->enumtype)
2433                                 break;
2434
2435                         tmp_locals [i] = mono_mb_add_local (mb, &klass->byval_arg);
2436
2437                         if (t->attrs & PARAM_ATTRIBUTE_OUT)
2438                                 break;
2439
2440                         if (t->byref) 
2441                                 mono_mb_emit_ldarg (mb, i);
2442                         else
2443                                 mono_mb_emit_ldarg_addr (mb, i);
2444                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2445
2446                         if (t->byref) {
2447                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2448                                 mono_mb_emit_byte (mb, CEE_BRFALSE);
2449                                 pos = mb->pos;
2450                                 mono_mb_emit_i4 (mb, 0);
2451                         }                       
2452
2453                         mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2454                         mono_mb_emit_byte (mb, CEE_STLOC_1);
2455
2456                         /* emit valuetype conversion code */
2457                         emit_struct_conv (mb, klass, TRUE);
2458
2459                         if (t->byref)
2460                                 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2461                         break;
2462                 case MONO_TYPE_STRING: {
2463                         MonoMarshalNative encoding = mono_marshal_get_string_encoding (NULL, spec);
2464
2465                         if (t->byref)
2466                                 continue;
2467
2468                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2469                         csig->params [i] = &mono_defaults.int_class->byval_arg;
2470
2471                         mono_mb_emit_ldarg (mb, i);
2472                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2473                         mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2474
2475                         switch (encoding) {
2476                         case MONO_NATIVE_LPWSTR:
2477                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPWSTR_STR);
2478                                 break;
2479                         case MONO_NATIVE_LPSTR:
2480                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
2481                                 break;
2482                         default: {
2483                                         char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding);
2484                                         MonoException *exc = mono_get_exception_not_implemented (msg);
2485                                         g_warning (msg);
2486                                         g_free (msg);
2487                                         mono_raise_exception (exc);
2488                                 }
2489                         }
2490
2491                         mono_mb_emit_stloc (mb, tmp_locals [i]);
2492                         break;  
2493                 }
2494                 case MONO_TYPE_ARRAY:
2495                 case MONO_TYPE_SZARRAY:
2496                         if (t->byref)
2497                                 continue;
2498
2499                         klass = mono_class_from_mono_type (t);
2500
2501                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2502                         csig->params [i] = &mono_defaults.int_class->byval_arg;
2503
2504                         g_warning ("array marshaling not implemented");
2505                         g_assert_not_reached ();
2506                         break;
2507                 }
2508         }
2509
2510         for (i = 0; i < sig->param_count; i++) {
2511                 MonoType *t = sig->params [i];
2512
2513                 switch (t->type) {
2514                 case MONO_TYPE_BOOLEAN:
2515                 case MONO_TYPE_I1:
2516                 case MONO_TYPE_U1:
2517                 case MONO_TYPE_I2:
2518                 case MONO_TYPE_U2:
2519                 case MONO_TYPE_I4:
2520                 case MONO_TYPE_U4:
2521                 case MONO_TYPE_I:
2522                 case MONO_TYPE_U:
2523                 case MONO_TYPE_PTR:
2524                 case MONO_TYPE_R4:
2525                 case MONO_TYPE_R8:
2526                 case MONO_TYPE_I8:
2527                 case MONO_TYPE_U8:
2528                         mono_mb_emit_ldarg (mb, i);
2529                         break;
2530                 case MONO_TYPE_STRING:
2531                         if (t->byref) {
2532                                 mono_mb_emit_ldarg (mb, i);
2533                         } else {
2534                                 g_assert (tmp_locals [i]);
2535                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2536                         }
2537                         break;  
2538                 case MONO_TYPE_CLASS:  
2539                         if (t->byref)
2540                                 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2541                         else
2542                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2543                         break;
2544                 case MONO_TYPE_ARRAY:
2545                 case MONO_TYPE_SZARRAY:
2546                 case MONO_TYPE_OBJECT:
2547                         if (tmp_locals [i])
2548                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2549                         else
2550                                 mono_mb_emit_ldarg (mb, i);
2551                         break;
2552                 case MONO_TYPE_VALUETYPE:
2553                         klass = sig->params [i]->data.klass;
2554                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2555                             klass->blittable || klass->enumtype) {
2556                                 mono_mb_emit_ldarg (mb, i);
2557                                 break;
2558                         }
2559
2560                         g_assert (tmp_locals [i]);
2561                         if (t->byref)
2562                                 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2563                         else
2564                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2565                         break;
2566                 default:
2567                         g_warning ("type 0x%02x unknown", t->type);     
2568                         g_assert_not_reached ();
2569                 }
2570         }
2571
2572         emit_thread_interrupt_checkpoint (mb);
2573         mono_mb_emit_managed_call (mb, method, NULL);
2574
2575         /* Ensure that we have marshalling info for the return */
2576         mono_marshal_load_type_info (mono_class_from_mono_type (sig->ret));
2577
2578         if (!sig->ret->byref) { 
2579                 switch (sig->ret->type) {
2580                 case MONO_TYPE_VOID:
2581                         break;
2582                 case MONO_TYPE_BOOLEAN:
2583                 case MONO_TYPE_I1:
2584                 case MONO_TYPE_U1:
2585                 case MONO_TYPE_I2:
2586                 case MONO_TYPE_U2:
2587                 case MONO_TYPE_I4:
2588                 case MONO_TYPE_U4:
2589                 case MONO_TYPE_I:
2590                 case MONO_TYPE_U:
2591                 case MONO_TYPE_PTR:
2592                 case MONO_TYPE_R4:
2593                 case MONO_TYPE_R8:
2594                 case MONO_TYPE_I8:
2595                 case MONO_TYPE_U8:
2596                 case MONO_TYPE_OBJECT:
2597                         mono_mb_emit_byte (mb, CEE_STLOC_3);
2598                         break;
2599                 case MONO_TYPE_STRING:          
2600                         csig->ret = &mono_defaults.int_class->byval_arg;
2601
2602                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2603                         mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2604                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
2605                         mono_mb_emit_byte (mb, CEE_STLOC_3);
2606                         break;
2607                 case MONO_TYPE_VALUETYPE:
2608                         klass = sig->ret->data.klass;
2609                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2610                             klass->blittable || klass->enumtype)
2611                                 break;
2612                         
2613                         /* load pointer to returned value type */
2614                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2615                         mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
2616                         
2617                         /* store the address of the source into local variable 0 */
2618                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2619                         /* allocate space for the native struct and
2620                          * store the address into dst_ptr */
2621                         retobj_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2622                         g_assert (retobj_var);
2623                         mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2624                         mono_mb_emit_byte (mb, CEE_CONV_I);
2625                         mono_mb_emit_native_call (mb, alloc_sig, mono_marshal_alloc);
2626                         emit_thread_interrupt_checkpoint (mb);
2627                         mono_mb_emit_byte (mb, CEE_STLOC_1);
2628                         mono_mb_emit_byte (mb, CEE_LDLOC_1);
2629                         mono_mb_emit_stloc (mb, retobj_var);
2630
2631                         /* emit valuetype conversion code */
2632                         emit_struct_conv (mb, klass, FALSE);
2633                         break;
2634                 case MONO_TYPE_CLASS: {
2635                         int pos2;
2636
2637                         klass = sig->ret->data.klass;
2638
2639                         if (klass->delegate) {
2640                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2641                                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2642                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_DEL_FTN);
2643                                 mono_mb_emit_byte (mb, CEE_STLOC_3);
2644                                 break;
2645                         }
2646
2647                         /* The class can not have an automatic layout */
2648                         if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT)
2649                                 raise_auto_layout_exception (klass);
2650
2651                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2652                         /* Check for null */
2653                         mono_mb_emit_byte (mb, CEE_LDLOC_0);
2654                         pos = mono_mb_emit_branch (mb, CEE_BRTRUE);
2655                         mono_mb_emit_byte (mb, CEE_LDNULL);
2656                         mono_mb_emit_byte (mb, CEE_STLOC_3);
2657                         pos2 = mono_mb_emit_branch (mb, CEE_BR);
2658
2659                         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2660
2661                         /* Set src */
2662                         mono_mb_emit_byte (mb, CEE_LDLOC_0);
2663                         mono_mb_emit_icon (mb, sizeof (MonoObject));
2664                         mono_mb_emit_byte (mb, CEE_ADD);
2665                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2666
2667                         /* Allocate and set dest */
2668                         mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2669                         mono_mb_emit_byte (mb, CEE_CONV_I);
2670                         mono_mb_emit_native_call (mb, alloc_sig, mono_marshal_alloc);
2671                         emit_thread_interrupt_checkpoint (mb);
2672                         mono_mb_emit_byte (mb, CEE_DUP);
2673                         mono_mb_emit_byte (mb, CEE_STLOC_1);
2674                         mono_mb_emit_byte (mb, CEE_STLOC_3);
2675
2676                         emit_struct_conv (mb, klass, FALSE);
2677
2678                         mono_mb_patch_addr (mb, pos2, mb->pos - (pos2 + 4));
2679                         break;
2680                 }
2681                 default:
2682                         g_warning ("return type 0x%02x unknown", sig->ret->type);       
2683                         g_assert_not_reached ();
2684                 }
2685         } else {
2686                 mono_mb_emit_byte (mb, CEE_STLOC_3);
2687         }
2688
2689         /* Convert byref arguments back */
2690         for (i = 0; i < sig->param_count; i ++) {
2691                 MonoType *t = sig->params [i];
2692
2693                 if (!t->byref)
2694                         continue;
2695
2696                 switch (t->type) {
2697                 case MONO_TYPE_CLASS: {
2698                         int pos2;
2699
2700                         klass = t->data.klass;
2701
2702                         /* Check for null */
2703                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
2704                         pos = mono_mb_emit_branch (mb, CEE_BRTRUE);
2705                         mono_mb_emit_ldarg (mb, i);
2706                         mono_mb_emit_byte (mb, CEE_LDC_I4_0);
2707                         mono_mb_emit_byte (mb, CEE_STIND_I);
2708                         pos2 = mono_mb_emit_branch (mb, CEE_BR);
2709
2710                         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));                      
2711                         
2712                         /* Set src */
2713                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
2714                         mono_mb_emit_icon (mb, sizeof (MonoObject));
2715                         mono_mb_emit_byte (mb, CEE_ADD);
2716                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2717
2718                         /* Allocate and set dest */
2719                         mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2720                         mono_mb_emit_byte (mb, CEE_CONV_I);
2721                         mono_mb_emit_native_call (mb, alloc_sig, mono_marshal_alloc);
2722                         emit_thread_interrupt_checkpoint (mb);
2723                         mono_mb_emit_byte (mb, CEE_STLOC_1);
2724
2725                         /* Update argument pointer */
2726                         mono_mb_emit_ldarg (mb, i);
2727                         mono_mb_emit_byte (mb, CEE_LDLOC_1);
2728                         mono_mb_emit_byte (mb, CEE_STIND_I);
2729
2730                         /* emit valuetype conversion code */
2731                         emit_struct_conv (mb, klass, FALSE);
2732
2733                         mono_mb_patch_addr (mb, pos2, mb->pos - (pos2 + 4));
2734                         break;
2735                 }
2736                 case MONO_TYPE_VALUETYPE: {
2737                         int pos2;
2738
2739                         klass = t->data.klass;
2740
2741                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2742                             klass->blittable || klass->enumtype) {
2743                                 break;
2744                         }
2745
2746                         /* Check for null */
2747                         mono_mb_emit_ldarg (mb, i);
2748                         pos2 = mono_mb_emit_branch (mb, CEE_BRFALSE);
2749
2750                         /* Set src */
2751                         mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2752                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2753
2754                         /* Set dest */
2755                         mono_mb_emit_ldarg (mb, i);
2756                         mono_mb_emit_byte (mb, CEE_STLOC_1);
2757
2758                         /* emit valuetype conversion code */
2759                         emit_struct_conv (mb, klass, FALSE);
2760
2761                         mono_mb_patch_addr (mb, pos2, mb->pos - (pos2 + 4));
2762                         break;
2763                 }
2764                 }
2765         }
2766
2767         if (retobj_var) {
2768                 mono_mb_emit_ldloc (mb, retobj_var);
2769                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2770                 mono_mb_emit_byte (mb, CEE_MONO_RETOBJ);
2771                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2772         }
2773         else {
2774                 if (!MONO_TYPE_IS_VOID(sig->ret))
2775                         mono_mb_emit_byte (mb, CEE_LDLOC_3);
2776                 mono_mb_emit_byte (mb, CEE_RET);
2777         }
2778
2779         if (!this)
2780                 res = mono_mb_create_and_cache (cache, method,
2781                                                                                          mb, csig, sig->param_count + 16);
2782         else
2783                 res = mono_mb_create_method (mb, csig, sig->param_count + 16);
2784         mono_mb_free (mb);
2785
2786         /* 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)); */
2787
2788         return res;
2789 }
2790
2791 /*
2792  * mono_marshal_get_ldfld_wrapper:
2793  * @type: the type of the field
2794  *
2795  * This method generates a function which can be use to load a field with type
2796  * @type from an object. The generated function has the following signature:
2797  * <@type> ldfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset)
2798  */
2799 MonoMethod *
2800 mono_marshal_get_ldfld_wrapper (MonoType *type)
2801 {
2802         MonoMethodSignature *sig, *csig;
2803         MonoMethodBuilder *mb;
2804         MonoMethod *res;
2805         MonoClass *klass;
2806         static GHashTable *ldfld_hash = NULL; 
2807         char *name;
2808         int t, pos0, pos1 = 0;
2809
2810         t = type->type;
2811
2812         if (!type->byref) {
2813                 if (type->type == MONO_TYPE_SZARRAY) {
2814                         klass = mono_defaults.array_class;
2815                 } else if (type->type == MONO_TYPE_VALUETYPE) {
2816                         klass = type->data.klass;
2817                         if (klass->enumtype) {
2818                                 t = klass->enum_basetype->type;
2819                                 klass = mono_class_from_mono_type (klass->enum_basetype);
2820                         }
2821                 } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
2822                            t == MONO_TYPE_CLASS) { 
2823                         klass = mono_defaults.object_class;
2824                 } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
2825                         klass = mono_defaults.int_class;
2826                 } else {
2827                         klass = mono_class_from_mono_type (type);                       
2828                 }
2829         } else {
2830                 klass = mono_defaults.int_class;
2831         }
2832
2833         EnterCriticalSection (&marshal_mutex);
2834         if (!ldfld_hash) 
2835                 ldfld_hash = g_hash_table_new (NULL, NULL);
2836         res = g_hash_table_lookup (ldfld_hash, klass);
2837         LeaveCriticalSection (&marshal_mutex);
2838         if (res)
2839                 return res;
2840
2841         name = g_strdup_printf ("__ldfld_wrapper_%s.%s", klass->name_space, klass->name); 
2842         mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_LDFLD);
2843         g_free (name);
2844
2845         mb->method->save_lmf = 1;
2846
2847         sig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
2848         sig->params [0] = &mono_defaults.object_class->byval_arg;
2849         sig->params [1] = &mono_defaults.int_class->byval_arg;
2850         sig->params [2] = &mono_defaults.int_class->byval_arg;
2851         sig->params [3] = &mono_defaults.int_class->byval_arg;
2852         sig->ret = &klass->byval_arg;
2853
2854         mono_mb_emit_ldarg (mb, 0);
2855         pos0 = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
2856
2857         mono_mb_emit_ldarg (mb, 0);
2858         mono_mb_emit_ldarg (mb, 1);
2859         mono_mb_emit_ldarg (mb, 2);
2860
2861         csig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
2862         csig->params [0] = &mono_defaults.object_class->byval_arg;
2863         csig->params [1] = &mono_defaults.int_class->byval_arg;
2864         csig->params [2] = &mono_defaults.int_class->byval_arg;
2865         csig->ret = &klass->this_arg;
2866         csig->pinvoke = 1;
2867
2868         mono_mb_emit_native_call (mb, csig, mono_load_remote_field_new);
2869         emit_thread_interrupt_checkpoint (mb);
2870
2871         if (klass->valuetype) {
2872                 mono_mb_emit_byte (mb, CEE_UNBOX);
2873                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));             
2874                 mono_mb_emit_byte (mb, CEE_BR);
2875                 pos1 = mb->pos;
2876                 mono_mb_emit_i4 (mb, 0);
2877         } else {
2878                 mono_mb_emit_byte (mb, CEE_RET);
2879         }
2880
2881
2882         mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
2883
2884         mono_mb_emit_ldarg (mb, 0);
2885         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2886         mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2887         mono_mb_emit_ldarg (mb, 3);
2888         mono_mb_emit_byte (mb, CEE_ADD);
2889
2890         if (klass->valuetype)
2891                 mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
2892
2893         switch (t) {
2894         case MONO_TYPE_I1:
2895         case MONO_TYPE_U1:
2896         case MONO_TYPE_BOOLEAN:
2897                 mono_mb_emit_byte (mb, CEE_LDIND_I1);
2898                 break;
2899         case MONO_TYPE_CHAR:
2900         case MONO_TYPE_I2:
2901         case MONO_TYPE_U2:
2902                 mono_mb_emit_byte (mb, CEE_LDIND_I2);
2903                 break;
2904         case MONO_TYPE_I4:
2905         case MONO_TYPE_U4:
2906                 mono_mb_emit_byte (mb, CEE_LDIND_I4);
2907                 break;
2908         case MONO_TYPE_I8:
2909         case MONO_TYPE_U8:
2910                 mono_mb_emit_byte (mb, CEE_LDIND_I8);
2911                 break;
2912         case MONO_TYPE_R4:
2913                 mono_mb_emit_byte (mb, CEE_LDIND_R4);
2914                 break;
2915         case MONO_TYPE_R8:
2916                 mono_mb_emit_byte (mb, CEE_LDIND_R8);
2917                 break;
2918         case MONO_TYPE_ARRAY:
2919         case MONO_TYPE_PTR:
2920         case MONO_TYPE_FNPTR:
2921         case MONO_TYPE_SZARRAY:
2922         case MONO_TYPE_OBJECT:
2923         case MONO_TYPE_CLASS:
2924         case MONO_TYPE_STRING:
2925         case MONO_TYPE_I:
2926         case MONO_TYPE_U:
2927                 mono_mb_emit_byte (mb, CEE_LDIND_I);
2928                 break;
2929         case MONO_TYPE_VALUETYPE:
2930                 g_assert (!klass->enumtype);
2931                 mono_mb_emit_byte (mb, CEE_LDOBJ);
2932                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2933                 break;
2934         default:
2935                 g_warning ("type %x not implemented", type->type);
2936                 g_assert_not_reached ();
2937         }
2938
2939         mono_mb_emit_byte (mb, CEE_RET);
2940        
2941         res = mono_mb_create_and_cache (ldfld_hash, klass,
2942                                                                                  mb, sig, sig->param_count + 16);
2943         mono_mb_free (mb);
2944         
2945         return res;
2946 }
2947
2948 /*
2949  * mono_marshal_get_stfld_wrapper:
2950  * @type: the type of the field
2951  *
2952  * This method generates a function which can be use to store a field with type
2953  * @type. The generated function has the following signature:
2954  * void stfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset, <@type> val)
2955  */
2956 MonoMethod *
2957 mono_marshal_get_stfld_wrapper (MonoType *type)
2958 {
2959         MonoMethodSignature *sig, *csig;
2960         MonoMethodBuilder *mb;
2961         MonoMethod *res;
2962         MonoClass *klass;
2963         static GHashTable *stfld_hash = NULL; 
2964         char *name;
2965         int t, pos;
2966
2967         t = type->type;
2968
2969         if (!type->byref) {
2970                 if (type->type == MONO_TYPE_SZARRAY) {
2971                         klass = mono_defaults.array_class;
2972                 } else if (type->type == MONO_TYPE_VALUETYPE) {
2973                         klass = type->data.klass;
2974                         if (klass->enumtype) {
2975                                 t = klass->enum_basetype->type;
2976                                 klass = mono_class_from_mono_type (klass->enum_basetype);
2977                         }
2978                 } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
2979                            t == MONO_TYPE_CLASS) { 
2980                         klass = mono_defaults.object_class;
2981                 } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
2982                         klass = mono_defaults.int_class;
2983                 } else {
2984                         klass = mono_class_from_mono_type (type);                       
2985                 }
2986         } else {
2987                 klass = mono_defaults.int_class;
2988         }
2989
2990         EnterCriticalSection (&marshal_mutex);
2991         if (!stfld_hash) 
2992                 stfld_hash = g_hash_table_new (NULL, NULL);
2993         res = g_hash_table_lookup (stfld_hash, klass);
2994         LeaveCriticalSection (&marshal_mutex);
2995         if (res)
2996                 return res;
2997
2998         name = g_strdup_printf ("__stfld_wrapper_%s.%s", klass->name_space, klass->name); 
2999         mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_STFLD);
3000         g_free (name);
3001
3002         mb->method->save_lmf = 1;
3003
3004         sig = mono_metadata_signature_alloc (mono_defaults.corlib, 5);
3005         sig->params [0] = &mono_defaults.object_class->byval_arg;
3006         sig->params [1] = &mono_defaults.int_class->byval_arg;
3007         sig->params [2] = &mono_defaults.int_class->byval_arg;
3008         sig->params [3] = &mono_defaults.int_class->byval_arg;
3009         sig->params [4] = &klass->byval_arg;
3010         sig->ret = &mono_defaults.void_class->byval_arg;
3011
3012         mono_mb_emit_ldarg (mb, 0);
3013         pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
3014
3015         mono_mb_emit_ldarg (mb, 0);
3016         mono_mb_emit_ldarg (mb, 1);
3017         mono_mb_emit_ldarg (mb, 2);
3018         mono_mb_emit_ldarg (mb, 4);
3019
3020         if (klass->valuetype) {
3021                 mono_mb_emit_byte (mb, CEE_BOX);
3022                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));             
3023         }
3024
3025         csig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
3026         csig->params [0] = &mono_defaults.object_class->byval_arg;
3027         csig->params [1] = &mono_defaults.int_class->byval_arg;
3028         csig->params [2] = &mono_defaults.int_class->byval_arg;
3029         csig->params [3] = &klass->this_arg;
3030         csig->ret = &mono_defaults.void_class->byval_arg;
3031         csig->pinvoke = 1;
3032
3033         mono_mb_emit_native_call (mb, csig, mono_store_remote_field_new);
3034         emit_thread_interrupt_checkpoint (mb);
3035
3036         mono_mb_emit_byte (mb, CEE_RET);
3037
3038         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3039
3040         mono_mb_emit_ldarg (mb, 0);
3041         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3042         mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
3043         mono_mb_emit_ldarg (mb, 3);
3044         mono_mb_emit_byte (mb, CEE_ADD);
3045         mono_mb_emit_ldarg (mb, 4);
3046
3047         switch (t) {
3048         case MONO_TYPE_I1:
3049         case MONO_TYPE_U1:
3050         case MONO_TYPE_BOOLEAN:
3051                 mono_mb_emit_byte (mb, CEE_STIND_I1);
3052                 break;
3053         case MONO_TYPE_CHAR:
3054         case MONO_TYPE_I2:
3055         case MONO_TYPE_U2:
3056                 mono_mb_emit_byte (mb, CEE_STIND_I2);
3057                 break;
3058         case MONO_TYPE_I4:
3059         case MONO_TYPE_U4:
3060                 mono_mb_emit_byte (mb, CEE_STIND_I4);
3061                 break;
3062         case MONO_TYPE_I8:
3063         case MONO_TYPE_U8:
3064                 mono_mb_emit_byte (mb, CEE_STIND_I8);
3065                 break;
3066         case MONO_TYPE_R4:
3067                 mono_mb_emit_byte (mb, CEE_STIND_R4);
3068                 break;
3069         case MONO_TYPE_R8:
3070                 mono_mb_emit_byte (mb, CEE_STIND_R8);
3071                 break;
3072         case MONO_TYPE_ARRAY:
3073         case MONO_TYPE_PTR:
3074         case MONO_TYPE_FNPTR:
3075         case MONO_TYPE_SZARRAY:
3076         case MONO_TYPE_OBJECT:
3077         case MONO_TYPE_CLASS:
3078         case MONO_TYPE_STRING:
3079         case MONO_TYPE_I:
3080         case MONO_TYPE_U:
3081                 mono_mb_emit_byte (mb, CEE_STIND_I);
3082                 break;
3083         case MONO_TYPE_VALUETYPE:
3084                 g_assert (!klass->enumtype);
3085                 mono_mb_emit_byte (mb, CEE_STOBJ);
3086                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3087                 break;
3088         default:
3089                 g_warning ("type %x not implemented", type->type);
3090                 g_assert_not_reached ();
3091         }
3092
3093         mono_mb_emit_byte (mb, CEE_RET);
3094        
3095         res = mono_mb_create_and_cache (stfld_hash, klass,
3096                                                                         mb, sig, sig->param_count + 16);
3097         mono_mb_free (mb);
3098         
3099         return res;
3100 }
3101
3102 /*
3103  * generates IL code for the icall wrapper (the generated method
3104  * calls the unmanaged code in func)
3105  */
3106 MonoMethod *
3107 mono_marshal_get_icall_wrapper (MonoMethodSignature *sig, const char *name, gconstpointer func)
3108 {
3109         MonoMethodSignature *csig;
3110         MonoMethodBuilder *mb;
3111         MonoMethod *res;
3112         int i;
3113         
3114         g_assert (sig->pinvoke);
3115
3116         mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_MANAGED_TO_NATIVE);
3117
3118         mb->method->save_lmf = 1;
3119
3120         /* we copy the signature, so that we can modify it */
3121
3122         if (sig->hasthis)
3123                 mono_mb_emit_byte (mb, CEE_LDARG_0);
3124
3125         for (i = 0; i < sig->param_count; i++)
3126                 mono_mb_emit_ldarg (mb, i + sig->hasthis);
3127
3128         mono_mb_emit_native_call (mb, sig, (gpointer) func);
3129         emit_thread_interrupt_checkpoint (mb);
3130         mono_mb_emit_byte (mb, CEE_RET);
3131
3132         csig = mono_metadata_signature_dup (sig);
3133         csig->pinvoke = 0;
3134
3135         res = mono_mb_create_method (mb, csig, csig->param_count + 16);
3136         mono_mb_free (mb);
3137         
3138         return res;
3139 }
3140
3141 /**
3142  * mono_marshal_get_native_wrapper:
3143  * @method: The MonoMethod to wrap.
3144  *
3145  * generates IL code for the pinvoke wrapper (the generated method
3146  * calls the unmanaged code in method->addr)
3147  */
3148 MonoMethod *
3149 mono_marshal_get_native_wrapper (MonoMethod *method)
3150 {
3151         MonoMethodSignature *sig, *csig;
3152         MonoMethodPInvoke *piinfo;
3153         MonoMethodBuilder *mb;
3154         MonoMarshalSpec **mspecs;
3155         MonoMethod *res;
3156         GHashTable *cache;
3157         MonoClass *klass;
3158         gboolean pinvoke = FALSE;
3159         int i, pos, argnum, *tmp_locals;
3160         int type;
3161         const char *exc_class = "MissingMethodException";
3162         const char *exc_arg = NULL;
3163
3164         g_assert (method != NULL);
3165         g_assert (method->signature->pinvoke);
3166
3167         cache = method->klass->image->native_wrapper_cache;
3168         if ((res = mono_marshal_find_in_cache (cache, method)))
3169                 return res;
3170
3171         sig = method->signature;
3172
3173         if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
3174             (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
3175                 pinvoke = TRUE;
3176
3177         if (!method->addr) {
3178                 if (pinvoke)
3179                         mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
3180                 else
3181                         method->addr = mono_lookup_internal_call (method);
3182         }
3183
3184         mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_MANAGED_TO_NATIVE);
3185
3186         mb->method->save_lmf = 1;
3187
3188         piinfo = (MonoMethodPInvoke *)method;
3189
3190         if (!method->addr) {
3191                 mono_mb_emit_exception (mb, exc_class, exc_arg);
3192                 csig = mono_metadata_signature_dup (sig);
3193                 csig->pinvoke = 0;
3194                 res = mono_mb_create_and_cache (cache, method,
3195                                                                                 mb, csig, csig->param_count + 16);
3196                 mono_mb_free (mb);
3197                 return res;
3198         }
3199
3200         /* internal calls: we simply push all arguments and call the method (no conversions) */
3201         if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
3202
3203                 /* hack - string constructors returns a value */
3204                 if (method->string_ctor) {
3205                         csig = mono_metadata_signature_dup (sig);
3206                         csig->ret = &mono_defaults.string_class->byval_arg;
3207                 } else
3208                         csig = sig;
3209
3210                 if (sig->hasthis)
3211                         mono_mb_emit_byte (mb, CEE_LDARG_0);
3212
3213                 for (i = 0; i < sig->param_count; i++)
3214                         mono_mb_emit_ldarg (mb, i + sig->hasthis);
3215
3216                 g_assert (method->addr);
3217                 mono_mb_emit_native_call (mb, csig, method->addr);
3218                 emit_thread_interrupt_checkpoint (mb);
3219                 mono_mb_emit_byte (mb, CEE_RET);
3220
3221                 csig = mono_metadata_signature_dup (csig);
3222                 csig->pinvoke = 0;
3223                 res = mono_mb_create_and_cache (cache, method,
3224                                                                                 mb, csig, csig->param_count + 16);
3225                 mono_mb_free (mb);
3226                 return res;
3227         }
3228
3229         g_assert (pinvoke);
3230
3231         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
3232         mono_method_get_marshal_info (method, mspecs);
3233
3234         /* pinvoke: we need to convert the arguments if necessary */
3235
3236         /* we copy the signature, so that we can set pinvoke to 0 */
3237         csig = mono_metadata_signature_dup (sig);
3238         csig->pinvoke = 1;
3239
3240         /* we allocate local for use with emit_struct_conv() */
3241         /* allocate local 0 (pointer) src_ptr */
3242         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3243         /* allocate local 1 (pointer) dst_ptr */
3244         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3245         /* allocate local 2 (boolean) delete_old */
3246         mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
3247
3248         /* delete_old = FALSE */
3249         mono_mb_emit_icon (mb, 0);
3250         mono_mb_emit_byte (mb, CEE_STLOC_2);
3251
3252         if (!MONO_TYPE_IS_VOID(sig->ret)) {
3253                 /* allocate local 3 to store the return value */
3254                 mono_mb_add_local (mb, sig->ret);
3255         }
3256
3257         if (mspecs [0] && mspecs [0]->native == MONO_NATIVE_CUSTOM) {
3258                 /* Return type custom marshaling */
3259                 /*
3260                  * Since we can't determine the return type of the unmanaged function,
3261                  * we assume it returns a pointer, and pass that pointer to
3262                  * MarshalNativeToManaged.
3263                  */
3264                 csig->ret = &mono_defaults.int_class->byval_arg;
3265         }
3266
3267         /* we first do all conversions */
3268         tmp_locals = alloca (sizeof (int) * sig->param_count);
3269
3270         for (i = 0; i < sig->param_count; i ++) {
3271                 MonoType *t = sig->params [i];
3272                 MonoMarshalSpec *spec = mspecs [i + 1];
3273
3274                 argnum = i + sig->hasthis;
3275                 tmp_locals [i] = 0;
3276
3277                 /* Ensure that we have marshalling info for this param */
3278                 mono_marshal_load_type_info (mono_class_from_mono_type (t));
3279
3280                 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
3281                         MonoType *mtype;
3282                         MonoClass *mklass;
3283                         MonoMethod *marshal_managed_to_native;
3284                         MonoMethod *get_instance;
3285
3286                         /* FIXME: Call CleanUpNativeData after the call */
3287
3288                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
3289                         g_assert (mtype != NULL);
3290                         mklass = mono_class_from_mono_type (mtype);
3291                         g_assert (mklass != NULL);
3292
3293                         marshal_managed_to_native = mono_find_method_by_name (mklass, "MarshalManagedToNative", 1);
3294                         g_assert (marshal_managed_to_native);
3295                         get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
3296                         g_assert (get_instance);
3297                         
3298                         switch (t->type) {
3299                         case MONO_TYPE_CLASS:
3300                         case MONO_TYPE_OBJECT:
3301                         case MONO_TYPE_STRING:
3302                         case MONO_TYPE_ARRAY:
3303                         case MONO_TYPE_SZARRAY:
3304                         case MONO_TYPE_VALUETYPE:
3305                                 if (t->byref)
3306                                         break;
3307
3308                                 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3309
3310                                 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
3311
3312                                 mono_mb_emit_byte (mb, CEE_CALL);
3313                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
3314                                 
3315                                 mono_mb_emit_ldarg (mb, argnum);
3316
3317                                 if (t->type == MONO_TYPE_VALUETYPE) {
3318                                         /*
3319                                          * Since we can't determine the type of the argument, we
3320                                          * will assume the unmanaged function takes a pointer.
3321                                          */
3322                                         csig->params [i] = &mono_defaults.int_class->byval_arg;
3323
3324                                         mono_mb_emit_byte (mb, CEE_BOX);
3325                                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (t)));
3326                                 }
3327
3328                                 mono_mb_emit_byte (mb, CEE_CALLVIRT);
3329                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_managed_to_native));
3330
3331                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
3332                                 break;
3333
3334                         default:
3335                                 g_warning ("custom marshalling of type %x is currently not supported", t->type);
3336                                 g_assert_not_reached ();
3337                                 break;
3338                         }
3339                         continue;
3340                 }
3341
3342                 if (spec && spec->native == MONO_NATIVE_ASANY) {
3343                         MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, NULL);
3344
3345                         g_assert (t->type == MONO_TYPE_OBJECT);
3346                         g_assert (!t->byref);
3347
3348                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3349                         mono_mb_emit_ldarg (mb, argnum);
3350                         mono_mb_emit_icon (mb, encoding);
3351                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3352                         mono_mb_emit_byte (mb, CEE_MONO_FUNC2);
3353                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_ASANY);
3354                         mono_mb_emit_stloc (mb, tmp_locals [i]);
3355                         continue;
3356                 }
3357                         
3358                 switch (t->type) {
3359                 case MONO_TYPE_VALUETYPE:                       
3360                         klass = t->data.klass;
3361
3362                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3363                             klass->blittable || klass->enumtype)
3364                                 break;
3365
3366                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3367                         
3368                         /* store the address of the source into local variable 0 */
3369                         if (t->byref)
3370                                 mono_mb_emit_ldarg (mb, argnum);
3371                         else
3372                                 mono_mb_emit_ldarg_addr (mb, argnum);
3373
3374                         mono_mb_emit_byte (mb, CEE_STLOC_0);
3375                         
3376                         /* allocate space for the native struct and
3377                          * store the address into local variable 1 (dest) */
3378                         mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
3379                         mono_mb_emit_byte (mb, CEE_PREFIX1);
3380                         mono_mb_emit_byte (mb, CEE_LOCALLOC);
3381                         mono_mb_emit_stloc (mb, tmp_locals [i]);
3382
3383                         if (t->byref) {
3384                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3385                                 mono_mb_emit_byte (mb, CEE_BRFALSE);
3386                                 pos = mb->pos;
3387                                 mono_mb_emit_i4 (mb, 0);
3388                         }
3389
3390                         /* set dst_ptr */
3391                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
3392                         mono_mb_emit_byte (mb, CEE_STLOC_1);
3393
3394                         /* emit valuetype conversion code */
3395                         emit_struct_conv (mb, klass, FALSE);
3396                         
3397                         if (t->byref)
3398                                 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3399                         break;
3400                 case MONO_TYPE_STRING: {
3401                         MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, spec);
3402
3403                         csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3404                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3405
3406                         if (t->byref) {
3407                                 if (t->attrs & PARAM_ATTRIBUTE_OUT)
3408                                         break;
3409
3410                                 mono_mb_emit_ldarg (mb, argnum);
3411                                 mono_mb_emit_byte (mb, CEE_LDIND_I);                            
3412                         } else {
3413                                 mono_mb_emit_ldarg (mb, argnum);
3414                         }
3415
3416                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3417                         mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3418                         
3419                         switch (encoding) {
3420                         case MONO_NATIVE_LPWSTR:
3421                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPWSTR);
3422                                 break;
3423                         case MONO_NATIVE_LPSTR:
3424                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
3425                                 break;
3426                         case MONO_NATIVE_LPTSTR:
3427                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPTSTR);
3428                                 break;
3429                         default: {
3430                                         char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding);
3431                                         MonoException *exc = mono_get_exception_not_implemented (msg);
3432                                         g_warning (msg);
3433                                         g_free (msg);
3434                                         mono_raise_exception (exc);
3435                                 }
3436                         }
3437
3438                         mono_mb_emit_stloc (mb, tmp_locals [i]);
3439                         break;
3440                 }
3441                 case MONO_TYPE_CLASS:
3442                 case MONO_TYPE_OBJECT:
3443                         klass = t->data.klass;
3444
3445                         csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3446                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3447
3448                         if (klass->delegate) {
3449                                 g_assert (!t->byref);
3450                                 mono_mb_emit_ldarg (mb, argnum);
3451                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3452                                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3453                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_DEL_FTN);
3454                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
3455                         } else if (klass == mono_defaults.stringbuilder_class) {
3456                                 MonoMarshalNative encoding = mono_marshal_get_stringbuilder_to_ptr_encoding (piinfo, spec);
3457
3458                                 g_assert (!t->byref);
3459                                 mono_mb_emit_ldarg (mb, argnum);
3460                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3461                                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3462
3463                                 if (encoding != -1)
3464                                         mono_mb_emit_byte (mb, encoding);
3465                                 else {
3466                                         char *msg = g_strdup_printf ("stringbuilder marshalling conversion %d not implemented", encoding);
3467                                         MonoException *exc = mono_get_exception_not_implemented (msg);
3468                                         g_warning (msg);
3469                                         g_free (msg);
3470                                         mono_raise_exception (exc);
3471                                 }
3472
3473                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
3474                         } else {
3475                                 mono_mb_emit_byte (mb, CEE_LDNULL);
3476                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
3477
3478                                 if (t->byref) {
3479                                         /* we dont need any conversions for out parameters */
3480                                         if (t->attrs & PARAM_ATTRIBUTE_OUT)
3481                                                 break;
3482
3483                                         mono_mb_emit_ldarg (mb, argnum);                                
3484                                         mono_mb_emit_byte (mb, CEE_LDIND_I);
3485
3486                                 } else {
3487                                         mono_mb_emit_ldarg (mb, argnum);
3488                                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3489                                         mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
3490                                 }
3491                                 
3492                                 /* store the address of the source into local variable 0 */
3493                                 mono_mb_emit_byte (mb, CEE_STLOC_0);
3494                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3495                                 mono_mb_emit_byte (mb, CEE_BRFALSE);
3496                                 pos = mb->pos;
3497                                 mono_mb_emit_i4 (mb, 0);
3498
3499                                 /* allocate space for the native struct and store the address */
3500                                 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
3501                                 mono_mb_emit_byte (mb, CEE_PREFIX1);
3502                                 mono_mb_emit_byte (mb, CEE_LOCALLOC);
3503                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
3504                                 
3505                                 /* set the src_ptr */
3506                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3507                                 mono_mb_emit_icon (mb, sizeof (MonoObject));
3508                                 mono_mb_emit_byte (mb, CEE_ADD);
3509                                 mono_mb_emit_byte (mb, CEE_STLOC_0);
3510
3511                                 /* set dst_ptr */
3512                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3513                                 mono_mb_emit_byte (mb, CEE_STLOC_1);
3514
3515                                 /* emit valuetype conversion code */
3516                                 emit_struct_conv (mb, klass, FALSE);
3517
3518                                 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3519                         }
3520
3521                         break;
3522                 case MONO_TYPE_ARRAY:
3523                 case MONO_TYPE_SZARRAY:
3524                         if (t->byref)
3525                                 continue;
3526
3527                         klass = mono_class_from_mono_type (t);
3528
3529                         csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3530                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3531
3532                         if (klass->element_class == mono_defaults.string_class) {
3533                                 MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, spec);
3534
3535                                 mono_mb_emit_ldarg (mb, argnum);
3536                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3537                                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3538
3539                                 switch (encoding) {
3540                                 case MONO_NATIVE_LPWSTR:
3541                                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STRARRAY_STRWLPARRAY);
3542                                         break;
3543                                 case MONO_NATIVE_LPSTR:
3544                                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STRARRAY_STRLPARRAY);
3545                                         break;
3546                                 default: {
3547                                         char *msg = g_strdup_printf ("string array marshalling conversion %d not implemented", encoding);
3548                                         MonoException *exc = mono_get_exception_not_implemented (msg);
3549                                         g_warning (msg);
3550                                         g_free (msg);
3551                                         mono_raise_exception (exc);
3552                                 }
3553                                 }
3554                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
3555                         }
3556                         else if (klass->element_class->blittable) {
3557                                 mono_mb_emit_ldarg (mb, argnum);
3558                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3559                                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3560
3561                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_ARRAY_LPARRAY);
3562                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
3563                         }
3564                         else {
3565                                 MonoClass *eklass;
3566                                 guint32 label1, label2, label3;
3567                                 int index_var, dest_ptr, esize;
3568                                 MonoMarshalNative encoding = mono_marshal_get_stringbuilder_to_ptr_encoding (piinfo, spec);
3569
3570                                 dest_ptr = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3571
3572                                 eklass = klass->element_class;
3573
3574                                 /* Check null */
3575                                 mono_mb_emit_ldarg (mb, argnum);
3576                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
3577                                 mono_mb_emit_ldarg (mb, argnum);
3578                                 mono_mb_emit_byte (mb, CEE_BRFALSE);
3579                                 label1 = mb->pos;
3580                                 mono_mb_emit_i4 (mb, 0);
3581
3582                                 if (eklass == mono_defaults.stringbuilder_class) {
3583                                         if (encoding == -1) {
3584                                                 char *msg = g_strdup_printf ("stringbuilder marshalling conversion %d not implemented", encoding);
3585                                                 MonoException *exc = mono_get_exception_not_implemented (msg);
3586                                                 g_warning (msg);
3587                                                 g_free (msg);
3588                                                 mono_raise_exception (exc);
3589                                         }
3590                                 }
3591
3592                                 if (eklass == mono_defaults.stringbuilder_class)
3593                                         esize = sizeof (gpointer);
3594                                 else
3595                                         esize = mono_class_native_size (eklass, NULL);
3596
3597                                 /* allocate space for the native struct and store the address */
3598                                 mono_mb_emit_icon (mb, esize);
3599                                 mono_mb_emit_ldarg (mb, argnum);
3600                                 mono_mb_emit_byte (mb, CEE_LDLEN);
3601                                 mono_mb_emit_byte (mb, CEE_MUL);
3602                                 mono_mb_emit_byte (mb, CEE_PREFIX1);
3603                                 mono_mb_emit_byte (mb, CEE_LOCALLOC);
3604                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
3605
3606                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3607                                 mono_mb_emit_stloc (mb, dest_ptr);
3608
3609                                 /* Emit marshalling loop */
3610                                 index_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);                                
3611                                 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
3612                                 mono_mb_emit_stloc (mb, index_var);
3613                                 label2 = mb->pos;
3614                                 mono_mb_emit_ldloc (mb, index_var);
3615                                 mono_mb_emit_ldarg (mb, argnum);
3616                                 mono_mb_emit_byte (mb, CEE_LDLEN);
3617                                 mono_mb_emit_byte (mb, CEE_BGE);
3618                                 label3 = mb->pos;
3619                                 mono_mb_emit_i4 (mb, 0);
3620
3621                                 /* Emit marshalling code */
3622
3623                                 if (eklass == mono_defaults.stringbuilder_class) {
3624                                         mono_mb_emit_ldloc (mb, dest_ptr);
3625                                         mono_mb_emit_ldarg (mb, argnum);
3626                                         mono_mb_emit_ldloc (mb, index_var);
3627                                         mono_mb_emit_byte (mb, CEE_LDELEM_REF);
3628                                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3629                                         mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3630                                         mono_mb_emit_byte (mb, encoding);
3631                                         mono_mb_emit_byte (mb, CEE_STIND_I);
3632                                 }
3633                                 else {
3634                                         /* set the src_ptr */
3635                                         mono_mb_emit_ldarg (mb, argnum);
3636                                         mono_mb_emit_ldloc (mb, index_var);
3637                                         mono_mb_emit_byte (mb, CEE_LDELEMA);
3638                                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eklass));
3639                                         mono_mb_emit_byte (mb, CEE_STLOC_0);
3640
3641                                         /* set dst_ptr */
3642                                         mono_mb_emit_ldloc (mb, dest_ptr);
3643                                         mono_mb_emit_byte (mb, CEE_STLOC_1);
3644
3645                                         /* emit valuetype conversion code */
3646                                         emit_struct_conv (mb, eklass, FALSE);
3647                                 }
3648
3649                                 mono_mb_emit_add_to_local (mb, index_var, 1);
3650                                 mono_mb_emit_add_to_local (mb, dest_ptr, esize);
3651
3652                                 mono_mb_emit_byte (mb, CEE_BR);
3653                                 mono_mb_emit_i4 (mb, label2 - (mb->pos + 4));
3654
3655                                 mono_mb_patch_addr (mb, label1, mb->pos - (label1 + 4));
3656                                 mono_mb_patch_addr (mb, label3, mb->pos - (label3 + 4));
3657                         }
3658
3659                         break;
3660                 case MONO_TYPE_BOOLEAN: {
3661                         MonoType *local_type;
3662                         int variant_bool = 0;
3663                         if (!t->byref)
3664                                 continue;
3665                         if (spec == NULL) {
3666                                 local_type = &mono_defaults.int32_class->byval_arg;
3667                         } else {
3668                                 switch (spec->native) {
3669                                 case MONO_NATIVE_I1:
3670                                         local_type = &mono_defaults.byte_class->byval_arg;
3671                                         break;
3672                                 case MONO_NATIVE_VARIANTBOOL:
3673                                         local_type = &mono_defaults.int16_class->byval_arg;
3674                                         variant_bool = 1;
3675                                         break;
3676                                 default:
3677                                         g_warning ("marshalling bool as native type %x is currently not supported", spec->native);
3678                                 break;
3679                                 }
3680                         }
3681                         csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3682                         tmp_locals [i] = mono_mb_add_local (mb, local_type);
3683                         mono_mb_emit_ldarg (mb, argnum);
3684                         mono_mb_emit_byte (mb, CEE_LDIND_I1);
3685                         if (variant_bool)
3686                                 mono_mb_emit_byte (mb, CEE_NEG);
3687                         mono_mb_emit_stloc (mb, tmp_locals [i]);
3688                         break;
3689                 }
3690                 }
3691         }
3692
3693         /* push all arguments */
3694
3695         if (sig->hasthis)
3696                 mono_mb_emit_byte (mb, CEE_LDARG_0);
3697
3698         for (i = 0; i < sig->param_count; i++) {
3699                 MonoType *t = sig->params [i];
3700                 MonoMarshalSpec *spec = mspecs [i + 1];
3701
3702                 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
3703                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
3704                 }
3705                 else
3706                 if (spec && spec->native == MONO_NATIVE_ASANY) {
3707                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
3708                 }
3709                 else {
3710                         argnum = i + sig->hasthis;
3711
3712                         switch (t->type) {
3713                         case MONO_TYPE_BOOLEAN:
3714                                 if (t->byref) {
3715                                         g_assert (tmp_locals [i]);
3716                                         mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
3717                                 } else
3718                                         mono_mb_emit_ldarg (mb, argnum);
3719                                 break;
3720                         case MONO_TYPE_I1:
3721                         case MONO_TYPE_U1:
3722                         case MONO_TYPE_I2:
3723                         case MONO_TYPE_U2:
3724                         case MONO_TYPE_I4:
3725                         case MONO_TYPE_U4:
3726                         case MONO_TYPE_I:
3727                         case MONO_TYPE_U:
3728                         case MONO_TYPE_PTR:
3729                         case MONO_TYPE_R4:
3730                         case MONO_TYPE_R8:
3731                         case MONO_TYPE_I8:
3732                         case MONO_TYPE_U8:
3733                                 mono_mb_emit_ldarg (mb, argnum);
3734                                 break;
3735                         case MONO_TYPE_VALUETYPE:
3736                                 klass = sig->params [i]->data.klass;
3737                                 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3738                                         klass->blittable || klass->enumtype) {
3739                                         mono_mb_emit_ldarg (mb, argnum);
3740                                         break;
3741                                 }                       
3742                                 g_assert (tmp_locals [i]);
3743                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3744                                 if (!t->byref) {
3745                                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3746                                         mono_mb_emit_byte (mb, CEE_MONO_LDNATIVEOBJ);
3747                                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3748                                 }
3749                                 break;
3750                         case MONO_TYPE_STRING:
3751                         case MONO_TYPE_CLASS:
3752                         case MONO_TYPE_OBJECT:
3753                                 g_assert (tmp_locals [i]);
3754                                 if (t->byref) 
3755                                         mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
3756                                 else
3757                                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
3758                                 break;
3759                         case MONO_TYPE_CHAR:
3760                                 /* fixme: dont know how to marshal that. We cant simply
3761                                  * convert it to a one byte UTF8 character, because an
3762                                  * unicode character may need more that one byte in UTF8 */
3763                                 mono_mb_emit_ldarg (mb, argnum);
3764                                 break;
3765                         case MONO_TYPE_ARRAY:
3766                         case MONO_TYPE_SZARRAY:
3767                                 if (t->byref) {
3768                                         mono_mb_emit_ldarg (mb, argnum);
3769                                 } else {
3770                                         g_assert (tmp_locals [i]);
3771                                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
3772                                 }
3773                                 break;
3774                         case MONO_TYPE_TYPEDBYREF:
3775                         case MONO_TYPE_FNPTR:
3776                         default:
3777                                 g_warning ("type 0x%02x unknown", t->type);     
3778                                 g_assert_not_reached ();
3779                         }
3780                 }
3781         }                       
3782
3783         /* call the native method */
3784         mono_mb_emit_native_call (mb, csig, method->addr);
3785
3786         /* Set LastError if needed */
3787         if (piinfo->piflags & PINVOKE_ATTRIBUTE_SUPPORTS_LAST_ERROR) {
3788                 MonoMethodSignature *lasterr_sig;
3789
3790                 lasterr_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
3791                 lasterr_sig->ret = &mono_defaults.void_class->byval_arg;
3792                 lasterr_sig->pinvoke = 1;
3793
3794                 mono_mb_emit_native_call (mb, lasterr_sig, mono_marshal_set_last_error);
3795         }               
3796
3797         /* Ensure that we have marshalling info for the return */
3798         mono_marshal_load_type_info (mono_class_from_mono_type (sig->ret));
3799
3800         /* convert the result */
3801         if (!sig->ret->byref) {
3802                 MonoMarshalSpec *spec = mspecs [0];
3803                 type = sig->ret->type;
3804
3805                 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
3806                         MonoType *mtype;
3807                         MonoClass *mklass;
3808                         MonoMethod *marshal_native_to_managed;
3809                         MonoMethod *get_instance;
3810
3811                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
3812                         g_assert (mtype != NULL);
3813                         mklass = mono_class_from_mono_type (mtype);
3814                         g_assert (mklass != NULL);
3815
3816                         marshal_native_to_managed = mono_find_method_by_name (mklass, "MarshalNativeToManaged", 1);
3817                         g_assert (marshal_native_to_managed);
3818                         get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
3819                         g_assert (get_instance);
3820                         
3821                         switch (type) {
3822                         case MONO_TYPE_CLASS:
3823                         case MONO_TYPE_OBJECT:
3824                         case MONO_TYPE_STRING:
3825                         case MONO_TYPE_ARRAY:
3826                         case MONO_TYPE_SZARRAY:
3827                         case MONO_TYPE_VALUETYPE:
3828                                 if (type == MONO_TYPE_VALUETYPE) {
3829                                         /* local 3 can't hold a pointer */
3830                                         mono_mb_emit_byte (mb, CEE_STLOC_0);
3831                                 }
3832                                 else
3833                                         mono_mb_emit_byte (mb, CEE_STLOC_3);
3834
3835                                 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
3836
3837                                 mono_mb_emit_byte (mb, CEE_CALL);
3838                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
3839
3840                                 if (type == MONO_TYPE_VALUETYPE)
3841                                         mono_mb_emit_byte (mb, CEE_LDLOC_0);
3842                                 else
3843                                         mono_mb_emit_byte (mb, CEE_LDLOC_3);
3844                                 
3845                                 mono_mb_emit_byte (mb, CEE_CALLVIRT);
3846                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_native_to_managed));
3847                                 
3848                                 if (type == MONO_TYPE_VALUETYPE) {
3849                                         mono_mb_emit_byte (mb, CEE_UNBOX);
3850                                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (sig->ret)));
3851                                 }
3852                                 mono_mb_emit_byte (mb, CEE_STLOC_3);
3853                                 break;
3854                         default:
3855                                 g_warning ("custom marshalling of type %x is currently not supported", type);
3856                                 g_assert_not_reached ();
3857                                 break;
3858                         }
3859                 } else {
3860
3861                 handle_enum:
3862                         switch (type) {
3863                         case MONO_TYPE_VOID:
3864                                 break;
3865                         case MONO_TYPE_I1:
3866                         case MONO_TYPE_U1:
3867                         case MONO_TYPE_I2:
3868                         case MONO_TYPE_U2:
3869                         case MONO_TYPE_I4:
3870                         case MONO_TYPE_U4:
3871                         case MONO_TYPE_I:
3872                         case MONO_TYPE_U:
3873                         case MONO_TYPE_PTR:
3874                         case MONO_TYPE_R4:
3875                         case MONO_TYPE_R8:
3876                         case MONO_TYPE_I8:
3877                         case MONO_TYPE_U8:
3878                                 /* no conversions necessary */
3879                                 mono_mb_emit_byte (mb, CEE_STLOC_3);
3880                                 break;
3881                         case MONO_TYPE_BOOLEAN:
3882                                 /* maybe we need to make sure that it fits within 8 bits */
3883                                 mono_mb_emit_byte (mb, CEE_STLOC_3);
3884                                 break;
3885                         case MONO_TYPE_VALUETYPE:
3886                                 klass = sig->ret->data.klass;
3887                                 if (klass->enumtype) {
3888                                         type = sig->ret->data.klass->enum_basetype->type;
3889                                         goto handle_enum;
3890                                 }
3891
3892                                 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3893                                     klass->blittable) {
3894                                         mono_mb_emit_byte (mb, CEE_STLOC_3);
3895                                         break;
3896                                 }
3897                                 /* load pointer to returned value type */
3898                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3899                                 mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
3900                                 /* store the address of the source into local variable 0 */
3901                                 mono_mb_emit_byte (mb, CEE_STLOC_0);
3902                                 /* set dst_ptr */
3903                                 mono_mb_emit_ldloc_addr (mb, 3);
3904                                 mono_mb_emit_byte (mb, CEE_STLOC_1);
3905                                 
3906                                 /* emit valuetype conversion code */
3907                                 emit_struct_conv (mb, sig->ret->data.klass, TRUE);
3908                                 break;
3909                         case MONO_TYPE_STRING:
3910                                 mono_mb_emit_byte (mb, CEE_STLOC_0);
3911                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3912                                 
3913                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3914                                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3915                                 if (spec) {
3916                                         switch (spec->native) {
3917                                         case MONO_NATIVE_LPWSTR:
3918                                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPWSTR_STR);
3919                                                 break;
3920                                         default:
3921                                                 g_warning ("marshalling conversion not implemented");
3922                                                 g_assert_not_reached ();
3923                                         }
3924                                 } else {
3925                                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
3926                                 }
3927                                 mono_mb_emit_byte (mb, CEE_STLOC_3);
3928
3929                                 /* free the string */
3930                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3931                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3932                                 mono_mb_emit_byte (mb, CEE_MONO_FREE);
3933                                 break;
3934                         case MONO_TYPE_CLASS:
3935                         case MONO_TYPE_OBJECT:
3936                                 klass = sig->ret->data.klass;
3937
3938                                 /* set src */
3939                                 mono_mb_emit_byte (mb, CEE_STLOC_0);
3940
3941                                 mono_mb_emit_byte (mb, CEE_LDNULL);
3942                                 mono_mb_emit_byte (mb, CEE_STLOC_3);
3943
3944
3945                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3946                                 mono_mb_emit_byte (mb, CEE_BRFALSE);
3947                                 pos = mb->pos;
3948                                 mono_mb_emit_i4 (mb, 0);
3949
3950                                 /* allocate result object */
3951
3952                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3953                                 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);        
3954                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3955                                 mono_mb_emit_byte (mb, CEE_STLOC_3);
3956                                 
3957                                 /* set dst  */
3958
3959                                 mono_mb_emit_byte (mb, CEE_LDLOC_3);
3960                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3961                                 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
3962                                 mono_mb_emit_icon (mb, sizeof (MonoObject));
3963                                 mono_mb_emit_byte (mb, CEE_ADD);
3964                                 mono_mb_emit_byte (mb, CEE_STLOC_1);
3965                                                         
3966                                 /* emit conversion code */
3967                                 emit_struct_conv (mb, klass, TRUE);
3968
3969                                 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3970                                 break;
3971                         case MONO_TYPE_ARRAY:
3972                         case MONO_TYPE_SZARRAY:
3973                                 /* fixme: we need conversions here */
3974                                 mono_mb_emit_byte (mb, CEE_STLOC_3);
3975                                 break;
3976                         case MONO_TYPE_CHAR:
3977                                 /* fixme: we need conversions here */
3978                                 mono_mb_emit_byte (mb, CEE_STLOC_3);
3979                                 break;
3980                         case MONO_TYPE_TYPEDBYREF:
3981                         case MONO_TYPE_FNPTR:
3982                         default:
3983                                 g_warning ("return type 0x%02x unknown", sig->ret->type);       
3984                                 g_assert_not_reached ();
3985                         }
3986                 }
3987         } else {
3988                 mono_mb_emit_byte (mb, CEE_STLOC_3);
3989         }
3990
3991         /* 
3992          * Need to call this after converting the result since MONO_VTADDR needs 
3993          * to be adjacent to the call instruction.
3994          */
3995         emit_thread_interrupt_checkpoint (mb);
3996
3997         /* we need to convert byref arguments back and free string arrays */
3998         for (i = 0; i < sig->param_count; i++) {
3999                 MonoType *t = sig->params [i];
4000                 MonoMarshalSpec *spec = mspecs [i + 1];
4001
4002                 argnum = i + sig->hasthis;
4003
4004                 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
4005                         MonoType *mtype;
4006                         MonoClass *mklass;
4007                         MonoMethod *get_instance;
4008                         MonoMethod *cleanup_native;
4009
4010                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
4011                         g_assert (mtype != NULL);
4012                         mklass = mono_class_from_mono_type (mtype);
4013                         g_assert (mklass != NULL);
4014
4015                         get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
4016                         g_assert (get_instance);
4017                         cleanup_native = mono_find_method_by_name (mklass, "CleanUpNativeData", 1);
4018                         g_assert (get_instance);
4019                         
4020                         switch (t->type) {
4021                         case MONO_TYPE_CLASS:
4022                         case MONO_TYPE_OBJECT:
4023                         case MONO_TYPE_STRING:
4024                         case MONO_TYPE_ARRAY:
4025                         case MONO_TYPE_SZARRAY:
4026                         case MONO_TYPE_VALUETYPE:
4027                                 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
4028
4029                                 mono_mb_emit_byte (mb, CEE_CALL);
4030                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
4031                                 
4032                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4033
4034                                 mono_mb_emit_byte (mb, CEE_CALLVIRT);
4035                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, cleanup_native));
4036
4037                                 break;
4038
4039                         default:
4040                                 g_warning ("custom marshalling of type %x is currently not supported", t->type);
4041                                 g_assert_not_reached ();
4042                                 break;
4043                         }
4044                         continue;
4045                 }
4046
4047                 if (spec && spec->native == MONO_NATIVE_ASANY) {
4048                         MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, NULL);
4049
4050                         mono_mb_emit_ldarg (mb, argnum);
4051                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
4052                         mono_mb_emit_icon (mb, encoding);
4053                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4054                         mono_mb_emit_byte (mb, CEE_MONO_PROC3);
4055                         mono_mb_emit_byte (mb, MONO_MARSHAL_FREE_ASANY);
4056                         continue;
4057                 }
4058                 
4059                 switch (t->type) {
4060                 case MONO_TYPE_STRING:
4061                         if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT)) {
4062                                 mono_mb_emit_ldarg (mb, argnum);
4063                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4064                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4065                                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
4066                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
4067                                 mono_mb_emit_byte (mb, CEE_STIND_I);            
4068                         } else {
4069                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4070                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4071                                 mono_mb_emit_byte (mb, CEE_MONO_FREE);
4072                         }
4073                         break;
4074                 case MONO_TYPE_CLASS:
4075                 case MONO_TYPE_OBJECT:                  
4076                         if (t->data.klass == mono_defaults.stringbuilder_class) {
4077                                 gboolean need_free;
4078                                 MonoMarshalNative encoding;
4079
4080                                 encoding = mono_marshal_get_ptr_to_stringbuilder_encoding (piinfo, spec, &need_free);
4081
4082                                 g_assert (!t->byref);
4083                                 g_assert (encoding != -1);
4084
4085                                 mono_mb_emit_ldarg (mb, argnum);
4086                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4087                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4088                                 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
4089
4090                                 mono_mb_emit_byte (mb, encoding);
4091
4092                                 if (need_free) {
4093                                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
4094                                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4095                                         mono_mb_emit_byte (mb, CEE_MONO_FREE);
4096                                 }
4097                                 break;
4098                         }
4099                         
4100                         if (!(t->byref || (t->attrs & PARAM_ATTRIBUTE_OUT)))
4101                                 continue;
4102
4103                         if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT)) {
4104                                 /* allocate a new object new object */
4105                                 mono_mb_emit_ldarg (mb, argnum);
4106                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4107                                 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);        
4108                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
4109                                 mono_mb_emit_byte (mb, CEE_STIND_I);
4110                         }
4111
4112                         /* dst = *argument */
4113                         mono_mb_emit_ldarg (mb, argnum);
4114
4115                         if (t->byref)
4116                                 mono_mb_emit_byte (mb, CEE_LDIND_I);
4117
4118                         mono_mb_emit_byte (mb, CEE_STLOC_1);
4119
4120                         mono_mb_emit_byte (mb, CEE_LDLOC_1);
4121                         mono_mb_emit_byte (mb, CEE_BRFALSE);
4122                         pos = mb->pos;
4123                         mono_mb_emit_i4 (mb, 0);
4124
4125                         mono_mb_emit_byte (mb, CEE_LDLOC_1);
4126                         mono_mb_emit_icon (mb, sizeof (MonoObject));
4127                         mono_mb_emit_byte (mb, CEE_ADD);
4128                         mono_mb_emit_byte (mb, CEE_STLOC_1);
4129                         
4130                         /* src = tmp_locals [i] */
4131                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
4132                         mono_mb_emit_byte (mb, CEE_STLOC_0);
4133
4134                         /* emit valuetype conversion code */
4135                         emit_struct_conv (mb, klass, TRUE);
4136
4137                         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
4138                         break;
4139                 case MONO_TYPE_VALUETYPE:
4140                         if (!t->byref)
4141                                 continue;
4142         
4143                         klass = t->data.klass;
4144                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
4145                             klass->blittable || klass->enumtype)
4146                                 break;
4147
4148                         /* dst = argument */
4149                         mono_mb_emit_ldarg (mb, argnum);
4150                         mono_mb_emit_byte (mb, CEE_STLOC_1);
4151
4152                         mono_mb_emit_byte (mb, CEE_LDLOC_1);
4153                         mono_mb_emit_byte (mb, CEE_BRFALSE);
4154                         pos = mb->pos;
4155                         mono_mb_emit_i4 (mb, 0);
4156
4157                         /* src = tmp_locals [i] */
4158                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
4159                         mono_mb_emit_byte (mb, CEE_STLOC_0);
4160
4161                         /* emit valuetype conversion code */
4162                         emit_struct_conv (mb, klass, TRUE);
4163                         
4164                         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
4165                         break;
4166                 case MONO_TYPE_SZARRAY:
4167                         if (t->byref)
4168                                 continue;
4169  
4170                         klass = mono_class_from_mono_type (t);
4171
4172                         if (klass->element_class == mono_defaults.string_class) {
4173                                 MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, spec);
4174                                 g_assert (tmp_locals [i]);
4175
4176                                 mono_mb_emit_ldarg (mb, argnum);
4177                                 mono_mb_emit_byte (mb, CEE_BRFALSE);
4178                                 pos = mb->pos;
4179                                 mono_mb_emit_i4 (mb, 0);
4180
4181                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4182
4183                                 switch (encoding) {
4184                                 case MONO_NATIVE_LPWSTR:
4185                                         /* 
4186                                          * The array elements point to the managed string data so 
4187                                          * they don't need to be freed.
4188                                          */
4189                                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4190                                         mono_mb_emit_byte (mb, CEE_MONO_FREE);
4191                                         break;
4192                                 default:
4193                                         mono_mb_emit_ldarg (mb, argnum);
4194                                         mono_mb_emit_byte (mb, CEE_LDLEN);                              
4195                                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4196                                         mono_mb_emit_byte (mb, CEE_MONO_PROC2);
4197                                         mono_mb_emit_byte (mb, MONO_MARSHAL_FREE_ARRAY);
4198                                         break;                                  
4199                                 }
4200
4201                                 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
4202                         }
4203
4204                         /* Character arrays are implicitly marshalled as [Out] */
4205                         if ((klass->element_class == mono_defaults.char_class) || (klass->element_class == mono_defaults.stringbuilder_class) || (t->attrs & PARAM_ATTRIBUTE_OUT)) {
4206                                 /* FIXME: Optimize blittable case */
4207                                 MonoClass *eklass;
4208                                 guint32 label1, label2, label3;
4209                                 int index_var, src_ptr, esize;
4210
4211                                 eklass = klass->element_class;
4212                                 if (eklass == mono_defaults.stringbuilder_class)
4213                                         esize = sizeof (gpointer);
4214                                 else
4215                                         esize = mono_class_native_size (eklass, NULL);
4216                                 src_ptr = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
4217
4218                                 /* Check null */
4219                                 mono_mb_emit_ldarg (mb, argnum);
4220                                 mono_mb_emit_byte (mb, CEE_BRFALSE);
4221                                 label1 = mb->pos;
4222                                 mono_mb_emit_i4 (mb, 0);
4223
4224                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
4225                                 mono_mb_emit_stloc (mb, src_ptr);
4226
4227                                 /* Emit marshalling loop */
4228                                 index_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);                                
4229                                 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
4230                                 mono_mb_emit_stloc (mb, index_var);
4231                                 label2 = mb->pos;
4232                                 mono_mb_emit_ldloc (mb, index_var);
4233                                 mono_mb_emit_ldarg (mb, argnum);
4234                                 mono_mb_emit_byte (mb, CEE_LDLEN);
4235                                 mono_mb_emit_byte (mb, CEE_BGE);
4236                                 label3 = mb->pos;
4237                                 mono_mb_emit_i4 (mb, 0);
4238
4239                                 /* Emit marshalling code */
4240
4241                                 if (eklass == mono_defaults.stringbuilder_class) {
4242                                         gboolean need_free;
4243                                         MonoMarshalNative encoding = mono_marshal_get_ptr_to_stringbuilder_encoding (piinfo, spec, &need_free);
4244
4245                                         g_assert (encoding != -1);
4246
4247                                         /* dest */
4248                                         mono_mb_emit_ldarg (mb, argnum);
4249                                         mono_mb_emit_ldloc (mb, index_var);
4250                                         mono_mb_emit_byte (mb, CEE_LDELEM_REF);
4251
4252                                         /* src */
4253                                         mono_mb_emit_ldloc (mb, src_ptr);
4254                                         mono_mb_emit_byte (mb, CEE_LDIND_I);
4255
4256                                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4257                                         mono_mb_emit_byte (mb, CEE_MONO_PROC2);
4258
4259                                         mono_mb_emit_byte (mb, encoding);
4260
4261                                         if (need_free) {
4262                                                 /* src */
4263                                                 mono_mb_emit_ldloc (mb, src_ptr);
4264                                                 mono_mb_emit_byte (mb, CEE_LDIND_I);
4265
4266                                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4267                                                 mono_mb_emit_byte (mb, CEE_MONO_FREE);
4268                                         }
4269                                 }
4270                                 else {
4271                                         /* set the src_ptr */
4272                                         mono_mb_emit_ldloc (mb, src_ptr);
4273                                         mono_mb_emit_byte (mb, CEE_STLOC_0);
4274
4275                                         /* set dst_ptr */
4276                                         mono_mb_emit_ldarg (mb, argnum);
4277                                         mono_mb_emit_ldloc (mb, index_var);
4278                                         mono_mb_emit_byte (mb, CEE_LDELEMA);
4279                                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eklass));
4280                                         mono_mb_emit_byte (mb, CEE_STLOC_1);
4281
4282                                         /* emit valuetype conversion code */
4283                                         emit_struct_conv (mb, eklass, TRUE);
4284                                 }
4285
4286                                 mono_mb_emit_add_to_local (mb, index_var, 1);
4287                                 mono_mb_emit_add_to_local (mb, src_ptr, esize);
4288
4289                                 mono_mb_emit_byte (mb, CEE_BR);
4290                                 mono_mb_emit_i4 (mb, label2 - (mb->pos + 4));
4291
4292                                 mono_mb_patch_addr (mb, label1, mb->pos - (label1 + 4));
4293                                 mono_mb_patch_addr (mb, label3, mb->pos - (label3 + 4));
4294                         }
4295                         break;
4296                 case MONO_TYPE_BOOLEAN:
4297                         if (!t->byref)
4298                                 continue;
4299                         mono_mb_emit_ldarg (mb, argnum);
4300                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
4301                         if (mspecs [i + 1] != NULL && mspecs [i + 1]->native == MONO_NATIVE_VARIANTBOOL)
4302                                 mono_mb_emit_byte (mb, CEE_NEG);
4303                         mono_mb_emit_byte (mb, CEE_STIND_I1);
4304                 }
4305         }
4306
4307         if (!MONO_TYPE_IS_VOID(sig->ret))
4308                 mono_mb_emit_byte (mb, CEE_LDLOC_3);
4309
4310         mono_mb_emit_byte (mb, CEE_RET);
4311
4312         csig = mono_metadata_signature_dup (sig);
4313         csig->pinvoke = 0;
4314         res = mono_mb_create_and_cache (cache, method,
4315                                                                         mb, csig, csig->param_count + 16);
4316         mono_mb_free (mb);
4317
4318         for (i = sig->param_count; i >= 0; i--)
4319                 g_free (mspecs [i]);
4320         g_free (mspecs);
4321
4322         /* 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)); */
4323
4324         return res;
4325 }
4326
4327 void
4328 mono_upgrade_remote_class_wrapper (MonoReflectionType *rtype, MonoTransparentProxy *tproxy);
4329
4330 static MonoReflectionType *
4331 type_from_handle (MonoType *handle)
4332 {
4333         MonoDomain *domain = mono_domain_get (); 
4334         MonoClass *klass = mono_class_from_mono_type (handle);
4335
4336         MONO_ARCH_SAVE_REGS;
4337
4338         mono_class_init (klass);
4339         return mono_type_get_object (domain, handle);
4340 }
4341
4342 /*
4343  * mono_marshal_get_isinst:
4344  * @klass: the type of the field
4345  *
4346  * This method generates a function which can be used to check if an object is
4347  * an instance of the given type, icluding the case where the object is a proxy.
4348  * The generated function has the following signature:
4349  * MonoObject* __isinst_wrapper_ (MonoObject *obj)
4350  */
4351 MonoMethod *
4352 mono_marshal_get_isinst (MonoClass *klass)
4353 {
4354         static MonoMethodSignature *isint_sig = NULL;
4355         static GHashTable *isinst_hash = NULL; 
4356         MonoMethod *res;
4357         int pos_was_ok, pos_failed, pos_end, pos_end2;
4358         char *name;
4359         MonoMethodBuilder *mb;
4360
4361         EnterCriticalSection (&marshal_mutex);
4362         if (!isinst_hash) 
4363                 isinst_hash = g_hash_table_new (NULL, NULL);
4364         
4365         res = g_hash_table_lookup (isinst_hash, klass);
4366         LeaveCriticalSection (&marshal_mutex);
4367         if (res)
4368                 return res;
4369
4370         if (!isint_sig) {
4371                 isint_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
4372                 isint_sig->params [0] = &mono_defaults.object_class->byval_arg;
4373                 isint_sig->ret = &mono_defaults.object_class->byval_arg;
4374                 isint_sig->pinvoke = 0;
4375         }
4376         
4377         name = g_strdup_printf ("__isinst_wrapper_%s", klass->name); 
4378         mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_UNKNOWN);
4379         g_free (name);
4380         
4381         mb->method->save_lmf = 1;
4382
4383         /* check if the object is a proxy that needs special cast */
4384         mono_mb_emit_ldarg (mb, 0);
4385         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4386         mono_mb_emit_byte (mb, CEE_MONO_CISINST);
4387         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
4388
4389         /* The result of MONO_ISINST can be:
4390                 0) the type check succeeded
4391                 1) the type check did not succeed
4392                 2) a CanCastTo call is needed */
4393         
4394         mono_mb_emit_byte (mb, CEE_DUP);
4395         pos_was_ok = mono_mb_emit_branch (mb, CEE_BRFALSE);
4396
4397         mono_mb_emit_byte (mb, CEE_LDC_I4_2);
4398         pos_failed = mono_mb_emit_branch (mb, CEE_BNE_UN);
4399         
4400         /* get the real proxy from the transparent proxy*/
4401
4402         mono_mb_emit_ldarg (mb, 0);
4403         mono_mb_emit_managed_call (mb, mono_marshal_get_proxy_cancast (klass), NULL);
4404         pos_end = mono_mb_emit_branch (mb, CEE_BR);
4405         
4406         /* fail */
4407         
4408         mono_mb_patch_addr (mb, pos_failed, mb->pos - (pos_failed + 4));
4409         mono_mb_emit_byte (mb, CEE_LDNULL);
4410         pos_end2 = mono_mb_emit_branch (mb, CEE_BR);
4411         
4412         /* success */
4413         
4414         mono_mb_patch_addr (mb, pos_was_ok, mb->pos - (pos_was_ok + 4));
4415         mono_mb_emit_byte (mb, CEE_POP);
4416         mono_mb_emit_ldarg (mb, 0);
4417         
4418         /* the end */
4419         
4420         mono_mb_patch_addr (mb, pos_end, mb->pos - (pos_end + 4));
4421         mono_mb_patch_addr (mb, pos_end2, mb->pos - (pos_end2 + 4));
4422         mono_mb_emit_byte (mb, CEE_RET);
4423
4424         res = mono_mb_create_and_cache (isinst_hash, klass, mb, isint_sig, isint_sig->param_count + 16);
4425         mono_mb_free (mb);
4426
4427         return res;
4428 }
4429
4430 /*
4431  * mono_marshal_get_castclass:
4432  * @klass: the type of the field
4433  *
4434  * This method generates a function which can be used to cast an object to
4435  * an instance of the given type, icluding the case where the object is a proxy.
4436  * The generated function has the following signature:
4437  * MonoObject* __castclass_wrapper_ (MonoObject *obj)
4438  */
4439 MonoMethod *
4440 mono_marshal_get_castclass (MonoClass *klass)
4441 {
4442         static MonoMethodSignature *castclass_sig = NULL;
4443         static GHashTable *castclass_hash = NULL; 
4444         MonoMethod *res;
4445         int pos_was_ok, pos_was_ok2;
4446         char *name;
4447         MonoMethodBuilder *mb;
4448
4449         EnterCriticalSection (&marshal_mutex);
4450         if (!castclass_hash) 
4451                 castclass_hash = g_hash_table_new (NULL, NULL);
4452         
4453         res = g_hash_table_lookup (castclass_hash, klass);
4454         LeaveCriticalSection (&marshal_mutex);
4455         if (res)
4456                 return res;
4457
4458         if (!castclass_sig) {
4459                 castclass_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
4460                 castclass_sig->params [0] = &mono_defaults.object_class->byval_arg;
4461                 castclass_sig->ret = &mono_defaults.object_class->byval_arg;
4462                 castclass_sig->pinvoke = 0;
4463         }
4464         
4465         name = g_strdup_printf ("__castclass_wrapper_%s", klass->name); 
4466         mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_UNKNOWN);
4467         g_free (name);
4468         
4469         mb->method->save_lmf = 1;
4470
4471         /* check if the object is a proxy that needs special cast */
4472         mono_mb_emit_ldarg (mb, 0);
4473         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4474         mono_mb_emit_byte (mb, CEE_MONO_CCASTCLASS);
4475         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
4476
4477         /* The result of MONO_ISINST can be:
4478                 0) the cast is valid
4479                 1) cast of unknown proxy type
4480                 or an exception if the cast is is invalid
4481         */
4482         
4483         pos_was_ok = mono_mb_emit_branch (mb, CEE_BRFALSE);
4484
4485         /* get the real proxy from the transparent proxy*/
4486
4487         mono_mb_emit_ldarg (mb, 0);
4488         mono_mb_emit_managed_call (mb, mono_marshal_get_proxy_cancast (klass), NULL);
4489         pos_was_ok2 = mono_mb_emit_branch (mb, CEE_BRTRUE);
4490         
4491         /* fail */
4492         mono_mb_emit_exception (mb, "InvalidCastException", NULL);
4493         
4494         /* success */
4495         mono_mb_patch_addr (mb, pos_was_ok, mb->pos - (pos_was_ok + 4));
4496         mono_mb_patch_addr (mb, pos_was_ok2, mb->pos - (pos_was_ok2 + 4));
4497         mono_mb_emit_ldarg (mb, 0);
4498         
4499         /* the end */
4500         mono_mb_emit_byte (mb, CEE_RET);
4501
4502         res = mono_mb_create_and_cache (castclass_hash, klass, mb, castclass_sig, castclass_sig->param_count + 16);
4503         mono_mb_free (mb);
4504
4505         return res;
4506 }
4507
4508 MonoMethod *
4509 mono_marshal_get_proxy_cancast (MonoClass *klass)
4510 {
4511         static MonoMethodSignature *from_handle_sig = NULL;
4512         static MonoMethodSignature *upgrade_proxy_sig = NULL;
4513         static MonoMethodSignature *isint_sig = NULL;
4514         static GHashTable *proxy_isinst_hash = NULL; 
4515         MonoMethod *res;
4516         int pos_failed, pos_end;
4517         char *name;
4518         MonoMethod *can_cast_to;
4519         MonoMethodDesc *desc;
4520         MonoMethodBuilder *mb;
4521
4522         EnterCriticalSection (&marshal_mutex);
4523         if (!proxy_isinst_hash) 
4524                 proxy_isinst_hash = g_hash_table_new (NULL, NULL);
4525         
4526         res = g_hash_table_lookup (proxy_isinst_hash, klass);
4527         LeaveCriticalSection (&marshal_mutex);
4528         if (res)
4529                 return res;
4530
4531         if (!isint_sig) {
4532                 upgrade_proxy_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
4533                 upgrade_proxy_sig->params [0] = &mono_defaults.object_class->byval_arg;
4534                 upgrade_proxy_sig->params [1] = &mono_defaults.object_class->byval_arg;
4535                 upgrade_proxy_sig->ret = &mono_defaults.void_class->byval_arg;
4536                 upgrade_proxy_sig->pinvoke = 1;
4537
4538                 from_handle_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
4539                 from_handle_sig->params [0] = &mono_defaults.object_class->byval_arg;
4540                 from_handle_sig->ret = &mono_defaults.object_class->byval_arg;
4541         
4542                 isint_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
4543                 isint_sig->params [0] = &mono_defaults.object_class->byval_arg;
4544                 isint_sig->ret = &mono_defaults.object_class->byval_arg;
4545                 isint_sig->pinvoke = 0;
4546         }
4547         
4548         name = g_strdup_printf ("__proxy_isinst_wrapper_%s", klass->name); 
4549         mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_UNKNOWN);
4550         g_free (name);
4551         
4552         mb->method->save_lmf = 1;
4553
4554         /* get the real proxy from the transparent proxy*/
4555         mono_mb_emit_ldarg (mb, 0);
4556         mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoTransparentProxy, rp));
4557         mono_mb_emit_byte (mb, CEE_LDIND_I);
4558         
4559         /* get the refletion type from the type handle */
4560         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4561         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
4562         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, &klass->byval_arg));
4563         mono_mb_emit_native_call (mb, from_handle_sig, type_from_handle);
4564         
4565         mono_mb_emit_ldarg (mb, 0);
4566         
4567         /* make the call to CanCastTo (type, ob) */
4568         desc = mono_method_desc_new ("IRemotingTypeInfo:CanCastTo", FALSE);
4569         can_cast_to = mono_method_desc_search_in_class (desc, mono_defaults.iremotingtypeinfo_class);
4570         g_assert (can_cast_to);
4571         mono_method_desc_free (desc);
4572         mono_mb_emit_byte (mb, CEE_CALLVIRT);
4573         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, can_cast_to));
4574
4575         
4576         pos_failed = mono_mb_emit_branch (mb, CEE_BRFALSE);
4577
4578         /* Upgrade the proxy vtable by calling: mono_upgrade_remote_class_wrapper (type, ob)*/
4579         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4580         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
4581         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, &klass->byval_arg));
4582         mono_mb_emit_native_call (mb, from_handle_sig, type_from_handle);
4583         mono_mb_emit_ldarg (mb, 0);
4584         
4585         mono_mb_emit_native_call (mb, upgrade_proxy_sig, mono_upgrade_remote_class_wrapper);
4586         emit_thread_interrupt_checkpoint (mb);
4587         
4588         mono_mb_emit_ldarg (mb, 0);
4589         pos_end = mono_mb_emit_branch (mb, CEE_BR);
4590         
4591         /* fail */
4592         
4593         mono_mb_patch_addr (mb, pos_failed, mb->pos - (pos_failed + 4));
4594         mono_mb_emit_byte (mb, CEE_LDNULL);
4595         
4596         /* the end */
4597         
4598         mono_mb_patch_addr (mb, pos_end, mb->pos - (pos_end + 4));
4599         mono_mb_emit_byte (mb, CEE_RET);
4600
4601         res = mono_mb_create_and_cache (proxy_isinst_hash, klass, mb, isint_sig, isint_sig->param_count + 16);
4602         mono_mb_free (mb);
4603
4604         return res;
4605 }
4606
4607 void
4608 mono_upgrade_remote_class_wrapper (MonoReflectionType *rtype, MonoTransparentProxy *tproxy)
4609 {
4610         MonoClass *klass;
4611         klass = mono_class_from_mono_type (rtype->type);
4612         mono_upgrade_remote_class (((MonoObject*)tproxy)->vtable->domain, tproxy->remote_class, klass);
4613         ((MonoObject*)tproxy)->vtable = tproxy->remote_class->vtable;
4614 }
4615
4616 /**
4617  * mono_marshal_get_struct_to_ptr:
4618  * @klass:
4619  *
4620  * generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld)
4621  */
4622 MonoMethod *
4623 mono_marshal_get_struct_to_ptr (MonoClass *klass)
4624 {
4625         MonoMethodBuilder *mb;
4626         static MonoMethod *stoptr = NULL;
4627         MonoMethod *res;
4628
4629         g_assert (klass != NULL);
4630
4631         if (klass->str_to_ptr)
4632                 return klass->str_to_ptr;
4633
4634         if (!stoptr) 
4635                 stoptr = mono_find_method_by_name (mono_defaults.marshal_class, "StructureToPtr", 3);
4636         g_assert (stoptr);
4637
4638         mb = mono_mb_new (klass, stoptr->name, MONO_WRAPPER_UNKNOWN);
4639
4640         if (klass->blittable) {
4641                 mono_mb_emit_byte (mb, CEE_LDARG_1);
4642                 mono_mb_emit_byte (mb, CEE_LDARG_0);
4643                 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
4644                 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
4645                 mono_mb_emit_byte (mb, CEE_PREFIX1);
4646                 mono_mb_emit_byte (mb, CEE_CPBLK);
4647         } else {
4648
4649                 /* allocate local 0 (pointer) src_ptr */
4650                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
4651                 /* allocate local 1 (pointer) dst_ptr */
4652                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
4653                 /* allocate local 2 (boolean) delete_old */
4654                 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
4655                 mono_mb_emit_byte (mb, CEE_LDARG_2);
4656                 mono_mb_emit_byte (mb, CEE_STLOC_2);
4657
4658                 /* initialize src_ptr to point to the start of object data */
4659                 mono_mb_emit_byte (mb, CEE_LDARG_0);
4660                 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
4661                 mono_mb_emit_byte (mb, CEE_STLOC_0);
4662
4663                 /* initialize dst_ptr */
4664                 mono_mb_emit_byte (mb, CEE_LDARG_1);
4665                 mono_mb_emit_byte (mb, CEE_STLOC_1);
4666
4667                 emit_struct_conv (mb, klass, FALSE);
4668         }
4669
4670         mono_mb_emit_byte (mb, CEE_RET);
4671
4672         res = mono_mb_create_method (mb, stoptr->signature, 0);
4673         mono_mb_free (mb);
4674
4675         klass->str_to_ptr = res;
4676         return res;
4677 }
4678
4679 /**
4680  * mono_marshal_get_ptr_to_struct:
4681  * @klass:
4682  *
4683  * generates IL code for PtrToStructure (IntPtr src, object structure)
4684  */
4685 MonoMethod *
4686 mono_marshal_get_ptr_to_struct (MonoClass *klass)
4687 {
4688         MonoMethodBuilder *mb;
4689         static MonoMethod *ptostr = NULL;
4690         MonoMethod *res;
4691
4692         g_assert (klass != NULL);
4693
4694         if (klass->ptr_to_str)
4695                 return klass->ptr_to_str;
4696
4697         if (!ptostr) 
4698                 ptostr = mono_find_method_by_name (mono_defaults.marshal_class, "PtrToStructure", 2);
4699         g_assert (ptostr);
4700
4701         mb = mono_mb_new (klass, ptostr->name, MONO_WRAPPER_UNKNOWN);
4702
4703         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable) {
4704                 mono_mb_emit_byte (mb, CEE_LDARG_1);
4705                 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
4706                 mono_mb_emit_byte (mb, CEE_LDARG_0);
4707                 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
4708                 mono_mb_emit_byte (mb, CEE_PREFIX1);
4709                 mono_mb_emit_byte (mb, CEE_CPBLK);
4710         } else {
4711
4712                 /* allocate local 0 (pointer) src_ptr */
4713                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
4714                 /* allocate local 1 (pointer) dst_ptr */
4715                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
4716                 
4717                 /* initialize src_ptr to point to the start of object data */
4718                 mono_mb_emit_byte (mb, CEE_LDARG_0);
4719                 mono_mb_emit_byte (mb, CEE_STLOC_0);
4720
4721                 /* initialize dst_ptr */
4722                 mono_mb_emit_byte (mb, CEE_LDARG_1);
4723                 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
4724                 mono_mb_emit_byte (mb, CEE_STLOC_1);
4725
4726                 emit_struct_conv (mb, klass, TRUE);
4727         }
4728
4729         mono_mb_emit_byte (mb, CEE_RET);
4730
4731         res = mono_mb_create_method (mb, ptostr->signature, 0);
4732         mono_mb_free (mb);
4733
4734         klass->ptr_to_str = res;
4735         return res;
4736 }
4737
4738 /*
4739  * generates IL code for the synchronized wrapper: the generated method
4740  * calls METHOD while locking 'this' or the parent type.
4741  */
4742 MonoMethod *
4743 mono_marshal_get_synchronized_wrapper (MonoMethod *method)
4744 {
4745         static MonoMethodSignature *from_handle_sig = NULL;
4746         static MonoMethod *enter_method, *exit_method;
4747         MonoMethodSignature *sig;
4748         MonoExceptionClause *clause;
4749         MonoMethodHeader *header;
4750         MonoMethodBuilder *mb;
4751         MonoMethod *res;
4752         GHashTable *cache;
4753         int i, pos, this_local, ret_local;
4754
4755         g_assert (method);
4756
4757         if (method->wrapper_type == MONO_WRAPPER_SYNCHRONIZED)
4758                 return method;
4759
4760         cache = method->klass->image->synchronized_cache;
4761         if ((res = mono_marshal_find_in_cache (cache, method)))
4762                 return res;
4763
4764         sig = method->signature;
4765
4766         mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_SYNCHRONIZED);
4767
4768         /* result */
4769         if (!MONO_TYPE_IS_VOID (sig->ret))
4770                 ret_local = mono_mb_add_local (mb, sig->ret);
4771
4772         /* this */
4773         this_local = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
4774
4775         clause = g_new0 (MonoExceptionClause, 1);
4776         clause->flags = MONO_EXCEPTION_CLAUSE_FINALLY;
4777
4778         if (!enter_method) {
4779                 MonoMethodDesc *desc;
4780
4781                 desc = mono_method_desc_new ("Monitor:Enter", FALSE);
4782                 enter_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
4783                 g_assert (enter_method);
4784                 mono_method_desc_free (desc);
4785                 desc = mono_method_desc_new ("Monitor:Exit", FALSE);
4786                 exit_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
4787                 g_assert (exit_method);
4788                 mono_method_desc_free (desc);
4789
4790                 /*
4791                  * GetTypeFromHandle isn't called as a managed method because it has
4792                  * a funky calling sequence, e.g. ldtoken+GetTypeFromHandle gets
4793                  * transformed into something else by the JIT.
4794                  */
4795                 from_handle_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
4796                 from_handle_sig->params [0] = &mono_defaults.object_class->byval_arg;
4797                 from_handle_sig->ret = &mono_defaults.object_class->byval_arg;
4798         }
4799
4800         /* Push this or the type object */
4801         if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4802                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
4803                 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
4804                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, &method->klass->byval_arg));
4805                 mono_mb_emit_native_call (mb, from_handle_sig, type_from_handle);
4806         }
4807         else
4808                 mono_mb_emit_ldarg (mb, 0);
4809         mono_mb_emit_stloc (mb, this_local);
4810
4811         /* Call Monitor::Enter() */
4812         mono_mb_emit_ldloc (mb, this_local);
4813         mono_mb_emit_managed_call (mb, enter_method, NULL);
4814
4815         clause->try_offset = mb->pos;
4816
4817         /* Call the method */
4818         if (sig->hasthis)
4819                 mono_mb_emit_ldarg (mb, 0);
4820         for (i = 0; i < sig->param_count; i++)
4821                 mono_mb_emit_ldarg (mb, i + (sig->hasthis == TRUE));
4822         mono_mb_emit_managed_call (mb, method, method->signature);
4823         if (!MONO_TYPE_IS_VOID (sig->ret))
4824                 mono_mb_emit_stloc (mb, ret_local);
4825
4826         mono_mb_emit_byte (mb, CEE_LEAVE);
4827         pos = mb->pos;
4828         mono_mb_emit_i4 (mb, 0);
4829
4830         clause->try_len = mb->pos - clause->try_offset;
4831         clause->handler_offset = mb->pos;
4832
4833         /* Call Monitor::Exit() */
4834         mono_mb_emit_ldloc (mb, this_local);
4835 /*      mono_mb_emit_native_call (mb, exit_sig, mono_monitor_exit); */
4836         mono_mb_emit_managed_call (mb, exit_method, NULL);
4837         mono_mb_emit_byte (mb, CEE_ENDFINALLY);
4838
4839         clause->handler_len = mb->pos - clause->handler_offset;
4840
4841         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
4842         if (!MONO_TYPE_IS_VOID (sig->ret))
4843                 mono_mb_emit_ldloc (mb, ret_local);
4844         mono_mb_emit_byte (mb, CEE_RET);
4845
4846         res = mono_mb_create_and_cache (cache, method,
4847                                                                         mb, sig, sig->param_count + 16);
4848         mono_mb_free (mb);
4849
4850         header = ((MonoMethodNormal *)res)->header;
4851         header->num_clauses = 1;
4852         header->clauses = clause;
4853
4854         return res;     
4855 }
4856
4857 /* FIXME: on win32 we should probably use GlobalAlloc(). */
4858 void*
4859 mono_marshal_alloc (gpointer size) 
4860 {
4861         MONO_ARCH_SAVE_REGS;
4862
4863         if (size == NULL)
4864                 size = (gpointer)4;
4865         return g_try_malloc ((gulong)size);
4866 }
4867
4868 void
4869 mono_marshal_free (gpointer ptr) 
4870 {
4871         MONO_ARCH_SAVE_REGS;
4872
4873         g_free (ptr);
4874 }
4875
4876 void
4877 mono_marshal_free_array (gpointer *ptr, int size) 
4878 {
4879         int i;
4880
4881         if (!ptr)
4882                 return;
4883
4884         for (i = 0; i < size; i++)
4885                 if (ptr [i])
4886                         g_free (ptr [i]);
4887 }
4888
4889 void *
4890 mono_marshal_realloc (gpointer ptr, gpointer size) 
4891 {
4892         MONO_ARCH_SAVE_REGS;
4893
4894         return g_try_realloc (ptr, (gulong)size);
4895 }
4896
4897 void *
4898 mono_marshal_string_array (MonoArray *array)
4899 {
4900         char **result;
4901         int i, len;
4902
4903         if (!array)
4904                 return NULL;
4905
4906         len = mono_array_length (array);
4907
4908         result = g_malloc (sizeof (char *) * (len + 1));
4909         for (i = 0; i < len; ++i) {
4910                 MonoString *s = (MonoString *)mono_array_get (array, gpointer, i);
4911                 result [i] = s ? mono_string_to_utf8 (s): NULL;
4912         }
4913         /* null terminate the array */
4914         result [i] = NULL;
4915
4916         return result;
4917 }
4918
4919 void *
4920 mono_marshal_string_array_to_unicode (MonoArray *array)
4921 {
4922         gunichar2 **result;
4923         int i, len;
4924
4925         if (!array)
4926                 return NULL;
4927
4928         len = mono_array_length (array);
4929
4930         result = g_malloc (sizeof (gunichar2 *) * (len + 1));
4931         for (i = 0; i < len; ++i) {
4932                 MonoString *s = (MonoString *)mono_array_get (array, gpointer, i);
4933                 result [i] = s ? mono_string_chars (s) : NULL;
4934         }
4935         /* null terminate the array */
4936         result [i] = NULL;
4937
4938         return result;
4939 }
4940
4941 /**
4942  * mono_marshal_set_last_error:
4943  *
4944  * This function is invoked to set the last error value from a P/Invoke call
4945  * which has SetLastError set.
4946  */
4947 void
4948 mono_marshal_set_last_error (void)
4949 {
4950 #ifdef WIN32
4951         TlsSetValue (last_error_tls_id, (gpointer)GetLastError ());
4952 #else
4953         TlsSetValue (last_error_tls_id, (gpointer)errno);
4954 #endif
4955 }
4956
4957 void
4958 ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArray *src, gint32 start_index,
4959                                                                     gpointer dest, gint32 length)
4960 {
4961         int element_size;
4962         void *source_addr;
4963
4964         MONO_ARCH_SAVE_REGS;
4965
4966         MONO_CHECK_ARG_NULL (src);
4967         MONO_CHECK_ARG_NULL (dest);
4968
4969         g_assert (src->obj.vtable->klass->rank == 1);
4970         g_assert (start_index >= 0);
4971         g_assert (length >= 0);
4972         g_assert (start_index + length <= mono_array_length (src));
4973
4974         element_size = mono_array_element_size (src->obj.vtable->klass);
4975           
4976         source_addr = mono_array_addr_with_size (src, element_size, start_index);
4977
4978         memcpy (dest, source_addr, length * element_size);
4979 }
4980
4981 void
4982 ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer src, gint32 start_index,
4983                                                                       MonoArray *dest, gint32 length)
4984 {
4985         int element_size;
4986         void *dest_addr;
4987
4988         MONO_ARCH_SAVE_REGS;
4989
4990         MONO_CHECK_ARG_NULL (src);
4991         MONO_CHECK_ARG_NULL (dest);
4992
4993         g_assert (dest->obj.vtable->klass->rank == 1);
4994         g_assert (start_index >= 0);
4995         g_assert (length >= 0);
4996         g_assert (start_index + length <= mono_array_length (dest));
4997
4998         element_size = mono_array_element_size (dest->obj.vtable->klass);
4999           
5000         dest_addr = mono_array_addr_with_size (dest, element_size, start_index);
5001
5002         memcpy (dest_addr, src, length * element_size);
5003 }
5004
5005 #if NO_UNALIGNED_ACCESS
5006 #define RETURN_UNALIGNED(type, addr) \
5007         { \
5008                 type val; \
5009                 memcpy(&val, p + offset, sizeof(val)); \
5010                 return val; \
5011         }
5012 #define WRITE_UNALIGNED(type, addr, val) \
5013         memcpy(addr, &val, sizeof(type))
5014 #else
5015 #define RETURN_UNALIGNED(type, addr) \
5016         return *(type*)(p + offset);
5017 #define WRITE_UNALIGNED(type, addr, val) \
5018         (*(type *)(addr) = (val))
5019 #endif
5020
5021 gpointer
5022 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr, gint32 offset)
5023 {
5024         char *p = ptr;
5025
5026         MONO_ARCH_SAVE_REGS;
5027
5028         RETURN_UNALIGNED(gpointer, p + offset);
5029 }
5030
5031 unsigned char
5032 ves_icall_System_Runtime_InteropServices_Marshal_ReadByte (gpointer ptr, gint32 offset)
5033 {
5034         char *p = ptr;
5035
5036         MONO_ARCH_SAVE_REGS;
5037
5038         return *(unsigned char*)(p + offset);
5039 }
5040
5041 gint16
5042 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt16 (gpointer ptr, gint32 offset)
5043 {
5044         char *p = ptr;
5045
5046         MONO_ARCH_SAVE_REGS;
5047
5048         RETURN_UNALIGNED(gint16, p + offset);
5049 }
5050
5051 gint32
5052 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt32 (gpointer ptr, gint32 offset)
5053 {
5054         char *p = ptr;
5055
5056         MONO_ARCH_SAVE_REGS;
5057
5058         RETURN_UNALIGNED(gint32, p + offset);
5059 }
5060
5061 gint64
5062 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt64 (gpointer ptr, gint32 offset)
5063 {
5064         char *p = ptr;
5065
5066         MONO_ARCH_SAVE_REGS;
5067
5068         RETURN_UNALIGNED(gint64, p + offset);
5069 }
5070
5071 void
5072 ves_icall_System_Runtime_InteropServices_Marshal_WriteByte (gpointer ptr, gint32 offset, unsigned char val)
5073 {
5074         char *p = ptr;
5075
5076         MONO_ARCH_SAVE_REGS;
5077
5078         *(unsigned char*)(p + offset) = val;
5079 }
5080
5081 void
5082 ves_icall_System_Runtime_InteropServices_Marshal_WriteIntPtr (gpointer ptr, gint32 offset, gpointer val)
5083 {
5084         char *p = ptr;
5085
5086         MONO_ARCH_SAVE_REGS;
5087
5088         WRITE_UNALIGNED(gpointer, p + offset, val);
5089 }
5090
5091 void
5092 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt16 (gpointer ptr, gint32 offset, gint16 val)
5093 {
5094         char *p = ptr;
5095
5096         MONO_ARCH_SAVE_REGS;
5097
5098         WRITE_UNALIGNED(gint16, p + offset, val);
5099 }
5100
5101 void
5102 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt32 (gpointer ptr, gint32 offset, gint32 val)
5103 {
5104         char *p = ptr;
5105
5106         MONO_ARCH_SAVE_REGS;
5107
5108         WRITE_UNALIGNED(gint32, p + offset, val);
5109 }
5110
5111 void
5112 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt64 (gpointer ptr, gint32 offset, gint64 val)
5113 {
5114         char *p = ptr;
5115
5116         MONO_ARCH_SAVE_REGS;
5117
5118         WRITE_UNALIGNED(gint64, p + offset, val);
5119 }
5120
5121 MonoString *
5122 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (char *ptr)
5123 {
5124         MONO_ARCH_SAVE_REGS;
5125
5126         if (ptr == NULL)
5127                 return mono_string_new (mono_domain_get (), "");
5128         else
5129                 return mono_string_new (mono_domain_get (), ptr);
5130 }
5131
5132 MonoString *
5133 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len (char *ptr, gint32 len)
5134 {
5135         MONO_ARCH_SAVE_REGS;
5136
5137         if (ptr == NULL)
5138                 return mono_string_new (mono_domain_get (), "");
5139         else
5140                 return mono_string_new_len (mono_domain_get (), ptr, len);
5141 }
5142
5143 MonoString *
5144 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni (guint16 *ptr)
5145 {
5146         MonoDomain *domain = mono_domain_get (); 
5147         int len = 0;
5148         guint16 *t = ptr;
5149
5150         MONO_ARCH_SAVE_REGS;
5151
5152         if (ptr == NULL)
5153                 return mono_string_new (mono_domain_get (), "");
5154
5155         while (*t++)
5156                 len++;
5157
5158         return mono_string_new_utf16 (domain, ptr, len);
5159 }
5160
5161 MonoString *
5162 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len (guint16 *ptr, gint32 len)
5163 {
5164         MonoDomain *domain = mono_domain_get (); 
5165
5166         MONO_ARCH_SAVE_REGS;
5167
5168         if (ptr == NULL)
5169                 return mono_string_new (mono_domain_get (), "");
5170         else
5171                 return mono_string_new_utf16 (domain, ptr, len);
5172 }
5173
5174 MonoString *
5175 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR (gpointer ptr)
5176 {
5177         MONO_ARCH_SAVE_REGS;
5178
5179         g_warning ("PtrToStringBSTR not implemented");
5180         g_assert_not_reached ();
5181
5182         return NULL;
5183 }
5184
5185 guint32 
5186 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
5187 {
5188         MONO_ARCH_SAVE_REGS;
5189
5190         return ((guint32)TlsGetValue (last_error_tls_id));
5191 }
5192
5193 guint32 
5194 ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype)
5195 {
5196         MonoClass *klass;
5197         MonoType *type;
5198         guint32 layout;
5199
5200         MONO_ARCH_SAVE_REGS;
5201
5202         MONO_CHECK_ARG_NULL (rtype);
5203
5204         type = rtype->type;
5205         klass = mono_class_from_mono_type (type);
5206         layout = (klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK);
5207
5208         if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
5209                 gchar *msg;
5210                 MonoException *exc;
5211
5212                 msg = g_strdup_printf ("Type %s cannot be marshaled as an unmanaged structure.", klass->name);
5213                 exc = mono_get_exception_argument ("t", msg);
5214                 g_free (msg);
5215                 mono_raise_exception (exc);
5216         }
5217
5218
5219         return mono_class_native_size (klass, NULL);
5220 }
5221
5222 void
5223 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old)
5224 {
5225         MonoMethod *method;
5226         gpointer pa [3];
5227
5228         MONO_ARCH_SAVE_REGS;
5229
5230         MONO_CHECK_ARG_NULL (obj);
5231         MONO_CHECK_ARG_NULL (dst);
5232
5233         method = mono_marshal_get_struct_to_ptr (obj->vtable->klass);
5234
5235         pa [0] = obj;
5236         pa [1] = &dst;
5237         pa [2] = &delete_old;
5238
5239         mono_runtime_invoke (method, NULL, pa, NULL);
5240 }
5241
5242 void
5243 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, MonoObject *dst)
5244 {
5245         MonoMethod *method;
5246         gpointer pa [2];
5247
5248         MONO_ARCH_SAVE_REGS;
5249
5250         MONO_CHECK_ARG_NULL (src);
5251         MONO_CHECK_ARG_NULL (dst);
5252
5253         method = mono_marshal_get_ptr_to_struct (dst->vtable->klass);
5254
5255         pa [0] = &src;
5256         pa [1] = dst;
5257
5258         mono_runtime_invoke (method, NULL, pa, NULL);
5259 }
5260
5261 MonoObject *
5262 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer src, MonoReflectionType *type)
5263 {
5264         MonoDomain *domain = mono_domain_get (); 
5265         MonoObject *res;
5266
5267         MONO_ARCH_SAVE_REGS;
5268
5269         MONO_CHECK_ARG_NULL (src);
5270         MONO_CHECK_ARG_NULL (type);
5271
5272         res = mono_object_new (domain, mono_class_from_mono_type (type->type));
5273
5274         ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (src, res);
5275
5276         return res;
5277 }
5278
5279 int
5280 ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *type, MonoString *field_name)
5281 {
5282         MonoMarshalType *info;
5283         MonoClass *klass;
5284         char *fname;
5285         int i, match_index = -1;
5286         
5287         MONO_ARCH_SAVE_REGS;
5288
5289         MONO_CHECK_ARG_NULL (type);
5290         MONO_CHECK_ARG_NULL (field_name);
5291
5292         fname = mono_string_to_utf8 (field_name);
5293         klass = mono_class_from_mono_type (type->type);
5294
5295         while(klass && match_index == -1) {
5296                 for (i = 0; i < klass->field.count; ++i) {
5297                         if (*fname == *klass->fields [i].name && strcmp (fname, klass->fields [i].name) == 0) {
5298                                 match_index = i;
5299                                 break;
5300                         }
5301                 }
5302
5303                 if(match_index == -1)
5304                         klass = klass->parent;
5305         }
5306
5307         g_free (fname);
5308
5309         if(match_index == -1) {
5310                MonoException* exc;
5311                gchar *tmp;
5312
5313                /* Get back original class instance */
5314                klass = mono_class_from_mono_type (type->type);
5315
5316                tmp = g_strdup_printf ("Field passed in is not a marshaled member of the type %s", klass->name);
5317                exc = mono_get_exception_argument ("fieldName", tmp);
5318                g_free (tmp);
5319  
5320                mono_raise_exception ((MonoException*)exc);
5321        }
5322
5323        info = mono_marshal_load_type_info (klass);     
5324        return info->fields [match_index].offset;
5325 }
5326
5327 gpointer
5328 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString *string)
5329 {
5330         MONO_ARCH_SAVE_REGS;
5331
5332         return mono_string_to_utf8 (string);
5333 }
5334
5335 gpointer
5336 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni (MonoString *string)
5337 {
5338         MONO_ARCH_SAVE_REGS;
5339
5340         if (string == NULL)
5341                 return NULL;
5342         else
5343                 return g_memdup (mono_string_chars (string), mono_string_length (string)*2);
5344 }
5345
5346 static void
5347 mono_struct_delete_old (MonoClass *klass, char *ptr)
5348 {
5349         MonoMarshalType *info;
5350         int i;
5351
5352         info = mono_marshal_load_type_info (klass);
5353
5354         for (i = 0; i < info->num_fields; i++) {
5355                 MonoMarshalNative ntype;
5356                 MonoMarshalConv conv;
5357                 MonoType *ftype = info->fields [i].field->type;
5358                 char *cpos;
5359
5360                 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
5361                         continue;
5362
5363                 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, 
5364                                                 klass->unicode, &conv);
5365                         
5366                 cpos = ptr + info->fields [i].offset;
5367
5368                 switch (conv) {
5369                 case MONO_MARSHAL_CONV_NONE:
5370                         if (MONO_TYPE_ISSTRUCT (ftype)) {
5371                                 mono_struct_delete_old (ftype->data.klass, cpos);
5372                                 continue;
5373                         }
5374                         break;
5375                 case MONO_MARSHAL_CONV_STR_LPWSTR:
5376                 case MONO_MARSHAL_CONV_STR_LPSTR:
5377                 case MONO_MARSHAL_CONV_STR_LPTSTR:
5378                 case MONO_MARSHAL_CONV_STR_BSTR:
5379                 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
5380                 case MONO_MARSHAL_CONV_STR_TBSTR:
5381                         g_free (*(gpointer *)cpos);
5382                         break;
5383                 default:
5384                         continue;
5385                 }
5386         }
5387 }
5388
5389 void
5390 ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure (gpointer src, MonoReflectionType *type)
5391 {
5392         MonoClass *klass;
5393
5394         MONO_ARCH_SAVE_REGS;
5395
5396         MONO_CHECK_ARG_NULL (src);
5397         MONO_CHECK_ARG_NULL (type);
5398
5399         klass = mono_class_from_mono_type (type->type);
5400
5401         mono_struct_delete_old (klass, (char *)src);
5402 }
5403
5404 void*
5405 ves_icall_System_Runtime_InteropServices_Marshal_AllocCoTaskMem (int size)
5406 {
5407         /* FIXME: Call AllocCoTaskMem under windows */
5408         MONO_ARCH_SAVE_REGS;
5409
5410         return g_try_malloc ((gulong)size);
5411 }
5412
5413 void
5414 ves_icall_System_Runtime_InteropServices_Marshal_FreeCoTaskMem (void *ptr)
5415 {
5416         /* FIXME: Call FreeCoTaskMem under windows */
5417         MONO_ARCH_SAVE_REGS;
5418
5419         g_free (ptr);
5420 }
5421
5422 void*
5423 ves_icall_System_Runtime_InteropServices_Marshal_UnsafeAddrOfPinnedArrayElement (MonoArray *arrayobj, int index)
5424 {
5425         return mono_array_addr_with_size (arrayobj, mono_array_element_size (arrayobj->obj.vtable->klass), index);
5426 }
5427
5428 MonoMarshalType *
5429 mono_marshal_load_type_info (MonoClass* klass)
5430 {
5431         int i, j, count = 0, native_size = 0, min_align = 1;
5432         MonoMarshalType *info;
5433         guint32 layout;
5434
5435         g_assert (klass != NULL);
5436
5437         if (klass->marshal_info)
5438                 return klass->marshal_info;
5439
5440         if (!klass->inited)
5441                 mono_class_init (klass);
5442         
5443         for (i = 0; i < klass->field.count; ++i) {
5444                 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
5445                         continue;
5446                 if (mono_field_is_deleted (&klass->fields [i]))
5447                         continue;
5448                 count++;
5449         }
5450
5451         layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
5452
5453         klass->marshal_info = info = g_malloc0 (sizeof (MonoMarshalType) + sizeof (MonoMarshalField) * count);
5454         info->num_fields = count;
5455         
5456         /* Try to find a size for this type in metadata */
5457         mono_metadata_packing_from_typedef (klass->image, klass->type_token, NULL, &native_size);
5458
5459         if (klass->parent) {
5460                 int parent_size = mono_class_native_size (klass->parent, NULL);
5461
5462                 /* Add parent size to real size */
5463                 native_size += parent_size;
5464                 info->native_size = parent_size;
5465         }
5466  
5467         for (j = i = 0; i < klass->field.count; ++i) {
5468                 int size, align;
5469                 
5470                 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
5471                         continue;
5472
5473                 if (mono_field_is_deleted (&klass->fields [i]))
5474                         continue;
5475                 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL)
5476                         mono_metadata_field_info (klass->image, klass->field.first + i, 
5477                                                   NULL, NULL, &info->fields [j].mspec);
5478
5479                 info->fields [j].field = &klass->fields [i];
5480
5481                 if ((klass->field.count == 1) && (klass->instance_size == sizeof (MonoObject)) &&
5482                         (strcmp (klass->fields [i].name, "$PRIVATE$") == 0)) {
5483                         /* This field is a hack inserted by MCS to empty structures */
5484                         continue;
5485                 }
5486
5487                 switch (layout) {
5488                 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
5489                 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
5490                         size = mono_marshal_type_size (klass->fields [i].type, info->fields [j].mspec, 
5491                                                        &align, TRUE, klass->unicode);
5492                         align = klass->packing_size ? MIN (klass->packing_size, align): align;
5493                         min_align = MAX (align, min_align);
5494                         info->fields [j].offset = info->native_size;
5495                         info->fields [j].offset += align - 1;
5496                         info->fields [j].offset &= ~(align - 1);
5497                         info->native_size = info->fields [j].offset + size;
5498                         break;
5499                 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
5500                         size = mono_marshal_type_size (klass->fields [i].type, info->fields [j].mspec, 
5501                                                        &align, TRUE, klass->unicode);
5502                         align = klass->packing_size ? MIN (klass->packing_size, align): align;
5503                         min_align = MAX (align, min_align);
5504                         info->fields [j].offset = klass->fields [i].offset - sizeof (MonoObject);
5505                         info->native_size = MAX (info->native_size, info->fields [j].offset + size);
5506                         break;
5507                 }       
5508                 j++;
5509         }
5510
5511         if(layout != TYPE_ATTRIBUTE_AUTO_LAYOUT) {
5512                 info->native_size = MAX (native_size, info->native_size);
5513         }
5514
5515         if (info->native_size & (min_align - 1)) {
5516                 info->native_size += min_align - 1;
5517                 info->native_size &= ~(min_align - 1);
5518         }
5519
5520         /* Update the class's blittable info, if the layouts don't match */
5521         if (info->native_size != mono_class_value_size (klass, NULL))
5522                 klass->blittable = FALSE;
5523
5524         /* If this is an array type, ensure that we have element info */
5525         if (klass->element_class) {
5526                 mono_marshal_load_type_info (klass->element_class);
5527         }
5528
5529         return klass->marshal_info;
5530 }
5531
5532 /**
5533  * mono_class_native_size:
5534  * @klass: a class 
5535  * 
5536  * Returns: the native size of an object instance (when marshaled 
5537  * to unmanaged code) 
5538  */
5539 gint32
5540 mono_class_native_size (MonoClass *klass, guint32 *align)
5541 {
5542         
5543         if (!klass->marshal_info)
5544                 mono_marshal_load_type_info (klass);
5545
5546         if (align)
5547                 *align = klass->min_align;
5548
5549         return klass->marshal_info->native_size;
5550 }
5551
5552 /*
5553  * mono_type_native_stack_size:
5554  * @t: the type to return the size it uses on the stack
5555  *
5556  * Returns: the number of bytes required to hold an instance of this
5557  * type on the native stack
5558  */
5559 int
5560 mono_type_native_stack_size (MonoType *t, gint *align)
5561 {
5562         int tmp;
5563
5564         g_assert (t != NULL);
5565
5566         if (!align)
5567                 align = &tmp;
5568
5569         if (t->byref) {
5570                 *align = 4;
5571                 return 4;
5572         }
5573
5574         switch (t->type){
5575         case MONO_TYPE_BOOLEAN:
5576         case MONO_TYPE_CHAR:
5577         case MONO_TYPE_I1:
5578         case MONO_TYPE_U1:
5579         case MONO_TYPE_I2:
5580         case MONO_TYPE_U2:
5581         case MONO_TYPE_I4:
5582         case MONO_TYPE_U4:
5583         case MONO_TYPE_I:
5584         case MONO_TYPE_U:
5585         case MONO_TYPE_STRING:
5586         case MONO_TYPE_OBJECT:
5587         case MONO_TYPE_CLASS:
5588         case MONO_TYPE_SZARRAY:
5589         case MONO_TYPE_PTR:
5590         case MONO_TYPE_FNPTR:
5591         case MONO_TYPE_ARRAY:
5592         case MONO_TYPE_TYPEDBYREF:
5593                 *align = 4;
5594                 return 4;
5595         case MONO_TYPE_R4:
5596                 *align = 4;
5597                 return 4;
5598         case MONO_TYPE_I8:
5599         case MONO_TYPE_U8:
5600         case MONO_TYPE_R8:
5601                 *align = 4;
5602                 return 8;
5603         case MONO_TYPE_VALUETYPE: {
5604                 guint32 size;
5605
5606                 if (t->data.klass->enumtype)
5607                         return mono_type_native_stack_size (t->data.klass->enum_basetype, align);
5608                 else {
5609                         size = mono_class_native_size (t->data.klass, align);
5610                         *align = *align + 3;
5611                         *align &= ~3;
5612                         
5613                         size +=  3;
5614                         size &= ~3;
5615
5616                         return size;
5617                 }
5618         }
5619         default:
5620                 g_error ("type 0x%02x unknown", t->type);
5621         }
5622         return 0;
5623 }
5624
5625 /* __alignof__ returns the preferred alignment of values not the actual alignment used by
5626    the compiler so is wrong e.g. for Linux where doubles are aligned on a 4 byte boundary
5627    but __alignof__ returns 8 - using G_STRUCT_OFFSET works better */
5628 #define ALIGNMENT(type) G_STRUCT_OFFSET(struct { char c; type x; }, x)
5629
5630 gint32
5631 mono_marshal_type_size (MonoType *type, MonoMarshalSpec *mspec, gint32 *align, 
5632                         gboolean as_field, gboolean unicode)
5633 {
5634         MonoMarshalNative native_type = mono_type_to_unmanaged (type, mspec, as_field, unicode, NULL);
5635         MonoClass *klass;
5636
5637         switch (native_type) {
5638         case MONO_NATIVE_BOOLEAN:
5639                 *align = 4;
5640                 return 4;
5641         case MONO_NATIVE_I1:
5642         case MONO_NATIVE_U1:
5643                 *align = 1;
5644                 return 1;
5645         case MONO_NATIVE_I2:
5646         case MONO_NATIVE_U2:
5647         case MONO_NATIVE_VARIANTBOOL:
5648                 *align = 2;
5649                 return 2;
5650         case MONO_NATIVE_I4:
5651         case MONO_NATIVE_U4:
5652         case MONO_NATIVE_ERROR:
5653                 *align = 4;
5654                 return 4;
5655         case MONO_NATIVE_I8:
5656         case MONO_NATIVE_U8:
5657                 *align = ALIGNMENT(guint64);
5658                 return 8;
5659         case MONO_NATIVE_R4:
5660                 *align = 4;
5661                 return 4;
5662         case MONO_NATIVE_R8:
5663                 *align = ALIGNMENT(double);
5664                 return 8;
5665         case MONO_NATIVE_INT:
5666         case MONO_NATIVE_UINT:
5667         case MONO_NATIVE_LPSTR:
5668         case MONO_NATIVE_LPWSTR:
5669         case MONO_NATIVE_LPTSTR:
5670         case MONO_NATIVE_BSTR:
5671         case MONO_NATIVE_ANSIBSTR:
5672         case MONO_NATIVE_TBSTR:
5673         case MONO_NATIVE_LPARRAY:
5674         case MONO_NATIVE_SAFEARRAY:
5675         case MONO_NATIVE_IUNKNOWN:
5676         case MONO_NATIVE_IDISPATCH:
5677         case MONO_NATIVE_INTERFACE:
5678         case MONO_NATIVE_ASANY:
5679         case MONO_NATIVE_FUNC:
5680         case MONO_NATIVE_LPSTRUCT:
5681                 *align = ALIGNMENT(gpointer);
5682                 return sizeof (gpointer);
5683         case MONO_NATIVE_STRUCT: 
5684                 klass = mono_class_from_mono_type (type);
5685                 return mono_class_native_size (klass, align);
5686         case MONO_NATIVE_BYVALTSTR: {
5687                 int esize = unicode ? 2: 1;
5688                 g_assert (mspec);
5689                 *align = esize;
5690                 return mspec->data.array_data.num_elem * esize;
5691         }
5692         case MONO_NATIVE_BYVALARRAY: {
5693                 int esize;
5694                 klass = mono_class_from_mono_type (type);
5695                 esize = mono_class_native_size (klass->element_class, align);
5696                 g_assert (mspec);
5697                 return mspec->data.array_data.num_elem * esize;
5698         }
5699         case MONO_NATIVE_CUSTOM:
5700                 g_assert_not_reached ();
5701                 break;
5702         case MONO_NATIVE_CURRENCY:
5703         case MONO_NATIVE_VBBYREFSTR:
5704         default:
5705                 g_error ("native type %02x not implemented", native_type); 
5706                 break;
5707         }
5708         g_assert_not_reached ();
5709         return 0;
5710 }
5711
5712 gpointer
5713 mono_marshal_asany (MonoObject *o, MonoMarshalNative string_encoding)
5714 {
5715         MonoType *t;
5716         MonoClass *klass;
5717
5718         if (o == NULL)
5719                 return NULL;
5720
5721         t = &o->vtable->klass->byval_arg;
5722         switch (t->type) {
5723         case MONO_TYPE_I4:
5724         case MONO_TYPE_U4:
5725         case MONO_TYPE_PTR:
5726         case MONO_TYPE_I1:
5727         case MONO_TYPE_U1:
5728         case MONO_TYPE_BOOLEAN:
5729         case MONO_TYPE_I2:
5730         case MONO_TYPE_U2:
5731         case MONO_TYPE_CHAR:
5732         case MONO_TYPE_I8:
5733         case MONO_TYPE_U8:
5734         case MONO_TYPE_R4:
5735         case MONO_TYPE_R8:
5736                 return mono_object_unbox (o);
5737                 break;
5738         case MONO_TYPE_STRING:
5739                 switch (string_encoding) {
5740                 case MONO_NATIVE_LPWSTR:
5741                         return mono_string_to_utf16 ((MonoString*)o);
5742                         break;
5743                 case MONO_NATIVE_LPSTR:
5744                         return mono_string_to_utf8 ((MonoString*)o);
5745                         break;
5746                 default:
5747                         g_warning ("marshaling conversion %d not implemented", string_encoding);
5748                         g_assert_not_reached ();
5749                 }
5750                 break;
5751         case MONO_TYPE_CLASS:
5752         case MONO_TYPE_VALUETYPE: {
5753                 MonoMethod *method;
5754                 gpointer pa [3];
5755                 gpointer res;
5756                 MonoBoolean delete_old = FALSE;
5757
5758                 klass = t->data.klass;
5759
5760                 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT)
5761                         break;
5762
5763                 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
5764                         klass->blittable || klass->enumtype)
5765                         return mono_object_unbox (o);
5766
5767                 res = g_malloc0 (mono_class_native_size (klass, NULL));
5768
5769                 method = mono_marshal_get_struct_to_ptr (o->vtable->klass);
5770
5771                 pa [0] = o;
5772                 pa [1] = &res;
5773                 pa [2] = &delete_old;
5774
5775                 mono_runtime_invoke (method, NULL, pa, NULL);
5776
5777                 return res;
5778         }
5779         }
5780
5781         mono_raise_exception (mono_get_exception_argument ("", "No PInvoke conversion exists for value passed to Object-typed parameter."));
5782
5783         return NULL;
5784 }
5785
5786 void
5787 mono_marshal_free_asany (MonoObject *o, gpointer ptr, MonoMarshalNative string_encoding)
5788 {
5789         MonoType *t;
5790         MonoClass *klass;
5791
5792         /* FIXME: Free embedded data as well */
5793
5794         if (o == NULL)
5795                 return;
5796
5797         t = &o->vtable->klass->byval_arg;
5798         switch (t->type) {
5799         case MONO_TYPE_STRING:
5800                 switch (string_encoding) {
5801                 case MONO_NATIVE_LPWSTR:
5802                         g_free (ptr);
5803                         break;
5804                 case MONO_NATIVE_LPSTR:
5805                         g_free (ptr);
5806                         break;
5807                 default:
5808                         g_warning ("marshaling conversion %d not implemented", string_encoding);
5809                         g_assert_not_reached ();
5810                 }
5811                 break;
5812         case MONO_TYPE_CLASS:
5813         case MONO_TYPE_VALUETYPE: {
5814                 klass = t->data.klass;
5815
5816                 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
5817                         klass->blittable || klass->enumtype)
5818                         break;
5819
5820                 g_free (ptr);
5821                 break;
5822         }
5823         default:
5824                 break;
5825         }
5826 }
5827