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