* mono-endian.h, mono-endian.c: new macro MONO_DOUBLE_ASSERT_ENDIANITY to
[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 = type->data.klass;
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 = type->data.klass;
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 || (t->attrs & PARAM_ATTRIBUTE_OUT)))
3139                                 continue;
3140
3141                         if (t->byref && (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
3153                         if (t->byref)
3154                                 mono_mb_emit_byte (mb, CEE_LDIND_I);
3155
3156                         mono_mb_emit_byte (mb, CEE_STLOC_1);
3157
3158                         mono_mb_emit_byte (mb, CEE_LDLOC_1);
3159                         mono_mb_emit_byte (mb, CEE_BRFALSE);
3160                         pos = mb->pos;
3161                         mono_mb_emit_i4 (mb, 0);
3162
3163                         mono_mb_emit_byte (mb, CEE_LDLOC_1);
3164                         mono_mb_emit_icon (mb, sizeof (MonoObject));
3165                         mono_mb_emit_byte (mb, CEE_ADD);
3166                         mono_mb_emit_byte (mb, CEE_STLOC_1);
3167                         
3168                         /* src = tmp_locals [i] */
3169                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
3170                         mono_mb_emit_byte (mb, CEE_STLOC_0);
3171
3172                         /* emit valuetype conversion code */
3173                         emit_struct_conv (mb, klass, TRUE);
3174
3175                         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3176                         break;
3177                 case MONO_TYPE_VALUETYPE:
3178                         if (!t->byref)
3179                                 continue;
3180         
3181                         klass = t->data.klass;
3182                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3183                             klass->blittable || klass->enumtype)
3184                                 break;
3185
3186                         /* dst = argument */
3187                         mono_mb_emit_ldarg (mb, argnum);
3188                         mono_mb_emit_byte (mb, CEE_STLOC_1);
3189
3190                         mono_mb_emit_byte (mb, CEE_LDLOC_1);
3191                         mono_mb_emit_byte (mb, CEE_BRFALSE);
3192                         pos = mb->pos;
3193                         mono_mb_emit_i4 (mb, 0);
3194
3195                         /* src = tmp_locals [i] */
3196                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
3197                         mono_mb_emit_byte (mb, CEE_STLOC_0);
3198
3199                         /* emit valuetype conversion code */
3200                         emit_struct_conv (mb, klass, TRUE);
3201                         
3202                         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3203                         break;
3204                 case MONO_TYPE_SZARRAY:
3205                         if (t->byref)
3206                                 continue;
3207  
3208                         klass = mono_class_from_mono_type (t);
3209                         
3210                         if (klass->element_class == mono_defaults.string_class) {
3211                                 g_assert (tmp_locals [i]);
3212
3213                                 mono_mb_emit_ldarg (mb, argnum);
3214                                 mono_mb_emit_byte (mb, CEE_BRFALSE);
3215                                 pos = mb->pos;
3216                                 mono_mb_emit_i4 (mb, 0);
3217
3218                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3219                                 mono_mb_emit_ldarg (mb, argnum);
3220                                 mono_mb_emit_byte (mb, CEE_LDLEN);                              
3221                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3222                                 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
3223                                 mono_mb_emit_byte (mb, MONO_MARSHAL_FREE_ARRAY);
3224
3225                                 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3226                         }
3227
3228                         break;
3229                 }
3230         }
3231
3232
3233         if (!MONO_TYPE_IS_VOID(sig->ret))
3234                 mono_mb_emit_byte (mb, CEE_LDLOC_3);
3235
3236         mono_mb_emit_byte (mb, CEE_RET);
3237
3238         csig = g_memdup (sig, sigsize);
3239         csig->pinvoke = 0;
3240         res = mono_mb_create_method (mb, csig, csig->param_count + 16);
3241         mono_mb_free (mb);
3242
3243         g_hash_table_insert (cache, method, res);
3244
3245         for (i = sig->param_count; i >= 0; i--)
3246                 g_free (mspecs [i]);
3247         g_free (mspecs);
3248
3249         return res;
3250 }
3251
3252 /*
3253  * generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld)
3254  */
3255 MonoMethod *
3256 mono_marshal_get_struct_to_ptr (MonoClass *klass)
3257 {
3258         MonoMethodBuilder *mb;
3259         static MonoMethod *stoptr = NULL;
3260         MonoMethod *res;
3261
3262         g_assert (klass != NULL);
3263
3264         if (klass->str_to_ptr)
3265                 return klass->str_to_ptr;
3266
3267         if (!stoptr) 
3268                 stoptr = mono_find_method_by_name (mono_defaults.marshal_class, "StructureToPtr", 3);
3269         g_assert (stoptr);
3270
3271         mb = mono_mb_new (klass, stoptr->name, MONO_WRAPPER_UNKNOWN);
3272
3273         if (klass->blittable) {
3274                 mono_mb_emit_byte (mb, CEE_LDARG_1);
3275                 mono_mb_emit_byte (mb, CEE_LDARG_0);
3276                 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3277                 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
3278                 mono_mb_emit_byte (mb, CEE_PREFIX1);
3279                 mono_mb_emit_byte (mb, CEE_CPBLK);
3280         } else {
3281
3282                 /* allocate local 0 (pointer) src_ptr */
3283                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3284                 /* allocate local 1 (pointer) dst_ptr */
3285                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3286                 /* allocate local 2 (boolean) delete_old */
3287                 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
3288                 mono_mb_emit_byte (mb, CEE_LDARG_2);
3289                 mono_mb_emit_byte (mb, CEE_STLOC_2);
3290
3291                 /* initialize src_ptr to point to the start of object data */
3292                 mono_mb_emit_byte (mb, CEE_LDARG_0);
3293                 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3294                 mono_mb_emit_byte (mb, CEE_STLOC_0);
3295
3296                 /* initialize dst_ptr */
3297                 mono_mb_emit_byte (mb, CEE_LDARG_1);
3298                 mono_mb_emit_byte (mb, CEE_STLOC_1);
3299
3300                 emit_struct_conv (mb, klass, FALSE);
3301         }
3302
3303         mono_mb_emit_byte (mb, CEE_RET);
3304
3305         res = mono_mb_create_method (mb, stoptr->signature, 0);
3306         mono_mb_free (mb);
3307
3308         klass->str_to_ptr = res;
3309         return res;
3310 }
3311
3312 /*
3313  * generates IL code for PtrToStructure (IntPtr src, object structure)
3314  */
3315 MonoMethod *
3316 mono_marshal_get_ptr_to_struct (MonoClass *klass)
3317 {
3318         MonoMethodBuilder *mb;
3319         static MonoMethod *ptostr = NULL;
3320         MonoMethod *res;
3321
3322         g_assert (klass != NULL);
3323
3324         if (klass->ptr_to_str)
3325                 return klass->ptr_to_str;
3326
3327         if (!ptostr) 
3328                 ptostr = mono_find_method_by_name (mono_defaults.marshal_class, "PtrToStructure", 2);
3329         g_assert (ptostr);
3330
3331         mb = mono_mb_new (klass, ptostr->name, MONO_WRAPPER_UNKNOWN);
3332
3333         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable) {
3334                 mono_mb_emit_byte (mb, CEE_LDARG_1);
3335                 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3336                 mono_mb_emit_byte (mb, CEE_LDARG_0);
3337                 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
3338                 mono_mb_emit_byte (mb, CEE_PREFIX1);
3339                 mono_mb_emit_byte (mb, CEE_CPBLK);
3340         } else {
3341
3342                 /* allocate local 0 (pointer) src_ptr */
3343                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3344                 /* allocate local 1 (pointer) dst_ptr */
3345                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3346                 
3347                 /* initialize src_ptr to point to the start of object data */
3348                 mono_mb_emit_byte (mb, CEE_LDARG_0);
3349                 mono_mb_emit_byte (mb, CEE_STLOC_0);
3350
3351                 /* initialize dst_ptr */
3352                 mono_mb_emit_byte (mb, CEE_LDARG_1);
3353                 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3354                 mono_mb_emit_byte (mb, CEE_STLOC_1);
3355
3356                 emit_struct_conv (mb, klass, TRUE);
3357         }
3358
3359         mono_mb_emit_byte (mb, CEE_RET);
3360
3361         res = mono_mb_create_method (mb, ptostr->signature, 0);
3362         mono_mb_free (mb);
3363
3364         klass->ptr_to_str = res;
3365         return res;
3366 }
3367
3368 static MonoReflectionType *
3369 type_from_handle (MonoType *handle)
3370 {
3371         MonoDomain *domain = mono_domain_get (); 
3372         MonoClass *klass = mono_class_from_mono_type (handle);
3373
3374         MONO_ARCH_SAVE_REGS;
3375
3376         mono_class_init (klass);
3377         return mono_type_get_object (domain, handle);
3378 }
3379
3380 /*
3381  * generates IL code for the synchronized wrapper: the generated method
3382  * calls METHOD while locking 'this' or the parent type.
3383  */
3384 MonoMethod *
3385 mono_marshal_get_synchronized_wrapper (MonoMethod *method)
3386 {
3387         static MonoMethodSignature *from_handle_sig = NULL;
3388         static MonoMethod *enter_method, *exit_method;
3389         MonoMethodSignature *sig;
3390         MonoExceptionClause *clause;
3391         MonoMethodHeader *header;
3392         MonoMethodBuilder *mb;
3393         MonoMethod *res;
3394         GHashTable *cache;
3395         int i, pos, this_local, ret_local;
3396
3397         g_assert (method);
3398
3399         if (method->wrapper_type == MONO_WRAPPER_SYNCHRONIZED)
3400                 return method;
3401
3402         cache = method->klass->image->synchronized_cache;
3403         if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
3404                 return res;
3405
3406         sig = method->signature;
3407
3408         mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_SYNCHRONIZED);
3409
3410         /* result */
3411         if (!MONO_TYPE_IS_VOID (sig->ret))
3412                 ret_local = mono_mb_add_local (mb, sig->ret);
3413
3414         /* this */
3415         this_local = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
3416
3417         clause = g_new0 (MonoExceptionClause, 1);
3418         clause->flags = MONO_EXCEPTION_CLAUSE_FINALLY;
3419
3420         if (!enter_method) {
3421                 MonoMethodDesc *desc;
3422
3423                 desc = mono_method_desc_new ("Monitor:Enter", FALSE);
3424                 enter_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
3425                 g_assert (enter_method);
3426                 mono_method_desc_free (desc);
3427                 desc = mono_method_desc_new ("Monitor:Exit", FALSE);
3428                 exit_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
3429                 g_assert (exit_method);
3430                 mono_method_desc_free (desc);
3431
3432                 /*
3433                  * GetTypeFromHandle isn't called as a managed method because it has
3434                  * a funky calling sequence, e.g. ldtoken+GetTypeFromHandle gets
3435                  * transformed into something else by the JIT.
3436                  */
3437                 from_handle_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
3438                 from_handle_sig->params [0] = &mono_defaults.object_class->byval_arg;
3439                 from_handle_sig->ret = &mono_defaults.object_class->byval_arg;
3440         }
3441
3442         /* Push this or the type object */
3443         if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3444                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3445                 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
3446                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, &method->klass->byval_arg));
3447                 mono_mb_emit_native_call (mb, from_handle_sig, type_from_handle);
3448         }
3449         else
3450                 mono_mb_emit_ldarg (mb, 0);
3451         mono_mb_emit_stloc (mb, this_local);
3452
3453         /* Call Monitor::Enter() */
3454         mono_mb_emit_ldloc (mb, this_local);
3455         mono_mb_emit_managed_call (mb, enter_method, NULL);
3456
3457         clause->try_offset = mb->pos;
3458
3459         /* Call the method */
3460         if (sig->hasthis)
3461                 mono_mb_emit_ldarg (mb, 0);
3462         for (i = 0; i < sig->param_count; i++)
3463                 mono_mb_emit_ldarg (mb, i + (sig->hasthis == TRUE));
3464         mono_mb_emit_managed_call (mb, method, method->signature);
3465         if (!MONO_TYPE_IS_VOID (sig->ret))
3466                 mono_mb_emit_stloc (mb, ret_local);
3467
3468         mono_mb_emit_byte (mb, CEE_LEAVE);
3469         pos = mb->pos;
3470         mono_mb_emit_i4 (mb, 0);
3471
3472         clause->try_len = mb->pos - clause->try_offset;
3473         clause->handler_offset = mb->pos;
3474
3475         /* Call Monitor::Exit() */
3476         mono_mb_emit_ldloc (mb, this_local);
3477 //      mono_mb_emit_native_call (mb, exit_sig, mono_monitor_exit);
3478         mono_mb_emit_managed_call (mb, exit_method, NULL);
3479         mono_mb_emit_byte (mb, CEE_ENDFINALLY);
3480
3481         clause->handler_len = mb->pos - clause->handler_offset;
3482
3483         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3484         if (!MONO_TYPE_IS_VOID (sig->ret))
3485                 mono_mb_emit_ldloc (mb, ret_local);
3486         mono_mb_emit_byte (mb, CEE_RET);
3487
3488         res = mono_mb_create_method (mb, sig, sig->param_count + 16);
3489         mono_mb_free (mb);
3490
3491         header = ((MonoMethodNormal *)res)->header;
3492         header->num_clauses = 1;
3493         header->clauses = clause;
3494
3495         g_hash_table_insert (cache, method, res);
3496
3497         return res;     
3498 }
3499
3500 /* FIXME: on win32 we should probably use GlobalAlloc(). */
3501 void*
3502 mono_marshal_alloc (gpointer size) 
3503 {
3504         MONO_ARCH_SAVE_REGS;
3505
3506         return g_try_malloc ((gulong)size);
3507 }
3508
3509 void
3510 mono_marshal_free (gpointer ptr) 
3511 {
3512         MONO_ARCH_SAVE_REGS;
3513
3514         g_free (ptr);
3515 }
3516
3517 void
3518 mono_marshal_free_array (gpointer *ptr, int size) 
3519 {
3520         int i;
3521
3522         if (!ptr)
3523                 return;
3524
3525         for (i = 0; i < size; i++)
3526                 if (ptr [i])
3527                         g_free (ptr [i]);
3528 }
3529
3530 void *
3531 mono_marshal_realloc (gpointer ptr, gpointer size) 
3532 {
3533         MONO_ARCH_SAVE_REGS;
3534
3535         return g_try_realloc (ptr, (gulong)size);
3536 }
3537
3538 void *
3539 mono_marshal_string_array (MonoArray *array)
3540 {
3541         char **result;
3542         int i, len;
3543
3544         if (!array)
3545                 return NULL;
3546
3547         len = mono_array_length (array);
3548
3549         result = g_malloc (sizeof (char *) * (len + 1));
3550         for (i = 0; i < len; ++i) {
3551                 MonoString *s = (MonoString *)mono_array_get (array, gpointer, i);
3552                 result [i] = s ? mono_string_to_utf8 (s): NULL;
3553         }
3554         /* null terminate the array */
3555         result [i] = NULL;
3556
3557         return result;
3558 }
3559
3560 void
3561 ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArray *src, gint32 start_index,
3562                                                                     gpointer dest, gint32 length)
3563 {
3564         int element_size;
3565         void *source_addr;
3566
3567         MONO_ARCH_SAVE_REGS;
3568
3569         MONO_CHECK_ARG_NULL (src);
3570         MONO_CHECK_ARG_NULL (dest);
3571
3572         g_assert (src->obj.vtable->klass->rank == 1);
3573         g_assert (start_index >= 0);
3574         g_assert (length >= 0);
3575         g_assert (start_index + length <= mono_array_length (src));
3576
3577         element_size = mono_array_element_size (src->obj.vtable->klass);
3578           
3579         source_addr = mono_array_addr_with_size (src, element_size, start_index);
3580
3581         memcpy (dest, source_addr, length * element_size);
3582 }
3583
3584 void
3585 ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer src, gint32 start_index,
3586                                                                       MonoArray *dest, gint32 length)
3587 {
3588         int element_size;
3589         void *dest_addr;
3590
3591         MONO_ARCH_SAVE_REGS;
3592
3593         MONO_CHECK_ARG_NULL (src);
3594         MONO_CHECK_ARG_NULL (dest);
3595
3596         g_assert (dest->obj.vtable->klass->rank == 1);
3597         g_assert (start_index >= 0);
3598         g_assert (length >= 0);
3599         g_assert (start_index + length <= mono_array_length (dest));
3600
3601         element_size = mono_array_element_size (dest->obj.vtable->klass);
3602           
3603         dest_addr = mono_array_addr_with_size (dest, element_size, start_index);
3604
3605         memcpy (dest_addr, src, length * element_size);
3606 }
3607
3608 gpointer
3609 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr, gint32 offset)
3610 {
3611         char *p = ptr;
3612
3613         MONO_ARCH_SAVE_REGS;
3614
3615         return *(gpointer*)(p + offset);
3616 }
3617
3618 unsigned char
3619 ves_icall_System_Runtime_InteropServices_Marshal_ReadByte (gpointer ptr, gint32 offset)
3620 {
3621         char *p = ptr;
3622
3623         MONO_ARCH_SAVE_REGS;
3624
3625         return *(unsigned char*)(p + offset);
3626 }
3627
3628 gint16
3629 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt16 (gpointer ptr, gint32 offset)
3630 {
3631         char *p = ptr;
3632
3633         MONO_ARCH_SAVE_REGS;
3634
3635         return *(gint16*)(p + offset);
3636 }
3637
3638 gint32
3639 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt32 (gpointer ptr, gint32 offset)
3640 {
3641         char *p = ptr;
3642
3643         MONO_ARCH_SAVE_REGS;
3644
3645         return *(gint32*)(p + offset);
3646 }
3647
3648 gint64
3649 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt64 (gpointer ptr, gint32 offset)
3650 {
3651         char *p = ptr;
3652
3653         MONO_ARCH_SAVE_REGS;
3654
3655         return *(gint64*)(p + offset);
3656 }
3657
3658 void
3659 ves_icall_System_Runtime_InteropServices_Marshal_WriteByte (gpointer ptr, gint32 offset, unsigned char val)
3660 {
3661         char *p = ptr;
3662
3663         MONO_ARCH_SAVE_REGS;
3664
3665         *(unsigned char*)(p + offset) = val;
3666 }
3667
3668 void
3669 ves_icall_System_Runtime_InteropServices_Marshal_WriteIntPtr (gpointer ptr, gint32 offset, gpointer val)
3670 {
3671         char *p = ptr;
3672
3673         MONO_ARCH_SAVE_REGS;
3674
3675         *(gpointer*)(p + offset) = val;
3676 }
3677
3678 void
3679 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt16 (gpointer ptr, gint32 offset, gint16 val)
3680 {
3681         char *p = ptr;
3682
3683         MONO_ARCH_SAVE_REGS;
3684
3685         *(gint16*)(p + offset) = val;
3686 }
3687
3688 void
3689 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt32 (gpointer ptr, gint32 offset, gint32 val)
3690 {
3691         char *p = ptr;
3692
3693         MONO_ARCH_SAVE_REGS;
3694
3695         *(gint32*)(p + offset) = val;
3696 }
3697
3698 void
3699 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt64 (gpointer ptr, gint32 offset, gint64 val)
3700 {
3701         char *p = ptr;
3702
3703         MONO_ARCH_SAVE_REGS;
3704
3705         *(gint64*)(p + offset) = val;
3706 }
3707
3708 MonoString *
3709 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (char *ptr)
3710 {
3711         MONO_ARCH_SAVE_REGS;
3712
3713         return mono_string_new (mono_domain_get (), ptr);
3714 }
3715
3716 MonoString *
3717 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len (char *ptr, gint32 len)
3718 {
3719         MONO_ARCH_SAVE_REGS;
3720
3721         return mono_string_new_len (mono_domain_get (), ptr, len);
3722 }
3723
3724 MonoString *
3725 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni (guint16 *ptr)
3726 {
3727         MonoDomain *domain = mono_domain_get (); 
3728         int len = 0;
3729         guint16 *t = ptr;
3730
3731         MONO_ARCH_SAVE_REGS;
3732
3733         while (*t++)
3734                 len++;
3735
3736         return mono_string_new_utf16 (domain, ptr, len);
3737 }
3738
3739 MonoString *
3740 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len (guint16 *ptr, gint32 len)
3741 {
3742         MonoDomain *domain = mono_domain_get (); 
3743
3744         MONO_ARCH_SAVE_REGS;
3745
3746         return mono_string_new_utf16 (domain, ptr, len);
3747 }
3748
3749 MonoString *
3750 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR (gpointer ptr)
3751 {
3752         MONO_ARCH_SAVE_REGS;
3753
3754         g_warning ("PtrToStringBSTR not implemented");
3755         g_assert_not_reached ();
3756
3757         return NULL;
3758 }
3759
3760 guint32 
3761 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
3762 {
3763         MONO_ARCH_SAVE_REGS;
3764
3765         return (GetLastError ());
3766 }
3767
3768 guint32 
3769 ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype)
3770 {
3771         MonoClass *klass;
3772
3773         MONO_ARCH_SAVE_REGS;
3774
3775         MONO_CHECK_ARG_NULL (rtype);
3776
3777         klass = mono_class_from_mono_type (rtype->type);
3778
3779         return mono_class_native_size (klass, NULL);
3780 }
3781
3782 void
3783 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old)
3784 {
3785         MonoMethod *method;
3786         gpointer pa [3];
3787
3788         MONO_ARCH_SAVE_REGS;
3789
3790         MONO_CHECK_ARG_NULL (obj);
3791         MONO_CHECK_ARG_NULL (dst);
3792
3793         method = mono_marshal_get_struct_to_ptr (obj->vtable->klass);
3794
3795         pa [0] = obj;
3796         pa [1] = &dst;
3797         pa [2] = &delete_old;
3798
3799         mono_runtime_invoke (method, NULL, pa, NULL);
3800 }
3801
3802 void
3803 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, MonoObject *dst)
3804 {
3805         MonoMethod *method;
3806         gpointer pa [2];
3807
3808         MONO_ARCH_SAVE_REGS;
3809
3810         MONO_CHECK_ARG_NULL (src);
3811         MONO_CHECK_ARG_NULL (dst);
3812
3813         method = mono_marshal_get_ptr_to_struct (dst->vtable->klass);
3814
3815         pa [0] = &src;
3816         pa [1] = dst;
3817
3818         mono_runtime_invoke (method, NULL, pa, NULL);
3819 }
3820
3821 MonoObject *
3822 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer src, MonoReflectionType *type)
3823 {
3824         MonoDomain *domain = mono_domain_get (); 
3825         MonoObject *res;
3826
3827         MONO_ARCH_SAVE_REGS;
3828
3829         MONO_CHECK_ARG_NULL (src);
3830         MONO_CHECK_ARG_NULL (type);
3831
3832         res = mono_object_new (domain, mono_class_from_mono_type (type->type));
3833
3834         ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (src, res);
3835
3836         return res;
3837 }
3838
3839 int
3840 ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *type, MonoString *field_name)
3841 {
3842         MonoMarshalType *info;
3843         MonoClass *klass;
3844         char *fname;
3845         int i, match_index = -1;
3846         
3847         MONO_ARCH_SAVE_REGS;
3848
3849         MONO_CHECK_ARG_NULL (type);
3850         MONO_CHECK_ARG_NULL (field_name);
3851
3852         fname = mono_string_to_utf8 (field_name);
3853         klass = mono_class_from_mono_type (type->type);
3854
3855         while(klass && match_index == -1) {
3856                 for (i = 0; i < klass->field.count; ++i) {
3857                         if (*fname == *klass->fields [i].name && strcmp (fname, klass->fields [i].name) == 0) {
3858                                 match_index = i;
3859                                 break;
3860                         }
3861                 }
3862
3863                 if(match_index == -1)
3864                         klass = klass->parent;
3865         }
3866
3867         g_free (fname);
3868
3869         if(match_index == -1) {
3870                MonoException* exc;
3871                gchar *tmp;
3872
3873                /* Get back original class instance */
3874                klass = mono_class_from_mono_type (type->type);
3875
3876                tmp = g_strdup_printf ("Field passed in is not a marshaled member of the type %s", klass->name);
3877                exc = mono_get_exception_argument ("fieldName", tmp);
3878                g_free (tmp);
3879  
3880                mono_raise_exception ((MonoException*)exc);
3881        }
3882
3883        info = mono_marshal_load_type_info (klass);     
3884        return info->fields [match_index].offset;
3885 }
3886
3887 gpointer
3888 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString *string)
3889 {
3890         MONO_ARCH_SAVE_REGS;
3891
3892         return mono_string_to_utf8 (string);
3893 }
3894
3895 gpointer
3896 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni (MonoString *string)
3897 {
3898         MONO_ARCH_SAVE_REGS;
3899
3900         return g_memdup (mono_string_chars (string), mono_string_length (string)*2);
3901 }
3902
3903 static void
3904 mono_struct_delete_old (MonoClass *klass, char *ptr)
3905 {
3906         MonoMarshalType *info;
3907         int i;
3908
3909         info = mono_marshal_load_type_info (klass);
3910
3911         for (i = 0; i < info->num_fields; i++) {
3912                 MonoMarshalNative ntype;
3913                 MonoMarshalConv conv;
3914                 MonoType *ftype = info->fields [i].field->type;
3915                 char *cpos;
3916
3917                 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
3918                         continue;
3919
3920                 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, 
3921                                                 klass->unicode, &conv);
3922                         
3923                 cpos = ptr + info->fields [i].offset;
3924
3925                 switch (conv) {
3926                 case MONO_MARSHAL_CONV_NONE:
3927                         if (MONO_TYPE_ISSTRUCT (ftype)) {
3928                                 mono_struct_delete_old (ftype->data.klass, cpos);
3929                                 continue;
3930                         }
3931                         break;
3932                 case MONO_MARSHAL_CONV_STR_LPWSTR:
3933                 case MONO_MARSHAL_CONV_STR_LPSTR:
3934                 case MONO_MARSHAL_CONV_STR_LPTSTR:
3935                 case MONO_MARSHAL_CONV_STR_BSTR:
3936                 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
3937                 case MONO_MARSHAL_CONV_STR_TBSTR:
3938                         g_free (*(gpointer *)cpos);
3939                         break;
3940                 default:
3941                         continue;
3942                 }
3943         }
3944 }
3945
3946 void
3947 ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure (gpointer src, MonoReflectionType *type)
3948 {
3949         MonoClass *klass;
3950
3951         MONO_ARCH_SAVE_REGS;
3952
3953         MONO_CHECK_ARG_NULL (src);
3954         MONO_CHECK_ARG_NULL (type);
3955
3956         klass = mono_class_from_mono_type (type->type);
3957
3958         mono_struct_delete_old (klass, (char *)src);
3959 }
3960
3961 MonoMarshalType *
3962 mono_marshal_load_type_info (MonoClass* klass)
3963 {
3964         int i, j, count = 0, native_size = 0;
3965         MonoMarshalType *info;
3966         guint32 layout;
3967
3968         g_assert (klass != NULL);
3969
3970         if (klass->marshal_info)
3971                 return klass->marshal_info;
3972
3973         if (!klass->inited)
3974                 mono_class_init (klass);
3975         
3976         for (i = 0; i < klass->field.count; ++i) {
3977                 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
3978                         continue;
3979                 count++;
3980         }
3981
3982         layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
3983
3984         klass->marshal_info = info = g_malloc0 (sizeof (MonoMarshalType) + sizeof (MonoMarshalField) * count);
3985         info->num_fields = count;
3986         
3987         /* Try to find a size for this type in metadata */
3988         mono_metadata_packing_from_typedef (klass->image, klass->type_token, NULL, &native_size);
3989
3990         if (klass->parent) {
3991                 int parent_size = mono_class_native_size (klass->parent, NULL);
3992
3993                 /* Add parent size to real size */
3994                 native_size += parent_size;
3995                 info->native_size = parent_size;
3996         }
3997  
3998         for (j = i = 0; i < klass->field.count; ++i) {
3999                 int size, align;
4000                 
4001                 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
4002                         continue;
4003
4004                 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL)
4005                         mono_metadata_field_info (klass->image, klass->field.first + i, 
4006                                                   NULL, NULL, &info->fields [j].mspec);
4007
4008                 info->fields [j].field = &klass->fields [i];
4009
4010                 switch (layout) {
4011                 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
4012                 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
4013                         size = mono_marshal_type_size (klass->fields [i].type, info->fields [j].mspec, 
4014                                                        &align, TRUE, klass->unicode);
4015                         align = klass->packing_size ? MIN (klass->packing_size, align): align;  
4016                         info->fields [j].offset = info->native_size;
4017                         info->fields [j].offset += align - 1;
4018                         info->fields [j].offset &= ~(align - 1);
4019                         info->native_size = info->fields [j].offset + size;
4020                         break;
4021                 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
4022                         /* FIXME: */
4023                         info->fields [j].offset = klass->fields [i].offset - sizeof (MonoObject);
4024                         info->native_size = klass->instance_size - sizeof (MonoObject);
4025                         break;
4026                 }       
4027                 j++;
4028         }
4029
4030         if(layout != TYPE_ATTRIBUTE_AUTO_LAYOUT) {
4031                 info->native_size = MAX (native_size, info->native_size);
4032         }
4033
4034         if (info->native_size & (klass->min_align - 1)) {
4035                 info->native_size += klass->min_align - 1;
4036                 info->native_size &= ~(klass->min_align - 1);
4037         }
4038
4039         return klass->marshal_info;
4040 }
4041
4042 /**
4043  * mono_class_native_size:
4044  * @klass: a class 
4045  * 
4046  * Returns: the native size of an object instance (when marshaled 
4047  * to unmanaged code) 
4048  */
4049 gint32
4050 mono_class_native_size (MonoClass *klass, guint32 *align)
4051 {
4052         
4053         if (!klass->marshal_info)
4054                 mono_marshal_load_type_info (klass);
4055
4056         if (align)
4057                 *align = klass->min_align;
4058
4059         return klass->marshal_info->native_size;
4060 }
4061
4062 /*
4063  * mono_type_native_stack_size:
4064  * @t: the type to return the size it uses on the stack
4065  *
4066  * Returns: the number of bytes required to hold an instance of this
4067  * type on the native stack
4068  */
4069 int
4070 mono_type_native_stack_size (MonoType *t, gint *align)
4071 {
4072         int tmp;
4073
4074         g_assert (t != NULL);
4075
4076         if (!align)
4077                 align = &tmp;
4078
4079         if (t->byref) {
4080                 *align = 4;
4081                 return 4;
4082         }
4083
4084         switch (t->type){
4085         case MONO_TYPE_BOOLEAN:
4086         case MONO_TYPE_CHAR:
4087         case MONO_TYPE_I1:
4088         case MONO_TYPE_U1:
4089         case MONO_TYPE_I2:
4090         case MONO_TYPE_U2:
4091         case MONO_TYPE_I4:
4092         case MONO_TYPE_U4:
4093         case MONO_TYPE_I:
4094         case MONO_TYPE_U:
4095         case MONO_TYPE_STRING:
4096         case MONO_TYPE_OBJECT:
4097         case MONO_TYPE_CLASS:
4098         case MONO_TYPE_SZARRAY:
4099         case MONO_TYPE_PTR:
4100         case MONO_TYPE_FNPTR:
4101         case MONO_TYPE_ARRAY:
4102         case MONO_TYPE_TYPEDBYREF:
4103                 *align = 4;
4104                 return 4;
4105         case MONO_TYPE_R4:
4106                 *align = 4;
4107                 return 4;
4108         case MONO_TYPE_I8:
4109         case MONO_TYPE_U8:
4110         case MONO_TYPE_R8:
4111                 *align = 4;
4112                 return 8;
4113         case MONO_TYPE_VALUETYPE: {
4114                 guint32 size;
4115
4116                 if (t->data.klass->enumtype)
4117                         return mono_type_native_stack_size (t->data.klass->enum_basetype, align);
4118                 else {
4119                         size = mono_class_native_size (t->data.klass, align);
4120                         *align = *align + 3;
4121                         *align &= ~3;
4122                         
4123                         size +=  3;
4124                         size &= ~3;
4125
4126                         return size;
4127                 }
4128         }
4129         default:
4130                 g_error ("type 0x%02x unknown", t->type);
4131         }
4132         return 0;
4133 }
4134
4135 gint32
4136 mono_marshal_type_size (MonoType *type, MonoMarshalSpec *mspec, gint32 *align, 
4137                         gboolean as_field, gboolean unicode)
4138 {
4139         MonoMarshalNative native_type = mono_type_to_unmanaged (type, mspec, as_field, unicode, NULL);
4140         MonoClass *klass;
4141
4142         switch (native_type) {
4143         case MONO_NATIVE_BOOLEAN:
4144                 *align = 4;
4145                 return 4;
4146         case MONO_NATIVE_I1:
4147         case MONO_NATIVE_U1:
4148                 *align = 1;
4149                 return 1;
4150         case MONO_NATIVE_I2:
4151         case MONO_NATIVE_U2:
4152                 *align = 2;
4153                 return 2;
4154         case MONO_NATIVE_I4:
4155         case MONO_NATIVE_U4:
4156         case MONO_NATIVE_ERROR:
4157                 *align = 4;
4158                 return 4;
4159         case MONO_NATIVE_I8:
4160         case MONO_NATIVE_U8:
4161                 *align = 4;
4162                 return 8;
4163         case MONO_NATIVE_R4:
4164                 *align = 4;
4165                 return 4;
4166         case MONO_NATIVE_R8:
4167                 *align = 4;
4168                 return 8;
4169         case MONO_NATIVE_INT:
4170         case MONO_NATIVE_UINT:
4171         case MONO_NATIVE_LPSTR:
4172         case MONO_NATIVE_LPWSTR:
4173         case MONO_NATIVE_LPTSTR:
4174         case MONO_NATIVE_BSTR:
4175         case MONO_NATIVE_ANSIBSTR:
4176         case MONO_NATIVE_TBSTR:
4177         case MONO_NATIVE_LPARRAY:
4178         case MONO_NATIVE_SAFEARRAY:
4179         case MONO_NATIVE_IUNKNOWN:
4180         case MONO_NATIVE_IDISPATCH:
4181         case MONO_NATIVE_INTERFACE:
4182         case MONO_NATIVE_ASANY:
4183         case MONO_NATIVE_VARIANTBOOL:
4184         case MONO_NATIVE_FUNC:
4185         case MONO_NATIVE_LPSTRUCT:
4186                 *align =  4;
4187                 return sizeof (gpointer);
4188         case MONO_NATIVE_STRUCT: 
4189                 klass = mono_class_from_mono_type (type);
4190                 return mono_class_native_size (klass, align);
4191         case MONO_NATIVE_BYVALTSTR: {
4192                 int esize = unicode ? 2: 1;
4193                 g_assert (mspec);
4194                 *align = esize;
4195                 return mspec->data.array_data.num_elem * esize;
4196         }
4197         case MONO_NATIVE_BYVALARRAY: {
4198                 int esize;
4199                 klass = mono_class_from_mono_type (type);
4200                 esize = mono_class_native_size (klass->element_class, align);
4201                 g_assert (mspec);
4202                 return mspec->data.array_data.num_elem * esize;
4203         }
4204         case MONO_NATIVE_CUSTOM:
4205                 g_assert_not_reached ();
4206                 break;
4207         case MONO_NATIVE_CURRENCY:
4208         case MONO_NATIVE_VBBYREFSTR:
4209         default:
4210                 g_error ("native type %02x not implemented", native_type); 
4211                 break;
4212         }
4213         g_assert_not_reached ();
4214         return 0;
4215 }
4216