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