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