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