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