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