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