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