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