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