2003-01-28 Dietmar Maurer <dietmar@ximian.com>
[mono.git] / mono / metadata / marshal.c
1 /*
2  * marshal.c: Routines for marshaling complex types in P/Invoke methods.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
7  * (C) 2002 Ximian, Inc.  http://www.ximian.com
8  *
9  */
10
11 #include "config.h"
12 #include "object.h"
13 #include "loader.h"
14 #include "metadata/marshal.h"
15 #include "metadata/tabledefs.h"
16 #include "metadata/exception.h"
17 #include "metadata/appdomain.h"
18 #include "mono/metadata/debug-helpers.h"
19 #include "mono/metadata/threadpool.h"
20 #include <string.h>
21
22 //#define DEBUG_RUNTIME_CODE
23
24 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
25         a = i,
26
27 enum {
28 #include "mono/cil/opcode.def"
29         LAST = 0xff
30 };
31 #undef OPDEF
32
33 struct _MonoMethodBuilder {
34         MonoMethod *method;
35         GList *locals_list;
36         int locals;
37         guint32 code_size, pos;
38         unsigned char *code;
39 };
40
41 static void
42 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object);
43
44 #ifdef DEBUG_RUNTIME_CODE
45 static char*
46 indenter (MonoDisHelper *dh, MonoMethod *method, guint32 ip_offset)
47 {
48         return g_strdup (" ");
49 }
50
51 static MonoDisHelper marshal_dh = {
52         "\n",
53         "IL_%04x: ",
54         "IL_%04x",
55         indenter, 
56         NULL,
57         NULL
58 };
59 #endif 
60
61 gpointer
62 mono_delegate_to_ftnptr (MonoDelegate *delegate)
63 {
64         MonoMethod *method, *wrapper;
65         MonoClass *klass;
66
67         if (!delegate)
68                 return NULL;
69
70         if (delegate->delegate_trampoline)
71                 return delegate->delegate_trampoline;
72
73         klass = ((MonoObject *)delegate)->vtable->klass;
74         g_assert (klass->delegate);
75         
76         method = delegate->method_info->method;
77         wrapper = mono_marshal_get_managed_wrapper (method, delegate->target);
78
79         delegate->delegate_trampoline =  mono_compile_method (wrapper);
80
81         return delegate->delegate_trampoline;
82 }
83
84 gpointer
85 mono_array_to_savearray (MonoArray *array)
86 {
87         if (!array)
88                 return NULL;
89
90         g_assert_not_reached ();
91         return NULL;
92 }
93
94 gpointer
95 mono_array_to_lparray (MonoArray *array)
96 {
97         if (!array)
98                 return NULL;
99
100         /* fixme: maybe we need to make a copy */
101         return array->vector;
102 }
103
104 void
105 mono_string_utf8_to_builder (MonoStringBuilder *sb, char *text)
106 {
107         GError *error = NULL;
108         guint16 *ut;
109         glong items_written;
110         int l;
111
112         if (!sb || !text)
113                 return;
114
115         l = strlen (text);
116
117         ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
118
119         if (items_written > sb->capacity)
120                 items_written = sb->capacity;
121         
122         if (!error) {
123                 memcpy (sb->chars->vector, ut, items_written * 2);
124                 sb->length = items_written;
125         } else 
126                 g_error_free (error);
127
128         g_free (ut);
129 }
130
131 gpointer
132 mono_string_builder_to_utf8 (MonoStringBuilder *sb)
133 {
134         char *res;
135
136         if (!sb)
137                 return NULL;
138
139         res = g_malloc (sb->capacity + 1);
140
141         /* fixme: copy the content of the string builder? */
142         res [0] = 0;
143
144         return res;
145 }
146
147 gpointer
148 mono_string_to_ansibstr (MonoString *string_obj)
149 {
150         g_error ("implement me");
151         return NULL;
152 }
153
154 gpointer
155 mono_string_to_bstr (MonoString *string_obj)
156 {
157         g_error ("implement me");
158         return NULL;
159 }
160
161 void
162 mono_string_to_byvalstr (gpointer dst, MonoString *src, int size)
163 {
164         char *s;
165         int len;
166
167         g_assert (dst != NULL);
168         g_assert (size > 0);
169
170         if (!src) {
171                 memset (dst, 0, size);
172                 return;
173         }
174
175         s = mono_string_to_utf8 (src);
176         len = MIN (size, strlen (s));
177         memcpy (dst, s, len);
178         g_free (s);
179
180         *((char *)dst + size - 1) = 0;
181 }
182
183 void
184 mono_string_to_byvalwstr (gpointer dst, MonoString *src, int size)
185 {
186         int len;
187
188         g_assert (dst != NULL);
189         g_assert (size > 1);
190
191         if (!src) {
192                 memset (dst, 0, size);
193                 return;
194         }
195
196         len = MIN (size, (mono_string_length (src) * 2));
197         memcpy (dst, mono_string_chars (src), len);
198
199         *((char *)dst + size - 1) = 0;
200         *((char *)dst + size - 2) = 0;
201 }
202
203
204 static MonoMethod *
205 mono_find_method_by_name (MonoClass *klass, const char *name, int param_count)
206 {
207         MonoMethod *res = NULL;
208         int i;
209
210         for (i = 0; i < klass->method.count; ++i) {
211                 if ((klass->methods [i]->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
212                     klass->methods [i]->name[0] == name [0] && 
213                     !strcmp (name, klass->methods [i]->name) &&
214                     klass->methods [i]->signature->param_count == param_count) {
215                         res = klass->methods [i];
216                         break;
217                 }
218         }
219         return res;
220 }
221
222 void
223 mono_mb_free (MonoMethodBuilder *mb)
224 {
225         g_list_free (mb->locals_list);
226         g_free (mb);
227 }
228
229 MonoMethodBuilder *
230 mono_mb_new (MonoClass *klass, const char *name, MonoWrapperType type)
231 {
232         MonoMethodBuilder *mb;
233         MonoMethod *m;
234
235         g_assert (klass != NULL);
236         g_assert (name != NULL);
237
238         mb = g_new0 (MonoMethodBuilder, 1);
239
240         mb->method = m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
241
242         m->klass = klass;
243         m->name = g_strdup (name);
244         m->inline_info = 1;
245         m->inline_count = -1;
246         m->wrapper_type = type;
247
248         mb->code_size = 256;
249         mb->code = g_malloc (mb->code_size);
250         
251         return mb;
252 }
253
254 int
255 mono_mb_add_local (MonoMethodBuilder *mb, MonoType *type)
256 {
257         int res = mb->locals;
258
259         g_assert (mb != NULL);
260         g_assert (type != NULL);
261
262         mb->locals_list = g_list_append (mb->locals_list, type);
263         mb->locals++;
264
265         return res;
266 }
267
268 MonoMethod *
269 mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack)
270 {
271         MonoMethodHeader *header;
272         GList *l;
273         int i;
274
275         g_assert (mb != NULL);
276
277         ((MonoMethodNormal *)mb->method)->header = header = (MonoMethodHeader *) 
278                 g_malloc0 (sizeof (MonoMethodHeader) + mb->locals * sizeof (MonoType *));
279
280         if (max_stack < 8)
281                 max_stack = 8;
282
283         header->max_stack = max_stack;
284
285         for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
286                 header->locals [i] = (MonoType *)l->data;
287         }
288
289         mb->method->signature = signature;
290         header->code = mb->code;
291         header->code_size = mb->pos;
292         header->num_locals = mb->locals;
293
294 #ifdef DEBUG_RUNTIME_CODE
295         printf ("RUNTIME CODE FOR %s\n", mono_method_full_name (mb->method, TRUE));
296         printf ("%s\n", mono_disasm_code (&marshal_dh, mb->method, mb->code, mb->code + mb->pos));
297 #endif
298
299         return mb->method;
300 }
301
302 guint32
303 mono_mb_add_data (MonoMethodBuilder *mb, gpointer data)
304 {
305         MonoMethodWrapper *mw;
306
307         g_assert (mb != NULL);
308
309         mw = (MonoMethodWrapper *)mb->method;
310
311         mw->data = g_list_append (mw->data, data);
312
313         return g_list_length (mw->data);
314 }
315
316 void
317 mono_mb_patch_addr (MonoMethodBuilder *mb, int pos, int value)
318 {
319         mb->code [pos] = value & 0xff;
320         mb->code [pos + 1] = (value >> 8) & 0xff;
321         mb->code [pos + 2] = (value >> 16) & 0xff;
322         mb->code [pos + 3] = (value >> 24) & 0xff;
323 }
324
325 void
326 mono_mb_patch_addr_s (MonoMethodBuilder *mb, int pos, gint8 value)
327 {
328         *((gint8 *)(&mb->code [pos])) = value;
329 }
330
331 void
332 mono_mb_emit_byte (MonoMethodBuilder *mb, guint8 op)
333 {
334         if (mb->pos >= mb->code_size) {
335                 mb->code_size += 64;
336                 mb->code = g_realloc (mb->code, mb->code_size);
337         }
338
339         mb->code [mb->pos++] = op;
340 }
341
342 void
343 mono_mb_emit_ldflda (MonoMethodBuilder *mb, gint32 offset)
344 {
345         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
346         mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
347         mono_mb_emit_icon (mb, offset);
348         mono_mb_emit_byte (mb, CEE_ADD);
349 }
350
351 void
352 mono_mb_emit_i4 (MonoMethodBuilder *mb, gint32 data)
353 {
354         if ((mb->pos + 4) >= mb->code_size) {
355                 mb->code_size += 64;
356                 mb->code = g_realloc (mb->code, mb->code_size);
357         }
358
359         mono_mb_patch_addr (mb, mb->pos, data);
360         mb->pos += 4;
361 }
362
363 void
364 mono_mb_emit_i2 (MonoMethodBuilder *mb, gint16 data)
365 {
366         if ((mb->pos + 2) >= mb->code_size) {
367                 mb->code_size += 64;
368                 mb->code = g_realloc (mb->code, mb->code_size);
369         }
370
371         mb->code [mb->pos] = data & 0xff;
372         mb->code [mb->pos + 1] = (data >> 8) & 0xff;
373         mb->pos += 2;
374 }
375
376 void
377 mono_mb_emit_ldarg (MonoMethodBuilder *mb, guint argnum)
378 {
379         if (argnum < 4) {
380                 mono_mb_emit_byte (mb, CEE_LDARG_0 + argnum);
381         } else if (argnum < 256) {
382                 mono_mb_emit_byte (mb, CEE_LDARG_S);
383                 mono_mb_emit_byte (mb, argnum);
384         } else {
385                 mono_mb_emit_byte (mb, CEE_PREFIX1);
386                 mono_mb_emit_byte (mb, CEE_LDARG);
387                 mono_mb_emit_i2 (mb, argnum);
388         }
389 }
390
391 void
392 mono_mb_emit_ldarg_addr (MonoMethodBuilder *mb, guint argnum)
393 {
394         if (argnum < 256) {
395                 mono_mb_emit_byte (mb, CEE_LDARGA_S);
396                 mono_mb_emit_byte (mb, argnum);
397         } else {
398                 mono_mb_emit_byte (mb, CEE_PREFIX1);
399                 mono_mb_emit_byte (mb, CEE_LDARGA);
400                 mono_mb_emit_i2 (mb, argnum);
401         }
402 }
403
404 void
405 mono_mb_emit_ldloc_addr (MonoMethodBuilder *mb, guint locnum)
406 {
407         if (locnum < 256) {
408                 mono_mb_emit_byte (mb, CEE_LDLOCA_S);
409                 mono_mb_emit_byte (mb, locnum);
410         } else {
411                 mono_mb_emit_byte (mb, CEE_PREFIX1);
412                 mono_mb_emit_byte (mb, CEE_LDLOCA);
413                 mono_mb_emit_i2 (mb, locnum);
414         }
415 }
416
417 void
418 mono_mb_emit_ldloc (MonoMethodBuilder *mb, guint num)
419 {
420         if (num < 4) {
421                 mono_mb_emit_byte (mb, CEE_LDLOC_0 + num);
422         } else if (num < 256) {
423                 mono_mb_emit_byte (mb, CEE_LDLOC_S);
424                 mono_mb_emit_byte (mb, num);
425         } else {
426                 mono_mb_emit_byte (mb, CEE_PREFIX1);
427                 mono_mb_emit_byte (mb, CEE_LDLOC);
428                 mono_mb_emit_i2 (mb, num);
429         }
430 }
431
432 void
433 mono_mb_emit_stloc (MonoMethodBuilder *mb, guint num)
434 {
435         if (num < 4) {
436                 mono_mb_emit_byte (mb, CEE_STLOC_0 + num);
437         } else if (num < 256) {
438                 mono_mb_emit_byte (mb, CEE_STLOC_S);
439                 mono_mb_emit_byte (mb, num);
440         } else {
441                 mono_mb_emit_byte (mb, CEE_PREFIX1);
442                 mono_mb_emit_byte (mb, CEE_STLOC);
443                 mono_mb_emit_i2 (mb, num);
444         }
445 }
446
447 void
448 mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value)
449 {
450         if (value >= -1 && value < 8) {
451                 mono_mb_emit_byte (mb, CEE_LDC_I4_0 + value);
452         } else if (value >= -128 && value <= 127) {
453                 mono_mb_emit_byte (mb, CEE_LDC_I4_S);
454                 mono_mb_emit_byte (mb, value);
455         } else {
456                 mono_mb_emit_byte (mb, CEE_LDC_I4);
457                 mono_mb_emit_i4 (mb, value);
458         }
459 }
460
461 void
462 mono_mb_emit_managed_call (MonoMethodBuilder *mb, MonoMethod *method, MonoMethodSignature *opt_sig)
463 {
464         if (!opt_sig)
465                 opt_sig = method->signature;
466         mono_mb_emit_byte (mb, CEE_PREFIX1);
467         mono_mb_emit_byte (mb, CEE_LDFTN);
468         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
469         mono_mb_emit_byte (mb, CEE_CALLI);
470         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, opt_sig));
471 }
472
473 void
474 mono_mb_emit_native_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, gpointer func)
475 {
476         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
477         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
478         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, func));
479         mono_mb_emit_byte (mb, CEE_CALLI);
480         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
481 }
482
483 void
484 mono_mb_emit_exception (MonoMethodBuilder *mb)
485 {
486         /* fixme: we need a better way to throw exception,
487          * supporting several exception types and messages */
488         static MonoMethod *missing_method_ctor = NULL;
489
490         if (!missing_method_ctor) {
491                 MonoClass *mme = mono_class_from_name (mono_defaults.corlib, "System", "MissingMethodException");
492                 int i;
493                 mono_class_init (mme);
494                 for (i = 0; i < mme->method.count; ++i) {
495                         if (strcmp (mme->methods [i]->name, ".ctor") == 0 && mme->methods [i]->signature->param_count == 0) {
496                                 missing_method_ctor = mme->methods [i];
497                                 break;
498                         }
499                 }
500         }
501         mono_mb_emit_byte (mb, CEE_NEWOBJ);
502         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, missing_method_ctor));
503         mono_mb_emit_byte (mb, CEE_THROW);
504         
505 }
506
507 void
508 mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint8 local, gint8 incr)
509 {
510         mono_mb_emit_ldloc (mb, local); 
511         mono_mb_emit_icon (mb, incr);
512         mono_mb_emit_byte (mb, CEE_ADD);
513         mono_mb_emit_stloc (mb, local); 
514 }
515
516 static void
517 emit_ptr_to_str_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, 
518                       int usize, int msize)
519 {
520         switch (conv) {
521         case MONO_MARSHAL_CONV_BOOL_I4:
522                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
523                 mono_mb_emit_byte (mb, CEE_LDIND_I);
524                 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
525                 mono_mb_emit_byte (mb, 5);
526                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
527                 mono_mb_emit_byte (mb, CEE_LDC_I4_1);
528                 mono_mb_emit_byte (mb, CEE_STIND_I1);
529                 mono_mb_emit_byte (mb, CEE_BR_S);
530                 mono_mb_emit_byte (mb, 3);
531                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
532                 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
533                 mono_mb_emit_byte (mb, CEE_STIND_I1);
534                 break;
535         case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
536                 MonoClass *eclass;
537                 int esize;
538
539                 if (type->type == MONO_TYPE_ARRAY)
540                         eclass = mono_class_from_mono_type (type->data.array->type);
541                 else if (type->type == MONO_TYPE_SZARRAY) {
542                         eclass = mono_class_from_mono_type (type->data.type);
543                 } else {
544                         g_assert_not_reached ();
545                 }
546
547                 if (eclass->valuetype)
548                         esize = mono_class_instance_size (eclass) - sizeof (MonoObject);
549                 else
550                         esize = sizeof (gpointer);
551
552                 /* create a new array */
553                 /* fixme: this only works for SZARRAYS */
554                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
555                 mono_mb_emit_icon (mb, msize / esize);
556                 mono_mb_emit_byte (mb, CEE_NEWARR);     
557                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eclass));
558                 mono_mb_emit_byte (mb, CEE_STIND_I);
559
560                 /* copy the elements */
561                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
562                 mono_mb_emit_byte (mb, CEE_LDIND_I);
563                 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
564                 mono_mb_emit_byte (mb, CEE_ADD);
565                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
566                 mono_mb_emit_icon (mb, usize);
567                 mono_mb_emit_byte (mb, CEE_PREFIX1);
568                 mono_mb_emit_byte (mb, CEE_CPBLK);                      
569
570                 break;
571         }
572         case MONO_MARSHAL_CONV_STR_BYVALSTR: 
573                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
574                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
575                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
576                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
577                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
578                 mono_mb_emit_byte (mb, CEE_STIND_I);            
579                 break;
580         case MONO_MARSHAL_CONV_STR_LPTSTR:
581         case MONO_MARSHAL_CONV_STR_LPSTR:
582                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
583                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
584                 mono_mb_emit_byte (mb, CEE_LDIND_I);
585                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
586                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
587                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
588                 mono_mb_emit_byte (mb, CEE_STIND_I);            
589                 break;
590         case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
591                 MonoClass *klass = mono_class_from_mono_type (type);
592                 int src_var, dst_var;
593
594                 src_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
595                 dst_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
596                 
597                 /* *dst = new object */
598                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
599                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
600                 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);        
601                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
602                 mono_mb_emit_byte (mb, CEE_STIND_I);
603         
604                 /* save the old src pointer */
605                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
606                 mono_mb_emit_stloc (mb, src_var);
607                 /* save the old dst pointer */
608                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
609                 mono_mb_emit_stloc (mb, dst_var);
610
611                 /* dst = pointer to newly created object data */
612                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
613                 mono_mb_emit_byte (mb, CEE_LDIND_I);
614                 mono_mb_emit_icon (mb, sizeof (MonoObject));
615                 mono_mb_emit_byte (mb, CEE_ADD);
616                 mono_mb_emit_byte (mb, CEE_STLOC_1); 
617
618                 emit_struct_conv (mb, klass, TRUE);
619                 
620                 /* restore the old src pointer */
621                 mono_mb_emit_ldloc (mb, src_var);
622                 mono_mb_emit_byte (mb, CEE_STLOC_0);
623                 /* restore the old dst pointer */
624                 mono_mb_emit_ldloc (mb, dst_var);
625                 mono_mb_emit_byte (mb, CEE_STLOC_1);
626                 break;
627         }
628         case MONO_MARSHAL_CONV_DEL_FTN: {
629                 // fixme: we never convert functions back to delegates, dont 
630                 // know if thats the correct behaviour
631                 break;
632         }
633         case MONO_MARSHAL_CONV_STR_LPWSTR:
634         case MONO_MARSHAL_CONV_STR_BSTR:
635         case MONO_MARSHAL_CONV_STR_ANSIBSTR:
636         case MONO_MARSHAL_CONV_STR_TBSTR:
637         case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
638         case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
639         case MONO_MARSHAL_CONV_STR_BYVALWSTR: 
640         case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
641         default:
642                 g_warning ("marshaling conversion %d not implemented", conv);
643                 g_assert_not_reached ();
644         }
645 }
646
647 static void
648 emit_str_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, int usize, int msize)
649 {
650         int pos;
651
652         switch (conv) {
653         case MONO_MARSHAL_CONV_BOOL_I4:
654                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
655                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
656                 mono_mb_emit_byte (mb, CEE_LDIND_U1);
657                 mono_mb_emit_byte (mb, CEE_STIND_I4);
658                 break;
659         case MONO_MARSHAL_CONV_STR_LPWSTR:
660         case MONO_MARSHAL_CONV_STR_LPSTR:
661         case MONO_MARSHAL_CONV_STR_LPTSTR:
662         case MONO_MARSHAL_CONV_STR_BSTR:
663         case MONO_MARSHAL_CONV_STR_ANSIBSTR:
664         case MONO_MARSHAL_CONV_STR_TBSTR:
665                 /* free space if free == true */
666                 mono_mb_emit_byte (mb, CEE_LDLOC_2);
667                 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
668                 mono_mb_emit_byte (mb, 4);
669                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
670                 mono_mb_emit_byte (mb, CEE_LDIND_I);
671                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
672                 mono_mb_emit_byte (mb, CEE_MONO_FREE);
673
674                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
675                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
676                 mono_mb_emit_byte (mb, CEE_LDIND_I);
677                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
678                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
679                 mono_mb_emit_byte (mb, conv);
680                 mono_mb_emit_byte (mb, CEE_STIND_I);    
681                 break;
682         case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
683         case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
684         case MONO_MARSHAL_CONV_DEL_FTN:
685                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
686                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
687                 mono_mb_emit_byte (mb, CEE_LDIND_I);
688                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
689                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
690                 mono_mb_emit_byte (mb, conv);
691                 mono_mb_emit_byte (mb, CEE_STIND_I);    
692                 break;
693         case MONO_MARSHAL_CONV_STR_BYVALSTR: 
694         case MONO_MARSHAL_CONV_STR_BYVALWSTR: {
695                 if (!usize)
696                         break;
697
698                 mono_mb_emit_byte (mb, CEE_LDLOC_1); /* dst */
699                 mono_mb_emit_byte (mb, CEE_LDLOC_0);    
700                 mono_mb_emit_byte (mb, CEE_LDIND_I); /* src String */
701                 mono_mb_emit_icon (mb, usize);
702                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
703                 mono_mb_emit_byte (mb, CEE_MONO_PROC3);
704                 mono_mb_emit_byte (mb, conv);
705                 break;
706         }
707         case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
708                 if (!usize) 
709                         break;
710
711                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
712                 mono_mb_emit_byte (mb, CEE_LDIND_I);            
713                 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
714                 pos = mb->pos;
715                 mono_mb_emit_byte (mb, 0);
716
717                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
718                 mono_mb_emit_byte (mb, CEE_LDLOC_0);    
719                 mono_mb_emit_byte (mb, CEE_LDIND_I);    
720                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
721                 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
722                 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
723                 mono_mb_emit_byte (mb, CEE_ADD);
724                 mono_mb_emit_icon (mb, usize);
725                 mono_mb_emit_byte (mb, CEE_PREFIX1);
726                 mono_mb_emit_byte (mb, CEE_CPBLK);                      
727                 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
728                 break;
729         }
730         case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
731                 int src_var, dst_var;
732
733                 src_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
734                 dst_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
735                 
736                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
737                 mono_mb_emit_byte (mb, CEE_LDIND_I);            
738                 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
739                 pos = mb->pos;
740                 mono_mb_emit_byte (mb, 0);
741                 
742                 /* save the old src pointer */
743                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
744                 mono_mb_emit_stloc (mb, src_var);
745                 /* save the old dst pointer */
746                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
747                 mono_mb_emit_stloc (mb, dst_var);
748
749                 /* src = pointer to object data */
750                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
751                 mono_mb_emit_byte (mb, CEE_LDIND_I);            
752                 mono_mb_emit_icon (mb, sizeof (MonoObject));
753                 mono_mb_emit_byte (mb, CEE_ADD);
754                 mono_mb_emit_byte (mb, CEE_STLOC_0); 
755
756                 emit_struct_conv (mb, mono_class_from_mono_type (type), FALSE);
757                 
758                 /* restore the old src pointer */
759                 mono_mb_emit_ldloc (mb, src_var);
760                 mono_mb_emit_byte (mb, CEE_STLOC_0);
761                 /* restore the old dst pointer */
762                 mono_mb_emit_ldloc (mb, dst_var);
763                 mono_mb_emit_byte (mb, CEE_STLOC_1);
764
765                 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
766                 break;
767         }
768         case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
769         default:
770                 g_warning ("marshalling conversion %d not implemented", conv);
771                 g_assert_not_reached ();
772         }
773 }
774
775 static void
776 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
777 {
778         MonoMarshalType *info;
779         int i;
780
781         info = mono_marshal_load_type_info (klass);
782
783         if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
784                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
785                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
786                 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
787                 mono_mb_emit_byte (mb, CEE_PREFIX1);
788                 mono_mb_emit_byte (mb, CEE_CPBLK);
789                 return;
790         }
791
792         for (i = 0; i < info->num_fields; i++) {
793                 MonoMarshalNative ntype;
794                 MonoMarshalConv conv;
795                 MonoType *ftype = info->fields [i].field->type;
796                 int msize = 0;
797                 int usize = 0;
798                 gboolean last_field = i < (info->num_fields -1) ? 0 : 1;
799
800                 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
801                         continue;
802
803                 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, klass->unicode, &conv);
804                         
805                 if (last_field) {
806                         msize = klass->instance_size - info->fields [i].field->offset;
807                         usize = info->native_size - info->fields [i].offset;
808                 } else {
809                         msize = klass->fields [i + 1].offset - info->fields [i].field->offset;
810                         usize = info->fields [i + 1].offset - info->fields [i].offset;
811                 }
812                 g_assert (msize > 0 && usize > 0);
813
814                 switch (conv) {
815                 case MONO_MARSHAL_CONV_NONE: {
816                         int t;
817
818                         if (ftype->byref || ftype->type == MONO_TYPE_I ||
819                             ftype->type == MONO_TYPE_U) {
820                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
821                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
822                                 mono_mb_emit_byte (mb, CEE_LDIND_I);
823                                 mono_mb_emit_byte (mb, CEE_STIND_I);
824                                 break;
825                         }
826
827                         t = ftype->type;
828                 handle_enum:
829                         switch (t) {
830                         case MONO_TYPE_I4:
831                         case MONO_TYPE_U4:
832 #if SIZEOF_VOID_P == 4
833                         case MONO_TYPE_PTR:
834 #endif
835                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
836                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
837                                 mono_mb_emit_byte (mb, CEE_LDIND_I4);
838                                 mono_mb_emit_byte (mb, CEE_STIND_I4);
839                                 break;
840                         case MONO_TYPE_I1:
841                         case MONO_TYPE_U1:
842                         case MONO_TYPE_BOOLEAN:
843                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
844                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
845                                 mono_mb_emit_byte (mb, CEE_LDIND_I1);
846                                 mono_mb_emit_byte (mb, CEE_STIND_I1);
847                                 break;
848                         case MONO_TYPE_I2:
849                         case MONO_TYPE_U2:
850                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
851                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
852                                 mono_mb_emit_byte (mb, CEE_LDIND_I2);
853                                 mono_mb_emit_byte (mb, CEE_STIND_I2);
854                                 break;
855                         case MONO_TYPE_I8:
856                         case MONO_TYPE_U8:
857 #if SIZEOF_VOID_P == 8
858                         case MONO_TYPE_PTR:
859 #endif
860                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
861                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
862                                 mono_mb_emit_byte (mb, CEE_LDIND_I8);
863                                 mono_mb_emit_byte (mb, CEE_STIND_I8);
864                                 break;
865                         case MONO_TYPE_R4:
866                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
867                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
868                                 mono_mb_emit_byte (mb, CEE_LDIND_R4);
869                                 mono_mb_emit_byte (mb, CEE_STIND_R4);
870                                 break;
871                         case MONO_TYPE_R8:
872                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
873                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
874                                 mono_mb_emit_byte (mb, CEE_LDIND_R8);
875                                 mono_mb_emit_byte (mb, CEE_STIND_R8);
876                                 break;
877                         case MONO_TYPE_VALUETYPE:
878                                 if (ftype->data.klass->enumtype) {
879                                         t = ftype->data.klass->enum_basetype->type;
880                                         goto handle_enum;
881                                 }
882                                 emit_struct_conv (mb, ftype->data.klass, to_object);
883                                 continue;
884                         default:
885                                 g_warning ("marshaling type %02x not implemented", ftype->type);
886                                 g_assert_not_reached ();
887                         }
888                         break;
889                 }
890                 default:
891                         if (to_object) 
892                                 emit_ptr_to_str_conv (mb, ftype, conv, usize, msize);
893                         else
894                                 emit_str_to_ptr_conv (mb, ftype, conv, usize, msize);   
895                 }
896                 
897                 if (to_object) {
898                         mono_mb_emit_add_to_local (mb, 0, usize);
899                         mono_mb_emit_add_to_local (mb, 1, msize);
900                 } else {
901                         mono_mb_emit_add_to_local (mb, 0, msize);
902                         mono_mb_emit_add_to_local (mb, 1, usize);
903                 }                               
904         }
905 }
906
907 static MonoAsyncResult *
908 mono_delegate_begin_invoke (MonoDelegate *delegate, gpointer *params)
909 {
910         MonoMethodMessage *msg;
911         MonoDelegate *async_callback;
912         MonoObject *state;
913         MonoMethod *im;
914         MonoClass *klass;
915         MonoMethod *method = NULL;
916         int i;
917
918         g_assert (delegate);
919
920         klass = delegate->object.vtable->klass;
921
922         method = mono_get_delegate_invoke (klass);
923         for (i = 0; i < klass->method.count; ++i) {
924                 if (klass->methods [i]->name[0] == 'B' && 
925                     !strcmp ("BeginInvoke", klass->methods [i]->name)) {
926                         method = klass->methods [i];
927                         break;
928                 }
929         }
930
931         g_assert (method != NULL);
932
933         im = mono_get_delegate_invoke (method->klass);
934         
935         msg = mono_method_call_message_new (method, params, im, &async_callback, &state);
936
937         return mono_thread_pool_add ((MonoObject *)delegate, msg, async_callback, state);
938 }
939
940 static int
941 mono_mb_emit_save_args (MonoMethodBuilder *mb, MonoMethodSignature *sig, gboolean save_this)
942 {
943         int i, params_var, tmp_var;
944
945         /* allocate local (pointer) *params[] */
946         params_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
947         /* allocate local (pointer) tmp */
948         tmp_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
949
950         /* alloate space on stack to store an array of pointers to the arguments */
951         mono_mb_emit_icon (mb, sizeof (gpointer) * (sig->param_count + 1));
952         mono_mb_emit_byte (mb, CEE_PREFIX1);
953         mono_mb_emit_byte (mb, CEE_LOCALLOC);
954         mono_mb_emit_stloc (mb, params_var);
955
956         /* tmp = params */
957         mono_mb_emit_ldloc (mb, params_var);
958         mono_mb_emit_stloc (mb, tmp_var);
959
960         if (save_this && sig->hasthis) {
961                 mono_mb_emit_ldloc (mb, tmp_var);
962                 mono_mb_emit_ldarg_addr (mb, 0);
963                 mono_mb_emit_byte (mb, CEE_STIND_I);
964                 /* tmp = tmp + sizeof (gpointer) */
965                 if (sig->param_count)
966                         mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
967
968         }
969
970         for (i = 0; i < sig->param_count; i++) {
971                 mono_mb_emit_ldloc (mb, tmp_var);
972                 mono_mb_emit_ldarg_addr (mb, i + sig->hasthis);
973                 mono_mb_emit_byte (mb, CEE_STIND_I);
974                 /* tmp = tmp + sizeof (gpointer) */
975                 if (i < (sig->param_count - 1))
976                         mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
977         }
978
979         return params_var;
980 }
981
982 static char*
983 mono_signature_to_name (MonoMethodSignature *sig, const char *prefix)
984 {
985         int i;
986         char *result;
987         GString *res = g_string_new ("");
988
989         if (prefix) {
990                 g_string_append (res, prefix);
991                 g_string_append_c (res, '_');
992         }
993
994         mono_type_get_desc (res, sig->ret, FALSE);
995
996         for (i = 0; i < sig->param_count; ++i) {
997                 g_string_append_c (res, '_');
998                 mono_type_get_desc (res, sig->params [i], FALSE);
999         }
1000         result = res->str;
1001         g_string_free (res, FALSE);
1002         return result;
1003 }
1004
1005 MonoMethod *
1006 mono_marshal_get_delegate_begin_invoke (MonoMethod *method)
1007 {
1008         MonoMethodSignature *sig;
1009         static MonoMethodSignature *csig = NULL;
1010         MonoMethodBuilder *mb;
1011         MonoMethod *res;
1012         GHashTable *cache;
1013         int params_var;
1014         char *name;
1015
1016         g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1017                   !strcmp (method->name, "BeginInvoke"));
1018
1019         sig = method->signature;
1020
1021         cache = method->klass->image->delegate_begin_invoke_cache;
1022         if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1023                 return res;
1024
1025         g_assert (sig->hasthis);
1026
1027         if (!csig) {
1028                 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1029                 csig = g_malloc0 (sigsize);
1030
1031                 /* MonoAsyncResult * begin_invoke (MonoDelegate *delegate, gpointer params[]) */
1032                 csig->param_count = 2;
1033                 csig->ret = &mono_defaults.object_class->byval_arg;
1034                 csig->params [0] = &mono_defaults.object_class->byval_arg;
1035                 csig->params [1] = &mono_defaults.int_class->byval_arg;
1036         }
1037
1038         name = mono_signature_to_name (sig, "begin_invoke");
1039         mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_BEGIN_INVOKE);
1040         g_free (name);
1041
1042         mb->method->save_lmf = 1;
1043
1044         params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1045
1046         mono_mb_emit_ldarg (mb, 0);
1047         mono_mb_emit_ldloc (mb, params_var);
1048         mono_mb_emit_native_call (mb, csig, mono_delegate_begin_invoke);
1049         mono_mb_emit_byte (mb, CEE_RET);
1050
1051         res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1052         mono_mb_free (mb);
1053         g_hash_table_insert (cache, sig, res);
1054         return res;
1055 }
1056
1057 static MonoObject *
1058 mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params)
1059 {
1060         MonoDomain *domain = mono_domain_get ();
1061         MonoAsyncResult *ares;
1062         MonoMethod *method = NULL;
1063         MonoMethodSignature *sig;
1064         MonoMethodMessage *msg;
1065         MonoObject *res, *exc;
1066         MonoArray *out_args;
1067         MonoClass *klass;
1068         int i;
1069
1070         g_assert (delegate);
1071
1072         if (!delegate->method_info || !delegate->method_info->method)
1073                 g_assert_not_reached ();
1074
1075         klass = delegate->object.vtable->klass;
1076
1077         for (i = 0; i < klass->method.count; ++i) {
1078                 if (klass->methods [i]->name[0] == 'E' && 
1079                     !strcmp ("EndInvoke", klass->methods [i]->name)) {
1080                         method = klass->methods [i];
1081                         break;
1082                 }
1083         }
1084
1085         g_assert (method != NULL);
1086
1087         sig = method->signature;
1088
1089         msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1090
1091         ares = mono_array_get (msg->args, gpointer, sig->param_count - 1);
1092         g_assert (ares);
1093
1094         res = mono_thread_pool_finish (ares, &out_args, &exc);
1095
1096         if (exc) {
1097                 char *strace = mono_string_to_utf8 (((MonoException*)exc)->stack_trace);
1098                 char  *tmp;
1099                 tmp = g_strdup_printf ("%s\nException Rethrown at:\n", strace);
1100                 g_free (strace);        
1101                 ((MonoException*)exc)->stack_trace = mono_string_new (domain, tmp);
1102                 g_free (tmp);
1103                 mono_raise_exception ((MonoException*)exc);
1104         }
1105
1106         mono_method_return_message_restore (method, params, out_args);
1107         return res;
1108 }
1109
1110 static void
1111 mono_mb_emit_restore_result (MonoMethodBuilder *mb, MonoType *return_type)
1112 {
1113         if (return_type->byref)
1114                 return_type = &mono_defaults.int_class->byval_arg;
1115         else if (return_type->type == MONO_TYPE_VALUETYPE && return_type->data.klass->enumtype)
1116                 return_type = return_type->data.klass->enum_basetype;
1117
1118         switch (return_type->type) {
1119         case MONO_TYPE_VOID:
1120                 g_assert_not_reached ();
1121                 break;
1122         case MONO_TYPE_STRING:
1123         case MONO_TYPE_CLASS: 
1124         case MONO_TYPE_OBJECT: 
1125         case MONO_TYPE_ARRAY: 
1126         case MONO_TYPE_SZARRAY: 
1127                 /* nothing to do */
1128                 break;
1129         case MONO_TYPE_U1:
1130         case MONO_TYPE_BOOLEAN:
1131                 mono_mb_emit_byte (mb, CEE_UNBOX);
1132                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1133                 mono_mb_emit_byte (mb, CEE_LDIND_U1);
1134                 break;
1135         case MONO_TYPE_I1:
1136                 mono_mb_emit_byte (mb, CEE_UNBOX);
1137                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1138                 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1139                 break;
1140         case MONO_TYPE_U2:
1141         case MONO_TYPE_CHAR:
1142                 mono_mb_emit_byte (mb, CEE_UNBOX);
1143                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1144                 mono_mb_emit_byte (mb, CEE_LDIND_U2);
1145                 break;
1146         case MONO_TYPE_I2:
1147                 mono_mb_emit_byte (mb, CEE_UNBOX);
1148                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1149                 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1150                 break;
1151         case MONO_TYPE_I:
1152         case MONO_TYPE_U:
1153                 mono_mb_emit_byte (mb, CEE_UNBOX);
1154                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1155                 mono_mb_emit_byte (mb, CEE_LDIND_I);
1156                 break;
1157         case MONO_TYPE_I4:
1158                 mono_mb_emit_byte (mb, CEE_UNBOX);
1159                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1160                 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1161                 break;
1162         case MONO_TYPE_U4:
1163                 mono_mb_emit_byte (mb, CEE_UNBOX);
1164                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1165                 mono_mb_emit_byte (mb, CEE_LDIND_U4);
1166                 break;
1167         case MONO_TYPE_U8:
1168         case MONO_TYPE_I8:
1169                 mono_mb_emit_byte (mb, CEE_UNBOX);
1170                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1171                 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1172                 break;
1173         case MONO_TYPE_R4:
1174                 mono_mb_emit_byte (mb, CEE_UNBOX);
1175                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1176                 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1177                 break;
1178         case MONO_TYPE_R8:
1179                 mono_mb_emit_byte (mb, CEE_UNBOX);
1180                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1181                 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1182                 break;
1183         case MONO_TYPE_VALUETYPE: {
1184                 int class;
1185                 mono_mb_emit_byte (mb, CEE_UNBOX);
1186                 class = mono_mb_add_data (mb, mono_class_from_mono_type (return_type));
1187                 mono_mb_emit_i4 (mb, class);
1188                 mono_mb_emit_byte (mb, CEE_LDOBJ);
1189                 mono_mb_emit_i4 (mb, class);
1190                 break;
1191         }
1192         default:
1193                 g_warning ("type 0x%x not handled", return_type->type);
1194                 g_assert_not_reached ();
1195         }
1196
1197         mono_mb_emit_byte (mb, CEE_RET);
1198 }
1199
1200 MonoMethod *
1201 mono_marshal_get_delegate_end_invoke (MonoMethod *method)
1202 {
1203         MonoMethodSignature *sig;
1204         static MonoMethodSignature *csig = NULL;
1205         MonoMethodBuilder *mb;
1206         MonoMethod *res;
1207         GHashTable *cache;
1208         int params_var;
1209         char *name;
1210
1211         g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1212                   !strcmp (method->name, "EndInvoke"));
1213
1214         sig = method->signature;
1215
1216         cache = method->klass->image->delegate_end_invoke_cache;
1217         if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1218                 return res;
1219
1220         g_assert (sig->hasthis);
1221
1222         if (!csig) {
1223                 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1224                 csig = g_malloc0 (sigsize);
1225
1226                 /* MonoObject *end_invoke (MonoDelegate *delegate, gpointer params[]) */
1227                 csig->param_count = 2;
1228                 csig->ret = &mono_defaults.object_class->byval_arg;
1229                 csig->params [0] = &mono_defaults.object_class->byval_arg;
1230                 csig->params [1] = &mono_defaults.int_class->byval_arg;
1231         }
1232
1233         name = mono_signature_to_name (sig, "end_invoke");
1234         mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_END_INVOKE);
1235         g_free (name);
1236
1237         mb->method->save_lmf = 1;
1238
1239         params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1240
1241         mono_mb_emit_ldarg (mb, 0);
1242         mono_mb_emit_ldloc (mb, params_var);
1243         mono_mb_emit_native_call (mb, csig, mono_delegate_end_invoke);
1244
1245         if (sig->ret->type == MONO_TYPE_VOID) {
1246                 mono_mb_emit_byte (mb, CEE_POP);
1247                 mono_mb_emit_byte (mb, CEE_RET);
1248         } else
1249                 mono_mb_emit_restore_result (mb, sig->ret);
1250
1251         res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1252         mono_mb_free (mb);
1253         g_hash_table_insert (cache, sig, res);
1254
1255         return res;
1256 }
1257
1258 static MonoObject *
1259 mono_remoting_wrapper (MonoMethod *method, gpointer *params)
1260 {
1261         MonoMethodMessage *msg;
1262         MonoTransparentProxy *this;
1263         MonoObject *res, *exc;
1264         MonoArray *out_args;
1265
1266         this = *((MonoTransparentProxy **)params [0]);
1267
1268         g_assert (this);
1269         g_assert (((MonoObject *)this)->vtable->klass == mono_defaults.transparent_proxy_class);
1270         
1271         /* skip the this pointer */
1272         params++;
1273
1274         msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1275
1276         res = mono_remoting_invoke ((MonoObject *)this->rp, msg, &exc, &out_args);
1277
1278         if (exc)
1279                 mono_raise_exception ((MonoException *)exc);
1280
1281         mono_method_return_message_restore (method, params, out_args);
1282
1283         return res;
1284
1285
1286 MonoMethod *
1287 mono_marshal_get_remoting_invoke (MonoMethod *method)
1288 {
1289         MonoMethodSignature *sig;
1290         static MonoMethodSignature *csig = NULL;
1291         MonoMethodBuilder *mb;
1292         MonoMethod *res;
1293         GHashTable *cache;
1294         int params_var;
1295
1296         g_assert (method);
1297
1298         if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE)
1299                 return method;
1300
1301         sig = method->signature;
1302
1303         /* we cant remote methods without this pointer */
1304         if (!sig->hasthis)
1305                 return method;
1306
1307         cache = method->klass->image->remoting_invoke_cache;
1308         if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1309                 return res;
1310
1311         if (!csig) {
1312                 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1313                 csig = g_malloc0 (sigsize);
1314
1315                 /* MonoObject *remoting_wrapper (MonoMethod *method, gpointer params[]) */
1316                 csig->param_count = 2;
1317                 csig->ret = &mono_defaults.object_class->byval_arg;
1318                 csig->params [0] = &mono_defaults.int_class->byval_arg;
1319                 csig->params [1] = &mono_defaults.int_class->byval_arg;
1320         }
1321
1322         mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE);
1323         mb->method->save_lmf = 1;
1324
1325         params_var = mono_mb_emit_save_args (mb, sig, TRUE);
1326
1327         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1328         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1329         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
1330         mono_mb_emit_ldloc (mb, params_var);
1331         mono_mb_emit_native_call (mb, csig, mono_remoting_wrapper);
1332
1333         if (sig->ret->type == MONO_TYPE_VOID)
1334                 mono_mb_emit_byte (mb, CEE_POP);
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, method, res);
1341         return res;
1342 }
1343
1344 /*
1345  * the returned method invokes all methods in a multicast delegate 
1346  */
1347 MonoMethod *
1348 mono_marshal_get_delegate_invoke (MonoMethod *method)
1349 {
1350         MonoMethodSignature *sig, *static_sig;
1351         int i, sigsize;
1352         MonoMethodBuilder *mb;
1353         MonoMethod *res;
1354         GHashTable *cache;
1355         int pos0, pos1;
1356         char *name;
1357
1358         g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1359                   !strcmp (method->name, "Invoke"));
1360                 
1361         sig = method->signature;
1362
1363         cache = method->klass->image->delegate_invoke_cache;
1364         if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1365                 return res;
1366
1367         sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1368         static_sig = g_memdup (sig, sigsize);
1369         static_sig->hasthis = 0;
1370
1371         name = mono_signature_to_name (sig, "invoke");
1372         mb = mono_mb_new (mono_defaults.multicastdelegate_class, name,  MONO_WRAPPER_DELEGATE_INVOKE);
1373         g_free (name);
1374
1375         /* allocate local 0 (object) */
1376         mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1377
1378         g_assert (sig->hasthis);
1379         
1380         /*
1381          * if (prev != null)
1382          *      prev.Invoke( args .. );
1383          * return this.<target>( args .. );
1384          */
1385
1386         /* get this->prev */
1387         mono_mb_emit_ldarg (mb, 0);
1388         mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoMulticastDelegate, prev));
1389         mono_mb_emit_byte (mb, CEE_LDIND_I );
1390         mono_mb_emit_stloc (mb, 0);
1391
1392         /* if prev != null */
1393         mono_mb_emit_ldloc (mb, 0);
1394         mono_mb_emit_byte (mb, CEE_BRFALSE);
1395
1396         pos0 = mb->pos;
1397         mono_mb_emit_i4 (mb, 0);
1398
1399         /* then recurse */
1400         mono_mb_emit_ldloc (mb, 0);
1401         for (i = 0; i < sig->param_count; i++)
1402                 mono_mb_emit_ldarg (mb, i + 1);
1403         mono_mb_emit_managed_call (mb, method, method->signature);
1404         if (sig->ret->type != MONO_TYPE_VOID)
1405                 mono_mb_emit_byte (mb, CEE_POP);
1406
1407         /* continued or prev == null */
1408         mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1409
1410         /* get this->target */
1411         mono_mb_emit_ldarg (mb, 0);
1412         mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, target));
1413         mono_mb_emit_byte (mb, CEE_LDIND_I );
1414         mono_mb_emit_stloc (mb, 0);
1415
1416         /* if target != null */
1417         mono_mb_emit_ldloc (mb, 0);
1418         mono_mb_emit_byte (mb, CEE_BRFALSE);
1419         pos0 = mb->pos;
1420         mono_mb_emit_i4 (mb, 0);
1421         
1422         /* then call this->method_ptr nonstatic */
1423         mono_mb_emit_ldloc (mb, 0); 
1424         for (i = 0; i < sig->param_count; ++i)
1425                 mono_mb_emit_ldarg (mb, i + 1);
1426         mono_mb_emit_ldarg (mb, 0);
1427         mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1428         mono_mb_emit_byte (mb, CEE_LDIND_I );
1429         mono_mb_emit_byte (mb, CEE_CALLI);
1430         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
1431
1432         mono_mb_emit_byte (mb, CEE_BR);
1433         pos1 = mb->pos;
1434         mono_mb_emit_i4 (mb, 0);
1435
1436         /* else [target == null] call this->method_ptr static */
1437         mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1438
1439         for (i = 0; i < sig->param_count; ++i)
1440                 mono_mb_emit_ldarg (mb, i + 1);
1441         mono_mb_emit_ldarg (mb, 0);
1442         mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1443         mono_mb_emit_byte (mb, CEE_LDIND_I );
1444         mono_mb_emit_byte (mb, CEE_CALLI);
1445         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, static_sig));
1446
1447         /* return */
1448         mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
1449         mono_mb_emit_byte (mb, CEE_RET);
1450
1451         res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1452         mono_mb_free (mb);
1453
1454         g_hash_table_insert (cache, sig, res);
1455
1456         return res;     
1457 }
1458
1459 /*
1460  * generates IL code for the runtime invoke function 
1461  * MonoObject *runtime_invoke (MonoObject *this, void **params, MonoObject **exc)
1462  *
1463  * we also catch exceptions if exc != null
1464  */
1465 MonoMethod *
1466 mono_marshal_get_runtime_invoke (MonoMethod *method)
1467 {
1468         MonoMethodSignature *sig, *csig;
1469         MonoExceptionClause *clause;
1470         MonoMethodHeader *header;
1471         MonoMethodBuilder *mb;
1472         MonoMethod *res;
1473         GHashTable *cache;
1474         static MonoString *string_dummy = NULL;
1475         int i, pos, sigsize;
1476
1477         g_assert (method);
1478
1479         cache = method->klass->image->runtime_invoke_cache;
1480         if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1481                 return res;
1482         
1483         /* to make it work with our special string constructors */
1484         if (!string_dummy)
1485                 string_dummy = mono_string_new_wrapper ("dummy");
1486
1487         sig = method->signature;
1488
1489         sigsize = sizeof (MonoMethodSignature) + 3 * sizeof (MonoType *);
1490         csig = g_malloc0 (sigsize);
1491
1492         csig->param_count = 3;
1493         csig->ret = &mono_defaults.object_class->byval_arg;
1494         csig->params [0] = &mono_defaults.object_class->byval_arg;
1495         csig->params [1] = &mono_defaults.int_class->byval_arg;
1496         csig->params [2] = &mono_defaults.int_class->byval_arg;
1497
1498         mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_RUNTIME_INVOKE);
1499
1500         /* allocate local 0 (object) tmp */
1501         mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1502         /* allocate local 1 (object) exc */
1503         mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1504
1505         /* cond set *exc to null */
1506         mono_mb_emit_byte (mb, CEE_LDARG_2);
1507         mono_mb_emit_byte (mb, CEE_BRFALSE_S);
1508         mono_mb_emit_byte (mb, 3);      
1509         mono_mb_emit_byte (mb, CEE_LDARG_2);
1510         mono_mb_emit_byte (mb, CEE_LDNULL);
1511         mono_mb_emit_byte (mb, CEE_STIND_I);
1512
1513         if (sig->hasthis) {
1514                 if (method->string_ctor) {
1515                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1516                         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1517                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, string_dummy));
1518                 } else {
1519                         mono_mb_emit_ldarg (mb, 0);
1520                         if (method->klass->valuetype) {
1521                                 mono_mb_emit_byte (mb, CEE_UNBOX);
1522                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method->klass));
1523                         } 
1524                 }
1525         }
1526
1527         for (i = 0; i < sig->param_count; i++) {
1528                 MonoType *t = sig->params [i];
1529                 int type;
1530
1531                 mono_mb_emit_ldarg (mb, 1);
1532                 if (i) {
1533                         mono_mb_emit_icon (mb, sizeof (gpointer) * i);
1534                         mono_mb_emit_byte (mb, CEE_ADD);
1535                 }
1536                 mono_mb_emit_byte (mb, CEE_LDIND_I);
1537
1538                 if (t->byref)
1539                         continue;
1540
1541                 type = sig->params [i]->type;
1542 handle_enum:
1543                 switch (type) {
1544                 case MONO_TYPE_I1:
1545                         mono_mb_emit_byte (mb, CEE_LDIND_I1);
1546                         break;
1547                 case MONO_TYPE_BOOLEAN:
1548                 case MONO_TYPE_U1:
1549                         mono_mb_emit_byte (mb, CEE_LDIND_U1);
1550                         break;
1551                 case MONO_TYPE_I2:
1552                         mono_mb_emit_byte (mb, CEE_LDIND_I2);
1553                         break;
1554                 case MONO_TYPE_U2:
1555                 case MONO_TYPE_CHAR:
1556                         mono_mb_emit_byte (mb, CEE_LDIND_U2);
1557                         break;
1558                 case MONO_TYPE_I:
1559                 case MONO_TYPE_U:
1560                         mono_mb_emit_byte (mb, CEE_LDIND_I);
1561                         break;
1562                 case MONO_TYPE_I4:
1563                         mono_mb_emit_byte (mb, CEE_LDIND_I4);
1564                         break;
1565                 case MONO_TYPE_U4:
1566                         mono_mb_emit_byte (mb, CEE_LDIND_U4);
1567                         break;
1568                 case MONO_TYPE_R4:
1569                         mono_mb_emit_byte (mb, CEE_LDIND_R4);
1570                         break;
1571                 case MONO_TYPE_R8:
1572                         mono_mb_emit_byte (mb, CEE_LDIND_R8);
1573                         break;
1574                 case MONO_TYPE_I8:
1575                 case MONO_TYPE_U8:
1576                         mono_mb_emit_byte (mb, CEE_LDIND_I8);
1577                         break;
1578                 case MONO_TYPE_STRING:
1579                 case MONO_TYPE_CLASS:  
1580                 case MONO_TYPE_ARRAY:
1581                 case MONO_TYPE_PTR:
1582                 case MONO_TYPE_SZARRAY:
1583                 case MONO_TYPE_OBJECT:
1584                         /* do nothing */
1585                         break;
1586                 case MONO_TYPE_VALUETYPE:
1587                         if (t->data.klass->enumtype) {
1588                                 type = t->data.klass->enum_basetype->type;
1589                                 goto handle_enum;
1590                         }
1591                         mono_mb_emit_byte (mb, CEE_LDOBJ);
1592                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, t->data.klass));
1593                         break;
1594                 default:
1595                         g_assert_not_reached ();
1596                 }               
1597         }
1598
1599         if (method->string_ctor) {
1600                 MonoMethodSignature *strsig;
1601
1602                 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1603                 strsig = g_memdup (sig, sigsize);
1604                 strsig->ret = &mono_defaults.string_class->byval_arg;
1605
1606                 mono_mb_emit_managed_call (mb, method, strsig);         
1607         } else 
1608                 mono_mb_emit_managed_call (mb, method, NULL);
1609
1610         if (sig->ret->byref) {
1611                 /* fixme: */
1612                 g_assert_not_reached ();
1613         }
1614
1615
1616         switch (sig->ret->type) {
1617         case MONO_TYPE_VOID:
1618                 if (!method->string_ctor)
1619                         mono_mb_emit_byte (mb, CEE_LDNULL);
1620                 break;
1621         case MONO_TYPE_BOOLEAN:
1622         case MONO_TYPE_CHAR:
1623         case MONO_TYPE_I1:
1624         case MONO_TYPE_U1:
1625         case MONO_TYPE_I2:
1626         case MONO_TYPE_U2:
1627         case MONO_TYPE_I4:
1628         case MONO_TYPE_U4:
1629         case MONO_TYPE_I:
1630         case MONO_TYPE_U:
1631         case MONO_TYPE_R4:
1632         case MONO_TYPE_R8:
1633         case MONO_TYPE_I8:
1634         case MONO_TYPE_U8:
1635         case MONO_TYPE_VALUETYPE:
1636                 /* box value types */
1637                 mono_mb_emit_byte (mb, CEE_BOX);
1638                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (sig->ret)));
1639                 break;
1640         case MONO_TYPE_STRING:
1641         case MONO_TYPE_CLASS:  
1642         case MONO_TYPE_ARRAY:
1643         case MONO_TYPE_SZARRAY:
1644         case MONO_TYPE_OBJECT:
1645                 /* nothing to do */
1646                 break;
1647         case MONO_TYPE_PTR:
1648         default:
1649                 g_assert_not_reached ();
1650         }
1651
1652         mono_mb_emit_stloc (mb, 0);
1653                 
1654         mono_mb_emit_byte (mb, CEE_LEAVE);
1655         pos = mb->pos;
1656         mono_mb_emit_i4 (mb, 0);
1657
1658         clause = g_new0 (MonoExceptionClause, 1);
1659         clause->flags = MONO_EXCEPTION_CLAUSE_FILTER;
1660         clause->try_len = mb->pos;
1661
1662         /* filter code */
1663         clause->token_or_filter = mb->pos;
1664         
1665         mono_mb_emit_byte (mb, CEE_POP);
1666         mono_mb_emit_byte (mb, CEE_LDARG_2);
1667         mono_mb_emit_byte (mb, CEE_LDC_I4_0);
1668         mono_mb_emit_byte (mb, CEE_PREFIX1);
1669         mono_mb_emit_byte (mb, CEE_CGT_UN);
1670         mono_mb_emit_byte (mb, CEE_PREFIX1);
1671         mono_mb_emit_byte (mb, CEE_ENDFILTER);
1672
1673         clause->handler_offset = mb->pos;
1674
1675         /* handler code */
1676         /* store exception */
1677         mono_mb_emit_stloc (mb, 1);
1678         
1679         mono_mb_emit_byte (mb, CEE_LDARG_2);
1680         mono_mb_emit_ldloc (mb, 1);
1681         mono_mb_emit_byte (mb, CEE_STIND_I);
1682
1683         mono_mb_emit_byte (mb, CEE_LEAVE);
1684         mono_mb_emit_i4 (mb, 0);
1685
1686         clause->handler_len = mb->pos - clause->handler_offset;
1687
1688         /* return result */
1689         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1690         mono_mb_emit_ldloc (mb, 0);
1691         mono_mb_emit_byte (mb, CEE_RET);
1692         
1693         res = mono_mb_create_method (mb, csig, sig->param_count + 16);
1694         mono_mb_free (mb);
1695
1696         header = ((MonoMethodNormal *)res)->header;
1697         header->num_clauses = 1;
1698         header->clauses = clause;
1699
1700         g_hash_table_insert (cache, method, res);
1701
1702         return res;     
1703 }
1704
1705 /*
1706  * generates IL code to call managed methods from unmanaged code 
1707  */
1708 MonoMethod *
1709 mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this)
1710 {
1711         MonoMethodSignature *sig, *csig;
1712         MonoMethodBuilder *mb;
1713         MonoClass *klass;
1714         MonoMethod *res;
1715         GHashTable *cache;
1716         int i, pos, sigsize, *tmp_locals;
1717
1718         g_assert (method != NULL);
1719
1720         cache = method->klass->image->managed_wrapper_cache;
1721         if (!this && (res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1722                 return res;
1723
1724         if (this) {
1725                 /* fime: howto free that memory ? */
1726         }
1727         
1728         sig = method->signature;
1729
1730         mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_NATIVE_TO_MANAGED);
1731
1732         /* allocate local 0 (pointer) src_ptr */
1733         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1734         /* allocate local 1 (pointer) dst_ptr */
1735         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1736         /* allocate local 2 (boolean) delete_old */
1737         mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
1738
1739         mono_mb_emit_byte (mb, CEE_LDNULL);
1740         mono_mb_emit_byte (mb, CEE_STLOC_2);
1741
1742         /* we copy the signature, so that we can modify it */
1743         sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1744         csig = g_memdup (sig, sigsize);
1745         csig->hasthis = 0;
1746         csig->pinvoke = 1;
1747
1748         /* fixme: howto handle this ? */
1749         if (sig->hasthis) {
1750
1751                 if (this) {
1752                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1753                         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1754                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, this));
1755
1756
1757                 } else {
1758                         /* fixme: */
1759                         g_assert_not_reached ();
1760                 }
1761         } 
1762
1763
1764         /* we first do all conversions */
1765         tmp_locals = alloca (sizeof (int) * sig->param_count);
1766         for (i = 0; i < sig->param_count; i ++) {
1767                 MonoType *t = sig->params [i];
1768
1769                 tmp_locals [i] = 0;
1770                 
1771                 switch (t->type) {
1772                 case MONO_TYPE_VALUETYPE:
1773                         
1774                         klass = sig->params [i]->data.klass;
1775                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
1776                             klass->blittable || klass->enumtype)
1777                                 break;
1778
1779                         tmp_locals [i] = mono_mb_add_local (mb, &klass->byval_arg);
1780
1781                         if (t->byref) 
1782                                 mono_mb_emit_ldarg (mb, i);
1783                         else
1784                                 mono_mb_emit_ldarg_addr (mb, i);
1785                         mono_mb_emit_byte (mb, CEE_STLOC_0);
1786
1787                         if (t->byref) {
1788                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1789                                 mono_mb_emit_byte (mb, CEE_BRFALSE);
1790                                 pos = mb->pos;
1791                                 mono_mb_emit_i4 (mb, 0);
1792                         }                       
1793
1794                         mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
1795                         mono_mb_emit_byte (mb, CEE_STLOC_1);
1796
1797                         /* emit valuetype convnversion code code */
1798                         emit_struct_conv (mb, klass, TRUE);
1799
1800                         if (t->byref)
1801                                 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1802                         break;
1803                 case MONO_TYPE_STRING:
1804                         if (t->byref)
1805                                 continue;
1806
1807                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1808                         csig->params [i] = &mono_defaults.int_class->byval_arg;
1809
1810                         mono_mb_emit_ldarg (mb, i);
1811                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1812                         mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1813                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
1814                         mono_mb_emit_stloc (mb, tmp_locals [i]);
1815                         break;  
1816                 case MONO_TYPE_ARRAY:
1817                 case MONO_TYPE_SZARRAY:
1818                         if (t->byref)
1819                                 continue;
1820
1821                         klass = mono_class_from_mono_type (t);
1822
1823                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1824                         csig->params [i] = &mono_defaults.int_class->byval_arg;
1825
1826                         g_warning ("array marshaling not implemented");
1827                         g_assert_not_reached ();
1828                         break;
1829                 }
1830         }
1831
1832         for (i = 0; i < sig->param_count; i++) {
1833                 MonoType *t = sig->params [i];
1834
1835                 switch (t->type) {
1836                 case MONO_TYPE_BOOLEAN:
1837                 case MONO_TYPE_I1:
1838                 case MONO_TYPE_U1:
1839                 case MONO_TYPE_I2:
1840                 case MONO_TYPE_U2:
1841                 case MONO_TYPE_I4:
1842                 case MONO_TYPE_U4:
1843                 case MONO_TYPE_I:
1844                 case MONO_TYPE_U:
1845                 case MONO_TYPE_PTR:
1846                 case MONO_TYPE_R4:
1847                 case MONO_TYPE_R8:
1848                 case MONO_TYPE_I8:
1849                 case MONO_TYPE_U8:
1850                         mono_mb_emit_ldarg (mb, i);
1851                         break;
1852                 case MONO_TYPE_STRING:
1853                         if (t->byref) {
1854                                 mono_mb_emit_ldarg (mb, i);
1855                         } else {
1856                                 g_assert (tmp_locals [i]);
1857                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
1858                         }
1859                         break;  
1860                 case MONO_TYPE_CLASS:  
1861                 case MONO_TYPE_ARRAY:
1862                 case MONO_TYPE_SZARRAY:
1863                 case MONO_TYPE_OBJECT:
1864                         /* fixme: conversions ? */
1865                         mono_mb_emit_ldarg (mb, i);
1866                         break;
1867                 case MONO_TYPE_VALUETYPE:
1868                         klass = sig->params [i]->data.klass;
1869                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
1870                             klass->blittable || klass->enumtype) {
1871                                 mono_mb_emit_ldarg (mb, i);
1872                                 break;
1873                         }
1874
1875                         g_assert (tmp_locals [i]);
1876                         if (t->byref)
1877                                 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
1878                         else
1879                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
1880                         break;
1881                 default:
1882                         g_warning ("type 0x%02x unknown", t->type);     
1883                         g_assert_not_reached ();
1884                 }
1885         }
1886
1887         mono_mb_emit_managed_call (mb, method, NULL);
1888
1889         if (!sig->ret->byref) { 
1890                 switch (sig->ret->type) {
1891                 case MONO_TYPE_VOID:
1892                 case MONO_TYPE_BOOLEAN:
1893                 case MONO_TYPE_I1:
1894                 case MONO_TYPE_U1:
1895                 case MONO_TYPE_I2:
1896                 case MONO_TYPE_U2:
1897                 case MONO_TYPE_I4:
1898                 case MONO_TYPE_U4:
1899                 case MONO_TYPE_I:
1900                 case MONO_TYPE_U:
1901                 case MONO_TYPE_PTR:
1902                 case MONO_TYPE_R4:
1903                 case MONO_TYPE_R8:
1904                 case MONO_TYPE_I8:
1905                 case MONO_TYPE_U8:
1906                         /* do nothing */
1907                         break;
1908                 case MONO_TYPE_STRING:          
1909                         csig->ret = &mono_defaults.int_class->byval_arg;
1910
1911                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1912                         mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1913                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
1914                         break;
1915                 case MONO_TYPE_VALUETYPE: {
1916                         int tmp;
1917                         klass = sig->ret->data.klass;
1918                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
1919                             klass->blittable || klass->enumtype)
1920                                 break;
1921                         
1922                         /* load pointer to returned value type */
1923                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1924                         mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
1925                         
1926                         /* store the address of the source into local variable 0 */
1927                         mono_mb_emit_byte (mb, CEE_STLOC_0);
1928                         /* allocate space for the native struct and
1929                          * store the address into dst_ptr */
1930                         tmp = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1931                         g_assert (tmp);
1932                         mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
1933                         mono_mb_emit_byte (mb, CEE_PREFIX1);
1934                         mono_mb_emit_byte (mb, CEE_LOCALLOC);
1935                         mono_mb_emit_byte (mb, CEE_STLOC_1);
1936                         mono_mb_emit_byte (mb, CEE_LDLOC_1);
1937                         mono_mb_emit_stloc (mb, tmp);
1938
1939                         /* emit valuetype conversion code */
1940                         emit_struct_conv (mb, klass, FALSE);
1941                         mono_mb_emit_ldloc (mb, tmp);
1942                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1943                         mono_mb_emit_byte (mb, CEE_MONO_RETOBJ);
1944                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
1945                         break;
1946                 }
1947                 default:
1948                         g_warning ("return type 0x%02x unknown", sig->ret->type);       
1949                         g_assert_not_reached ();
1950                 }
1951         }
1952
1953         mono_mb_emit_byte (mb, CEE_RET);
1954
1955         res = mono_mb_create_method (mb, csig, sig->param_count + 16);
1956         mono_mb_free (mb);
1957
1958         if (!this)
1959                 g_hash_table_insert (cache, method, res);
1960
1961         return res;
1962 }
1963
1964 /*
1965  * generates IL code for the icall wrapper (the generated method
1966  * calls the unamnaged code in func)
1967  */
1968 MonoMethod *
1969 mono_marshal_get_icall_wrapper (MonoMethodSignature *sig, const char *name, gpointer func)
1970 {
1971         MonoMethodSignature *csig;
1972         MonoMethodBuilder *mb;
1973         MonoMethod *res;
1974         int i, sigsize;
1975
1976         mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_MANAGED_TO_NATIVE);
1977
1978         mb->method->save_lmf = 1;
1979
1980         /* we copy the signature, so that we can modify it */
1981         sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1982
1983         if (sig->hasthis)
1984                 mono_mb_emit_byte (mb, CEE_LDARG_0);
1985
1986         for (i = 0; i < sig->param_count; i++)
1987                 mono_mb_emit_ldarg (mb, i + sig->hasthis);
1988
1989         csig = g_memdup (sig, sigsize);
1990         csig->pinvoke = 1;
1991
1992         mono_mb_emit_native_call (mb, csig, func);
1993
1994         mono_mb_emit_byte (mb, CEE_RET);
1995
1996         res = mono_mb_create_method (mb, csig, csig->param_count + 16);
1997         mono_mb_free (mb);
1998         
1999         return res;
2000 }
2001
2002 /*
2003  * generates IL code for the pinvoke wrapper (the generated method
2004  * calls the unamnage code in method->addr)
2005  */
2006 MonoMethod *
2007 mono_marshal_get_native_wrapper (MonoMethod *method)
2008 {
2009         MonoMethodSignature *sig, *csig;
2010         MonoMethodBuilder *mb;
2011         MonoMarshalSpec **mspecs;
2012         MonoMethod *res;
2013         GHashTable *cache;
2014         MonoClass *klass;
2015         gboolean pinvoke = FALSE;
2016         int i, pos, argnum, *tmp_locals;
2017         int type, sigsize;
2018
2019         g_assert (method != NULL);
2020
2021         cache = method->klass->image->native_wrapper_cache;
2022         if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
2023                 return res;
2024
2025         sig = method->signature;
2026
2027         if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
2028             (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2029                 pinvoke = TRUE;
2030
2031         mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_MANAGED_TO_NATIVE);
2032
2033         mb->method->save_lmf = 1;
2034
2035         if (pinvoke && !method->addr)
2036                 mono_lookup_pinvoke_call (method);
2037
2038         if (!method->addr) {
2039                 mono_mb_emit_exception (mb);
2040                 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
2041                 mono_mb_free (mb);
2042                 g_hash_table_insert (cache, method, res);
2043                 return res;
2044         }
2045
2046         /* we copy the signature, so that we can modify it */
2047         sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
2048
2049         /* internal calls: we simply push all arguments and call the method (no conversions) */
2050         if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
2051
2052                 MonoMethodSignature *call_sig;
2053
2054                 /* hack - string constructors returns a value */
2055                 if (method->string_ctor) {
2056                         csig = g_memdup (sig, sigsize);
2057                         csig->ret = &mono_defaults.string_class->byval_arg;
2058                 } else
2059                         csig = sig;
2060
2061                 if (sig->hasthis)
2062                         mono_mb_emit_byte (mb, CEE_LDARG_0);
2063
2064                 for (i = 0; i < sig->param_count; i++)
2065                         mono_mb_emit_ldarg (mb, i + sig->hasthis);
2066
2067                 call_sig = g_memdup (csig, sigsize);
2068                 call_sig->pinvoke = 1;
2069
2070                 g_assert (method->addr);
2071                 mono_mb_emit_native_call (mb, call_sig, method->addr);
2072
2073                 mono_mb_emit_byte (mb, CEE_RET);
2074
2075                 res = mono_mb_create_method (mb, csig, sig->param_count + 16);
2076                 mono_mb_free (mb);
2077                 g_hash_table_insert (cache, method, res);
2078                 return res;
2079         }
2080
2081         g_assert (pinvoke);
2082
2083         mspecs = g_new (MonoMarshalSpec, sig->param_count + 1);
2084         mono_method_get_marshal_info (method, mspecs);
2085
2086         /* pinvoke: we need to convert the arguments if necessary */
2087
2088         csig = g_memdup (sig, sigsize);
2089         csig->pinvoke = 1;
2090
2091         /* we allocate local for use with emit_struct_conv() */
2092         /* allocate local 0 (pointer) src_ptr */
2093         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2094         /* allocate local 1 (pointer) dst_ptr */
2095         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2096         /* allocate local 2 (boolean) delete_old */
2097         mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2098
2099         /* delete_old = FALSE */
2100         mono_mb_emit_icon (mb, 0);
2101         mono_mb_emit_byte (mb, CEE_STLOC_2);
2102
2103         if (sig->ret->type != MONO_TYPE_VOID) {
2104                 /* allocate local 3 to store the return value */
2105                 mono_mb_add_local (mb, sig->ret);
2106         }
2107
2108         /* we first do all conversions */
2109         tmp_locals = alloca (sizeof (int) * sig->param_count);
2110         for (i = 0; i < sig->param_count; i ++) {
2111                 MonoType *t = sig->params [i];
2112                 MonoMarshalSpec *spec = mspecs [i + 1];
2113
2114                 argnum = i + sig->hasthis;
2115                 tmp_locals [i] = 0;
2116
2117                 switch (t->type) {
2118                 case MONO_TYPE_VALUETYPE:                       
2119                         klass = t->data.klass;
2120
2121                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2122                             klass->blittable || klass->enumtype)
2123                                 break;
2124
2125                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2126                         
2127                         /* store the address of the source into local variable 0 */
2128                         if (t->byref)
2129                                 mono_mb_emit_ldarg (mb, argnum);
2130                         else
2131                                 mono_mb_emit_ldarg_addr (mb, argnum);
2132
2133                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2134                         
2135                         /* allocate space for the native struct and
2136                          * store the address into local variable 1 (dest) */
2137                         mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2138                         mono_mb_emit_byte (mb, CEE_PREFIX1);
2139                         mono_mb_emit_byte (mb, CEE_LOCALLOC);
2140                         mono_mb_emit_stloc (mb, tmp_locals [i]);
2141
2142                         if (t->byref) {
2143                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2144                                 mono_mb_emit_byte (mb, CEE_BRFALSE);
2145                                 pos = mb->pos;
2146                                 mono_mb_emit_i4 (mb, 0);
2147                         }
2148
2149                         /* set dst_ptr */
2150                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
2151                         mono_mb_emit_byte (mb, CEE_STLOC_1);
2152
2153                         /* emit valuetype conversion code */
2154                         emit_struct_conv (mb, klass, FALSE);
2155                         
2156                         if (t->byref)
2157                                 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2158                         break;
2159                 case MONO_TYPE_STRING:
2160                         if (t->byref)
2161                                 continue;
2162
2163                         csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2164                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2165
2166                         mono_mb_emit_ldarg (mb, argnum);
2167                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2168                         mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2169
2170                         if (spec) {
2171                                 switch (spec->native) {
2172                                 case MONO_NATIVE_LPWSTR:
2173                                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPWSTR);
2174                                         break;
2175                                 default:
2176                                         g_warning ("marshalling conversion not implemented");
2177                                         g_assert_not_reached ();
2178                                 }
2179                         } else {
2180                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
2181                         }
2182
2183                         mono_mb_emit_stloc (mb, tmp_locals [i]);
2184                         break;
2185                 case MONO_TYPE_CLASS:
2186                 case MONO_TYPE_OBJECT:
2187                         if (t->byref)
2188                                 continue;
2189
2190                         csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2191                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2192
2193                         if (t->data.klass->delegate) {
2194                                 mono_mb_emit_ldarg (mb, argnum);
2195                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2196                                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2197                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_DEL_FTN);
2198                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
2199                         } else if (t->data.klass == mono_defaults.stringbuilder_class) {
2200                                 mono_mb_emit_ldarg (mb, argnum);
2201                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2202                                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2203                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_SB_LPSTR);
2204                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
2205                         } else {
2206                                 mono_mb_emit_ldarg (mb, argnum);
2207                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2208                                 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2209                                 /* fixme: convert to what ? */
2210                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
2211                         }
2212
2213                         break;
2214                 case MONO_TYPE_ARRAY:
2215                 case MONO_TYPE_SZARRAY:
2216                         if (t->byref)
2217                                 continue;
2218
2219                         klass = mono_class_from_mono_type (t);
2220
2221                         csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2222                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2223
2224                         mono_mb_emit_ldarg (mb, argnum);
2225                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2226                         mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2227                         if (klass->element_class == mono_defaults.string_class) 
2228                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STRARRAY_STRLPARRAY);
2229                         else
2230                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_ARRAY_LPARRAY);
2231                         mono_mb_emit_stloc (mb, tmp_locals [i]);
2232                         break;
2233                 }
2234         }
2235
2236         /* push all arguments */
2237
2238         if (sig->hasthis)
2239                 mono_mb_emit_byte (mb, CEE_LDARG_0);
2240
2241         for (i = 0; i < sig->param_count; i++) {
2242                 MonoType *t = sig->params [i];
2243                 
2244                 argnum = i + sig->hasthis;
2245
2246                 switch (t->type) {
2247                 case MONO_TYPE_BOOLEAN:
2248                         if (t->byref)
2249                                 g_warning ("byref boolean marshalling not inplemented");
2250                         mono_mb_emit_ldarg (mb, argnum);
2251                         break;
2252                 case MONO_TYPE_I1:
2253                 case MONO_TYPE_U1:
2254                 case MONO_TYPE_I2:
2255                 case MONO_TYPE_U2:
2256                 case MONO_TYPE_I4:
2257                 case MONO_TYPE_U4:
2258                 case MONO_TYPE_I:
2259                 case MONO_TYPE_U:
2260                 case MONO_TYPE_PTR:
2261                 case MONO_TYPE_R4:
2262                 case MONO_TYPE_R8:
2263                 case MONO_TYPE_I8:
2264                 case MONO_TYPE_U8:
2265                         mono_mb_emit_ldarg (mb, argnum);
2266                         break;
2267                 case MONO_TYPE_VALUETYPE:
2268                         klass = sig->params [i]->data.klass;
2269                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2270                             klass->blittable || klass->enumtype) {
2271                                 mono_mb_emit_ldarg (mb, argnum);
2272                                 break;
2273                         }                       
2274                         g_assert (tmp_locals [i]);
2275                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
2276                         if (!t->byref) {
2277                                 mono_mb_emit_byte (mb, CEE_LDOBJ);
2278                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2279                         }
2280                         break;
2281                 case MONO_TYPE_STRING:
2282                         if (t->byref) {
2283                                 mono_mb_emit_ldarg (mb, argnum);
2284                         } else {
2285                                 g_assert (tmp_locals [i]);
2286                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2287                         }
2288                         break;
2289                 case MONO_TYPE_CLASS:
2290                 case MONO_TYPE_OBJECT:
2291                         if (t->byref) {
2292                                 mono_mb_emit_ldarg (mb, argnum);
2293                         } else {
2294                                 g_assert (tmp_locals [i]);
2295                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2296                         }
2297                         break;
2298                 case MONO_TYPE_CHAR:
2299                         /* fixme: dont know how to marshal that. We cant simply
2300                          * convert it to a one byte UTF8 character, because an
2301                          * unicode character may need more that one byte in UTF8 */
2302                         mono_mb_emit_ldarg (mb, argnum);
2303                         break;
2304                 case MONO_TYPE_ARRAY:
2305                 case MONO_TYPE_SZARRAY:
2306                         if (t->byref) {
2307                                 mono_mb_emit_ldarg (mb, argnum);
2308                         } else {
2309                                 g_assert (tmp_locals [i]);
2310                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2311                         }
2312                         break;
2313                 case MONO_TYPE_TYPEDBYREF:
2314                 case MONO_TYPE_FNPTR:
2315                 default:
2316                         g_warning ("type 0x%02x unknown", t->type);     
2317                         g_assert_not_reached ();
2318                 }
2319         }                       
2320
2321         /* call the native method */
2322         mono_mb_emit_native_call (mb, csig, method->addr);
2323
2324         /* return the result */
2325
2326         /* we need to convert byref arguments back and free string arrays */
2327         for (i = 0; i < sig->param_count; i++) {
2328                 MonoType *t = sig->params [i];
2329                 
2330                 argnum = i + sig->hasthis;
2331
2332                 switch (t->type) {
2333                 case MONO_TYPE_CLASS:
2334                 case MONO_TYPE_OBJECT:                  
2335                         if (t->byref)
2336                                 continue;
2337      
2338                         if (t->data.klass == mono_defaults.stringbuilder_class) {
2339                                 mono_mb_emit_ldarg (mb, argnum);
2340                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2341                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2342                                 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
2343                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_SB);
2344                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2345                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2346                                 mono_mb_emit_byte (mb, CEE_MONO_FREE);
2347                         }
2348                         break;
2349                 case MONO_TYPE_VALUETYPE:
2350                         if (!t->byref)
2351                                 continue;
2352         
2353                         klass = t->data.klass;
2354                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2355                             klass->blittable || klass->enumtype)
2356                                 break;
2357
2358                         /* dst = argument */
2359                         mono_mb_emit_ldarg (mb, argnum);
2360                         mono_mb_emit_byte (mb, CEE_STLOC_1);
2361
2362                         mono_mb_emit_byte (mb, CEE_LDLOC_1);
2363                         mono_mb_emit_byte (mb, CEE_BRFALSE);
2364                         pos = mb->pos;
2365                         mono_mb_emit_i4 (mb, 0);
2366
2367                         /* src = tmp_locals [i] */
2368                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
2369                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2370
2371                         /* emit valuetype conversion code */
2372                         emit_struct_conv (mb, klass, TRUE);
2373                         
2374                         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2375                         break;
2376                 case MONO_TYPE_SZARRAY:
2377                         if (t->byref)
2378                                 continue;
2379  
2380                         klass = mono_class_from_mono_type (t);
2381                         
2382                         if (klass->element_class == mono_defaults.string_class) {
2383                                 g_assert (tmp_locals [i]);
2384                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2385                                 mono_mb_emit_ldarg (mb, argnum);
2386                                 mono_mb_emit_byte (mb, CEE_LDLEN);                              
2387                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2388                                 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
2389                                 mono_mb_emit_byte (mb, MONO_MARSHAL_FREE_ARRAY);
2390                         }
2391
2392                         break;
2393                 }
2394         }
2395
2396         if (!sig->ret->byref) {
2397                 MonoMarshalSpec *spec = mspecs [0];
2398                 type = sig->ret->type;
2399
2400         handle_enum:
2401                 switch (type) {
2402                 case MONO_TYPE_VOID:
2403                 case MONO_TYPE_I1:
2404                 case MONO_TYPE_U1:
2405                 case MONO_TYPE_I2:
2406                 case MONO_TYPE_U2:
2407                 case MONO_TYPE_I4:
2408                 case MONO_TYPE_U4:
2409                 case MONO_TYPE_I:
2410                 case MONO_TYPE_U:
2411                 case MONO_TYPE_PTR:
2412                 case MONO_TYPE_R4:
2413                 case MONO_TYPE_R8:
2414                 case MONO_TYPE_I8:
2415                 case MONO_TYPE_U8:
2416                 /* no conversions necessary */
2417                         break;
2418                 case MONO_TYPE_BOOLEAN:
2419                         /* maybe we need to make sure that it fits within 8 bits */
2420                         break;
2421                 case MONO_TYPE_VALUETYPE: {
2422                         int tmp;
2423
2424                         klass = sig->ret->data.klass;
2425                         if (klass->enumtype) {
2426                                 type = sig->ret->data.klass->enum_basetype->type;
2427                                 goto handle_enum;
2428                         }
2429
2430                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2431                             klass->blittable)
2432                                 break;
2433
2434                         tmp = mono_mb_add_local (mb, sig->ret);
2435                         g_assert (tmp);
2436                         /* load pointer to returned value type */
2437                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2438                         mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
2439                         /* store the address of the source into local variable 0 */
2440                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2441                         /* set dst_ptr */
2442                         mono_mb_emit_ldloc_addr (mb, tmp);
2443                         mono_mb_emit_byte (mb, CEE_STLOC_1);
2444
2445                         /* emit valuetype conversion code */
2446                         emit_struct_conv (mb, sig->ret->data.klass, TRUE);
2447
2448                         mono_mb_emit_ldloc (mb, tmp);
2449                         break;
2450                 }
2451                 case MONO_TYPE_STRING:
2452                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2453                         mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2454                         if (spec) {
2455                                 switch (spec->native) {
2456                                 case MONO_NATIVE_LPWSTR:
2457                                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPWSTR_STR);
2458                                         break;
2459                                 default:
2460                                         g_warning ("marshalling conversion not implemented");
2461                                         g_assert_not_reached ();
2462                                 }
2463                         } else {
2464                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
2465                         }
2466                         break;
2467                 case MONO_TYPE_ARRAY:
2468                 case MONO_TYPE_SZARRAY:
2469                 case MONO_TYPE_CLASS:
2470                 case MONO_TYPE_OBJECT:
2471                         /* fixme: we need conversions here */
2472                         break;
2473                 case MONO_TYPE_CHAR:
2474                         /* fixme: we need conversions here */
2475                         break;
2476                 case MONO_TYPE_TYPEDBYREF:
2477                 case MONO_TYPE_FNPTR:
2478                 default:
2479                         g_warning ("return type 0x%02x unknown", sig->ret->type);       
2480                         g_assert_not_reached ();
2481                 }
2482         }
2483
2484         mono_mb_emit_byte (mb, CEE_RET);
2485
2486         res = mono_mb_create_method (mb, sig, sig->param_count + 16);
2487         mono_mb_free (mb);
2488
2489         g_hash_table_insert (cache, method, res);
2490
2491         for (i = sig->param_count; i >= 0; i--)
2492                 g_free (mspecs [i]);
2493         g_free (mspecs);
2494
2495         return res;
2496 }
2497
2498 /*
2499  * generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld)
2500  */
2501 MonoMethod *
2502 mono_marshal_get_struct_to_ptr (MonoClass *klass)
2503 {
2504         MonoMethodBuilder *mb;
2505         static MonoMethod *stoptr = NULL;
2506         MonoMethod *res;
2507
2508         g_assert (klass != NULL);
2509
2510         if (klass->str_to_ptr)
2511                 return klass->str_to_ptr;
2512
2513         if (!stoptr) 
2514                 stoptr = mono_find_method_by_name (mono_defaults.marshal_class, "StructureToPtr", 3);
2515         g_assert (stoptr);
2516
2517         mb = mono_mb_new (klass, stoptr->name, MONO_WRAPPER_UNKNOWN);
2518
2519         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable) {
2520                 mono_mb_emit_byte (mb, CEE_LDARG_1);
2521                 mono_mb_emit_byte (mb, CEE_LDARG_0);
2522                 mono_mb_emit_icon (mb, sizeof (MonoObject));
2523                 mono_mb_emit_byte (mb, CEE_ADD);
2524                 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
2525                 mono_mb_emit_byte (mb, CEE_PREFIX1);
2526                 mono_mb_emit_byte (mb, CEE_CPBLK);
2527         } else {
2528
2529                 /* allocate local 0 (pointer) src_ptr */
2530                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2531                 /* allocate local 1 (pointer) dst_ptr */
2532                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2533                 /* allocate local 2 (boolean) delete_old */
2534                 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2535                 mono_mb_emit_byte (mb, CEE_LDARG_2);
2536                 mono_mb_emit_byte (mb, CEE_STLOC_2);
2537
2538                 /* initialize src_ptr to point to the start of object data */
2539                 mono_mb_emit_byte (mb, CEE_LDARG_0);
2540                 mono_mb_emit_icon (mb, sizeof (MonoObject));
2541                 mono_mb_emit_byte (mb, CEE_ADD);
2542                 mono_mb_emit_byte (mb, CEE_STLOC_0);
2543
2544                 /* initialize dst_ptr */
2545                 mono_mb_emit_byte (mb, CEE_LDARG_1);
2546                 mono_mb_emit_byte (mb, CEE_STLOC_1);
2547
2548                 emit_struct_conv (mb, klass, FALSE);
2549         }
2550
2551         mono_mb_emit_byte (mb, CEE_RET);
2552
2553         res = mono_mb_create_method (mb, stoptr->signature, 0);
2554         mono_mb_free (mb);
2555
2556         klass->str_to_ptr = res;
2557         return res;
2558 }
2559
2560 /*
2561  * generates IL code for PtrToStructure (IntPtr src, object structure)
2562  */
2563 MonoMethod *
2564 mono_marshal_get_ptr_to_struct (MonoClass *klass)
2565 {
2566         MonoMethodBuilder *mb;
2567         static MonoMethod *ptostr = NULL;
2568         MonoMethod *res;
2569
2570         g_assert (klass != NULL);
2571
2572         if (klass->ptr_to_str)
2573                 return klass->ptr_to_str;
2574
2575         if (!ptostr) 
2576                 ptostr = mono_find_method_by_name (mono_defaults.marshal_class, "PtrToStructure", 2);
2577         g_assert (ptostr);
2578
2579         mb = mono_mb_new (klass, ptostr->name, MONO_WRAPPER_UNKNOWN);
2580
2581         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable) {
2582                 mono_mb_emit_byte (mb, CEE_LDARG_1);
2583                 mono_mb_emit_icon (mb, sizeof (MonoObject));
2584                 mono_mb_emit_byte (mb, CEE_ADD);
2585                 mono_mb_emit_byte (mb, CEE_LDARG_0);
2586                 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
2587                 mono_mb_emit_byte (mb, CEE_PREFIX1);
2588                 mono_mb_emit_byte (mb, CEE_CPBLK);
2589         } else {
2590
2591                 /* allocate local 0 (pointer) src_ptr */
2592                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2593                 /* allocate local 1 (pointer) dst_ptr */
2594                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2595                 
2596                 /* initialize src_ptr to point to the start of object data */
2597                 mono_mb_emit_byte (mb, CEE_LDARG_0);
2598                 mono_mb_emit_byte (mb, CEE_STLOC_0);
2599
2600                 /* initialize dst_ptr */
2601                 mono_mb_emit_byte (mb, CEE_LDARG_1);
2602                 mono_mb_emit_icon (mb, sizeof (MonoObject));
2603                 mono_mb_emit_byte (mb, CEE_ADD);
2604                 mono_mb_emit_byte (mb, CEE_STLOC_1);
2605
2606                 emit_struct_conv (mb, klass, TRUE);
2607         }
2608
2609         mono_mb_emit_byte (mb, CEE_RET);
2610
2611         res = mono_mb_create_method (mb, ptostr->signature, 0);
2612         mono_mb_free (mb);
2613
2614         klass->ptr_to_str = res;
2615         return res;
2616 }
2617
2618 /* FIXME: on win32 we should probably use GlobalAlloc(). */
2619 void*
2620 mono_marshal_alloc (gpointer size) 
2621 {
2622         MONO_ARCH_SAVE_REGS;
2623
2624         return g_try_malloc ((gulong)size);
2625 }
2626
2627 void
2628 mono_marshal_free (gpointer ptr) 
2629 {
2630         MONO_ARCH_SAVE_REGS;
2631
2632         g_free (ptr);
2633 }
2634
2635 void
2636 mono_marshal_free_array (gpointer *ptr, int size) {
2637         int i;
2638
2639         for (i = 0; i < size; i++)
2640                 if (ptr [i])
2641                         g_free (ptr [i]);
2642 }
2643
2644 void *
2645 mono_marshal_realloc (gpointer ptr, gpointer size) 
2646 {
2647         MONO_ARCH_SAVE_REGS;
2648
2649         return g_try_realloc (ptr, (gulong)size);
2650 }
2651
2652 void *
2653 mono_marshal_string_array (MonoArray *array)
2654 {
2655         char **result;
2656         int i, len;
2657
2658         if (!array)
2659                 return NULL;
2660
2661         len = mono_array_length (array);
2662
2663         result = g_malloc (sizeof (char *) * (len + 1));
2664         for (i = 0; i < len; ++i) {
2665                 MonoString *s = (MonoString *)mono_array_get (array, gpointer, i);
2666                 result [i] = s ? mono_string_to_utf8 (s): NULL;
2667         }
2668         /* null terminate the array */
2669         result [i] = NULL;
2670
2671         return result;
2672 }
2673
2674 void
2675 ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArray *src, gint32 start_index,
2676                                                                     gpointer dest, gint32 length)
2677 {
2678         int element_size;
2679         void *source_addr;
2680
2681         MONO_ARCH_SAVE_REGS;
2682
2683         MONO_CHECK_ARG_NULL (src);
2684         MONO_CHECK_ARG_NULL (dest);
2685
2686         g_assert (src->obj.vtable->klass->rank == 1);
2687         g_assert (start_index >= 0);
2688         g_assert (length >= 0);
2689         g_assert (start_index + length <= mono_array_length (src));
2690
2691         element_size = mono_array_element_size (src->obj.vtable->klass);
2692           
2693         source_addr = mono_array_addr_with_size (src, element_size, start_index);
2694
2695         memcpy (dest, source_addr, length * element_size);
2696 }
2697
2698 void
2699 ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer src, gint32 start_index,
2700                                                                       MonoArray *dest, gint32 length)
2701 {
2702         int element_size;
2703         void *dest_addr;
2704
2705         MONO_ARCH_SAVE_REGS;
2706
2707         MONO_CHECK_ARG_NULL (src);
2708         MONO_CHECK_ARG_NULL (dest);
2709
2710         g_assert (dest->obj.vtable->klass->rank == 1);
2711         g_assert (start_index >= 0);
2712         g_assert (length >= 0);
2713         g_assert (start_index + length <= mono_array_length (dest));
2714
2715         element_size = mono_array_element_size (dest->obj.vtable->klass);
2716           
2717         dest_addr = mono_array_addr_with_size (dest, element_size, start_index);
2718
2719         memcpy (dest_addr, src, length * element_size);
2720 }
2721
2722 gpointer
2723 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr, gint32 offset)
2724 {
2725         char *p = ptr;
2726
2727         MONO_ARCH_SAVE_REGS;
2728
2729         return *(gpointer*)(p + offset);
2730 }
2731
2732 unsigned char
2733 ves_icall_System_Runtime_InteropServices_Marshal_ReadByte (gpointer ptr, gint32 offset)
2734 {
2735         char *p = ptr;
2736
2737         MONO_ARCH_SAVE_REGS;
2738
2739         return *(unsigned char*)(p + offset);
2740 }
2741
2742 gint16
2743 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt16 (gpointer ptr, gint32 offset)
2744 {
2745         char *p = ptr;
2746
2747         MONO_ARCH_SAVE_REGS;
2748
2749         return *(gint16*)(p + offset);
2750 }
2751
2752 gint32
2753 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt32 (gpointer ptr, gint32 offset)
2754 {
2755         char *p = ptr;
2756
2757         MONO_ARCH_SAVE_REGS;
2758
2759         return *(gint32*)(p + offset);
2760 }
2761
2762 gint64
2763 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt64 (gpointer ptr, gint32 offset)
2764 {
2765         char *p = ptr;
2766
2767         MONO_ARCH_SAVE_REGS;
2768
2769         return *(gint64*)(p + offset);
2770 }
2771
2772 void
2773 ves_icall_System_Runtime_InteropServices_Marshal_WriteByte (gpointer ptr, gint32 offset, unsigned char val)
2774 {
2775         char *p = ptr;
2776
2777         MONO_ARCH_SAVE_REGS;
2778
2779         *(unsigned char*)(p + offset) = val;
2780 }
2781
2782 void
2783 ves_icall_System_Runtime_InteropServices_Marshal_WriteIntPtr (gpointer ptr, gint32 offset, gpointer val)
2784 {
2785         char *p = ptr;
2786
2787         MONO_ARCH_SAVE_REGS;
2788
2789         *(gpointer*)(p + offset) = val;
2790 }
2791
2792 void
2793 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt16 (gpointer ptr, gint32 offset, gint16 val)
2794 {
2795         char *p = ptr;
2796
2797         MONO_ARCH_SAVE_REGS;
2798
2799         *(gint16*)(p + offset) = val;
2800 }
2801
2802 void
2803 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt32 (gpointer ptr, gint32 offset, gint32 val)
2804 {
2805         char *p = ptr;
2806
2807         MONO_ARCH_SAVE_REGS;
2808
2809         *(gint32*)(p + offset) = val;
2810 }
2811
2812 void
2813 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt64 (gpointer ptr, gint32 offset, gint64 val)
2814 {
2815         char *p = ptr;
2816
2817         MONO_ARCH_SAVE_REGS;
2818
2819         *(gint64*)(p + offset) = val;
2820 }
2821
2822 MonoString *
2823 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (char *ptr)
2824 {
2825         MONO_ARCH_SAVE_REGS;
2826
2827         return mono_string_new (mono_domain_get (), ptr);
2828 }
2829
2830 MonoString *
2831 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len (char *ptr, gint32 len)
2832 {
2833         MONO_ARCH_SAVE_REGS;
2834
2835         return mono_string_new_len (mono_domain_get (), ptr, len);
2836 }
2837
2838 MonoString *
2839 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni (guint16 *ptr)
2840 {
2841         MonoDomain *domain = mono_domain_get (); 
2842         int len = 0;
2843         guint16 *t = ptr;
2844
2845         MONO_ARCH_SAVE_REGS;
2846
2847         while (*t++)
2848                 len++;
2849
2850         return mono_string_new_utf16 (domain, ptr, len);
2851 }
2852
2853 MonoString *
2854 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len (guint16 *ptr, gint32 len)
2855 {
2856         MonoDomain *domain = mono_domain_get (); 
2857
2858         MONO_ARCH_SAVE_REGS;
2859
2860         return mono_string_new_utf16 (domain, ptr, len);
2861 }
2862
2863 MonoString *
2864 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR (gpointer ptr)
2865 {
2866         MONO_ARCH_SAVE_REGS;
2867
2868         g_warning ("PtrToStringBSTR not implemented");
2869         g_assert_not_reached ();
2870
2871         return NULL;
2872 }
2873
2874 guint32 
2875 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
2876 {
2877         MONO_ARCH_SAVE_REGS;
2878
2879         return (GetLastError ());
2880 }
2881
2882 guint32 
2883 ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype)
2884 {
2885         MonoClass *klass;
2886
2887         MONO_ARCH_SAVE_REGS;
2888
2889         MONO_CHECK_ARG_NULL (rtype);
2890
2891         klass = mono_class_from_mono_type (rtype->type);
2892
2893         return mono_class_native_size (klass, NULL);
2894 }
2895
2896 void
2897 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old)
2898 {
2899         MonoMethod *method;
2900         gpointer pa [3];
2901
2902         MONO_ARCH_SAVE_REGS;
2903
2904         MONO_CHECK_ARG_NULL (obj);
2905         MONO_CHECK_ARG_NULL (dst);
2906
2907         method = mono_marshal_get_struct_to_ptr (obj->vtable->klass);
2908
2909         pa [0] = obj;
2910         pa [1] = &dst;
2911         pa [2] = &delete_old;
2912
2913         mono_runtime_invoke (method, NULL, pa, NULL);
2914 }
2915
2916 void
2917 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, MonoObject *dst)
2918 {
2919         MonoMethod *method;
2920         gpointer pa [2];
2921
2922         MONO_ARCH_SAVE_REGS;
2923
2924         MONO_CHECK_ARG_NULL (src);
2925         MONO_CHECK_ARG_NULL (dst);
2926
2927         method = mono_marshal_get_ptr_to_struct (dst->vtable->klass);
2928
2929         pa [0] = &src;
2930         pa [1] = dst;
2931
2932         mono_runtime_invoke (method, NULL, pa, NULL);
2933 }
2934
2935 MonoObject *
2936 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer src, MonoReflectionType *type)
2937 {
2938         MonoDomain *domain = mono_domain_get (); 
2939         MonoObject *res;
2940
2941         MONO_ARCH_SAVE_REGS;
2942
2943         MONO_CHECK_ARG_NULL (src);
2944         MONO_CHECK_ARG_NULL (type);
2945
2946         res = mono_object_new (domain, mono_class_from_mono_type (type->type));
2947
2948         ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (src, res);
2949
2950         return res;
2951 }
2952
2953 int
2954 ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *type, MonoString *field_name)
2955 {
2956         MonoMarshalType *info;
2957         MonoClass *klass;
2958         char *fname;
2959         int i;
2960
2961         MONO_ARCH_SAVE_REGS;
2962
2963         MONO_CHECK_ARG_NULL (type);
2964         MONO_CHECK_ARG_NULL (field_name);
2965
2966         fname = mono_string_to_utf8 (field_name);
2967         klass = mono_class_from_mono_type (type->type);
2968
2969         info = mono_marshal_load_type_info (klass);     
2970         
2971         for (i = 0; i < klass->field.count; ++i) {
2972                 if (*fname == *klass->fields [i].name && 
2973                     strcmp (fname, klass->fields [i].name) == 0)
2974                         break;
2975         }
2976         g_free (fname);
2977
2978         mono_assert (i < klass->field.count);
2979
2980         return info->fields [i].offset;
2981 }
2982
2983 gpointer
2984 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString *string)
2985 {
2986         MONO_ARCH_SAVE_REGS;
2987
2988         return mono_string_to_utf8 (string);
2989 }
2990
2991 gpointer
2992 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni (MonoString *string)
2993 {
2994         MONO_ARCH_SAVE_REGS;
2995
2996         return g_memdup (mono_string_chars (string), mono_string_length (string)*2);
2997 }
2998
2999 static void
3000 mono_struct_delete_old (MonoClass *klass, char *ptr)
3001 {
3002         MonoMarshalType *info;
3003         int i;
3004
3005         info = mono_marshal_load_type_info (klass);
3006
3007         for (i = 0; i < info->num_fields; i++) {
3008                 MonoMarshalNative ntype;
3009                 MonoMarshalConv conv;
3010                 MonoType *ftype = info->fields [i].field->type;
3011                 char *cpos;
3012
3013                 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
3014                         continue;
3015
3016                 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, 
3017                                                 klass->unicode, &conv);
3018                         
3019                 cpos = ptr + info->fields [i].offset;
3020
3021                 switch (conv) {
3022                 case MONO_MARSHAL_CONV_NONE:
3023                         if (MONO_TYPE_ISSTRUCT (ftype)) {
3024                                 mono_struct_delete_old (ftype->data.klass, cpos);
3025                                 continue;
3026                         }
3027                         break;
3028                 case MONO_MARSHAL_CONV_STR_LPWSTR:
3029                 case MONO_MARSHAL_CONV_STR_LPSTR:
3030                 case MONO_MARSHAL_CONV_STR_LPTSTR:
3031                 case MONO_MARSHAL_CONV_STR_BSTR:
3032                 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
3033                 case MONO_MARSHAL_CONV_STR_TBSTR:
3034                         g_free (*(gpointer *)cpos);
3035                         break;
3036                 default:
3037                         continue;
3038                 }
3039         }
3040 }
3041
3042 void
3043 ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure (gpointer src, MonoReflectionType *type)
3044 {
3045         MonoClass *klass;
3046
3047         MONO_ARCH_SAVE_REGS;
3048
3049         MONO_CHECK_ARG_NULL (src);
3050         MONO_CHECK_ARG_NULL (type);
3051
3052         klass = mono_class_from_mono_type (type->type);
3053
3054         mono_struct_delete_old (klass, (char *)src);
3055 }
3056