Thu Jan 9 15:54:53 CET 2003 Paolo Molaro <lupus@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         for (i = 0; i < info->num_fields; i++) {
784                 MonoMarshalNative ntype;
785                 MonoMarshalConv conv;
786                 MonoType *ftype = info->fields [i].field->type;
787                 int msize = 0;
788                 int usize = 0;
789                 gboolean last_field = i < (info->num_fields -1) ? 0 : 1;
790
791                 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
792                         continue;
793
794                 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, klass->unicode, &conv);
795                         
796                 if (last_field) {
797                         msize = klass->instance_size - info->fields [i].field->offset;
798                         usize = info->native_size - info->fields [i].offset;
799                 } else {
800                         msize = klass->fields [i + 1].offset - info->fields [i].field->offset;
801                         usize = info->fields [i + 1].offset - info->fields [i].offset;
802                 }
803                 g_assert (msize > 0 && usize > 0);
804
805                 switch (conv) {
806                 case MONO_MARSHAL_CONV_NONE: {
807                         int t;
808
809                         if (ftype->byref || ftype->type == MONO_TYPE_I ||
810                             ftype->type == MONO_TYPE_U) {
811                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
812                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
813                                 mono_mb_emit_byte (mb, CEE_LDIND_I);
814                                 mono_mb_emit_byte (mb, CEE_STIND_I);
815                                 break;
816                         }
817
818                         t = ftype->type;
819                 handle_enum:
820                         switch (t) {
821                         case MONO_TYPE_I4:
822                         case MONO_TYPE_U4:
823                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
824                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
825                                 mono_mb_emit_byte (mb, CEE_LDIND_I4);
826                                 mono_mb_emit_byte (mb, CEE_STIND_I4);
827                                 break;
828                         case MONO_TYPE_I1:
829                         case MONO_TYPE_U1:
830                         case MONO_TYPE_BOOLEAN:
831                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
832                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
833                                 mono_mb_emit_byte (mb, CEE_LDIND_I1);
834                                 mono_mb_emit_byte (mb, CEE_STIND_I1);
835                                 break;
836                         case MONO_TYPE_I2:
837                         case MONO_TYPE_U2:
838                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
839                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
840                                 mono_mb_emit_byte (mb, CEE_LDIND_I2);
841                                 mono_mb_emit_byte (mb, CEE_STIND_I2);
842                                 break;
843                         case MONO_TYPE_I8:
844                         case MONO_TYPE_U8:
845                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
846                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
847                                 mono_mb_emit_byte (mb, CEE_LDIND_I8);
848                                 mono_mb_emit_byte (mb, CEE_STIND_I8);
849                                 break;
850                         case MONO_TYPE_R4:
851                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
852                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
853                                 mono_mb_emit_byte (mb, CEE_LDIND_R4);
854                                 mono_mb_emit_byte (mb, CEE_STIND_R4);
855                                 break;
856                         case MONO_TYPE_R8:
857                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
858                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
859                                 mono_mb_emit_byte (mb, CEE_LDIND_R8);
860                                 mono_mb_emit_byte (mb, CEE_STIND_R8);
861                                 break;
862                         case MONO_TYPE_VALUETYPE:
863                                 if (ftype->data.klass->enumtype) {
864                                         t = ftype->data.klass->enum_basetype->type;
865                                         goto handle_enum;
866                                 }
867                                 emit_struct_conv (mb, ftype->data.klass, to_object);
868                                 continue;
869                         default:
870                                 g_warning ("marshaling type %02x not implemented", ftype->type);
871                                 g_assert_not_reached ();
872                         }
873                         break;
874                 }
875                 default:
876                         if (to_object) 
877                                 emit_ptr_to_str_conv (mb, ftype, conv, usize, msize);
878                         else
879                                 emit_str_to_ptr_conv (mb, ftype, conv, usize, msize);   
880                 }
881                 
882                 if (to_object) {
883                         mono_mb_emit_add_to_local (mb, 0, usize);
884                         mono_mb_emit_add_to_local (mb, 1, msize);
885                 } else {
886                         mono_mb_emit_add_to_local (mb, 0, msize);
887                         mono_mb_emit_add_to_local (mb, 1, usize);
888                 }                               
889         }
890 }
891
892 static MonoAsyncResult *
893 mono_delegate_begin_invoke (MonoDelegate *delegate, gpointer *params)
894 {
895         MonoMethodMessage *msg;
896         MonoDelegate *async_callback;
897         MonoObject *state;
898         MonoMethod *im;
899         MonoClass *klass;
900         MonoMethod *method = NULL;
901         int i;
902
903         g_assert (delegate);
904
905         klass = delegate->object.vtable->klass;
906
907         method = mono_get_delegate_invoke (klass);
908         for (i = 0; i < klass->method.count; ++i) {
909                 if (klass->methods [i]->name[0] == 'B' && 
910                     !strcmp ("BeginInvoke", klass->methods [i]->name)) {
911                         method = klass->methods [i];
912                         break;
913                 }
914         }
915
916         g_assert (method != NULL);
917
918         im = mono_get_delegate_invoke (method->klass);
919         
920         msg = mono_method_call_message_new (method, params, im, &async_callback, &state);
921
922         return mono_thread_pool_add ((MonoObject *)delegate, msg, async_callback, state);
923 }
924
925 static int
926 mono_mb_emit_save_args (MonoMethodBuilder *mb, MonoMethodSignature *sig, gboolean save_this)
927 {
928         int i, params_var, tmp_var;
929
930         /* allocate local (pointer) *params[] */
931         params_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
932         /* allocate local (pointer) tmp */
933         tmp_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
934
935         /* alloate space on stack to store an array of pointers to the arguments */
936         mono_mb_emit_icon (mb, sizeof (gpointer) * (sig->param_count + 1));
937         mono_mb_emit_byte (mb, CEE_PREFIX1);
938         mono_mb_emit_byte (mb, CEE_LOCALLOC);
939         mono_mb_emit_stloc (mb, params_var);
940
941         /* tmp = params */
942         mono_mb_emit_ldloc (mb, params_var);
943         mono_mb_emit_stloc (mb, tmp_var);
944
945         if (save_this && sig->hasthis) {
946                 mono_mb_emit_ldloc (mb, tmp_var);
947                 mono_mb_emit_ldarg_addr (mb, 0);
948                 mono_mb_emit_byte (mb, CEE_STIND_I);
949                 /* tmp = tmp + sizeof (gpointer) */
950                 if (sig->param_count)
951                         mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
952
953         }
954
955         for (i = 0; i < sig->param_count; i++) {
956                 mono_mb_emit_ldloc (mb, tmp_var);
957                 mono_mb_emit_ldarg_addr (mb, i + sig->hasthis);
958                 mono_mb_emit_byte (mb, CEE_STIND_I);
959                 /* tmp = tmp + sizeof (gpointer) */
960                 if (i < (sig->param_count - 1))
961                         mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
962         }
963
964         return params_var;
965 }
966
967 static char*
968 mono_signature_to_name (MonoMethodSignature *sig, const char *prefix)
969 {
970         int i;
971         char *result;
972         GString *res = g_string_new ("");
973
974         if (prefix) {
975                 g_string_append (res, prefix);
976                 g_string_append_c (res, '_');
977         }
978
979         mono_type_get_desc (res, sig->ret, FALSE);
980
981         for (i = 0; i < sig->param_count; ++i) {
982                 g_string_append_c (res, '_');
983                 mono_type_get_desc (res, sig->params [i], FALSE);
984         }
985         result = res->str;
986         g_string_free (res, FALSE);
987         return result;
988 }
989
990 MonoMethod *
991 mono_marshal_get_delegate_begin_invoke (MonoMethod *method)
992 {
993         MonoMethodSignature *sig;
994         static MonoMethodSignature *csig = NULL;
995         MonoMethodBuilder *mb;
996         MonoMethod *res;
997         GHashTable *cache;
998         int params_var;
999         char *name;
1000
1001         g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1002                   !strcmp (method->name, "BeginInvoke"));
1003
1004         sig = method->signature;
1005
1006         cache = method->klass->image->delegate_begin_invoke_cache;
1007         if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1008                 return res;
1009
1010         g_assert (sig->hasthis);
1011
1012         if (!csig) {
1013                 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1014                 csig = g_malloc0 (sigsize);
1015
1016                 /* MonoAsyncResult * begin_invoke (MonoDelegate *delegate, gpointer params[]) */
1017                 csig->param_count = 2;
1018                 csig->ret = &mono_defaults.object_class->byval_arg;
1019                 csig->params [0] = &mono_defaults.object_class->byval_arg;
1020                 csig->params [1] = &mono_defaults.int_class->byval_arg;
1021         }
1022
1023         name = mono_signature_to_name (sig, "begin_invoke");
1024         mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_BEGIN_INVOKE);
1025         g_free (name);
1026
1027         mb->method->save_lmf = 1;
1028
1029         params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1030
1031         mono_mb_emit_ldarg (mb, 0);
1032         mono_mb_emit_ldloc (mb, params_var);
1033         mono_mb_emit_native_call (mb, csig, mono_delegate_begin_invoke);
1034         mono_mb_emit_byte (mb, CEE_RET);
1035
1036         res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1037         mono_mb_free (mb);
1038         g_hash_table_insert (cache, sig, res);
1039         return res;
1040 }
1041
1042 static MonoObject *
1043 mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params)
1044 {
1045         MonoDomain *domain = mono_domain_get ();
1046         MonoAsyncResult *ares;
1047         MonoMethod *method = NULL;
1048         MonoMethodSignature *sig;
1049         MonoMethodMessage *msg;
1050         MonoObject *res, *exc;
1051         MonoArray *out_args;
1052         MonoClass *klass;
1053         int i;
1054
1055         g_assert (delegate);
1056
1057         if (!delegate->method_info || !delegate->method_info->method)
1058                 g_assert_not_reached ();
1059
1060         klass = delegate->object.vtable->klass;
1061
1062         for (i = 0; i < klass->method.count; ++i) {
1063                 if (klass->methods [i]->name[0] == 'E' && 
1064                     !strcmp ("EndInvoke", klass->methods [i]->name)) {
1065                         method = klass->methods [i];
1066                         break;
1067                 }
1068         }
1069
1070         g_assert (method != NULL);
1071
1072         sig = method->signature;
1073
1074         msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1075
1076         ares = mono_array_get (msg->args, gpointer, sig->param_count - 1);
1077         g_assert (ares);
1078
1079         res = mono_thread_pool_finish (ares, &out_args, &exc);
1080
1081         if (exc) {
1082                 char *strace = mono_string_to_utf8 (((MonoException*)exc)->stack_trace);
1083                 char  *tmp;
1084                 tmp = g_strdup_printf ("%s\nException Rethrown at:\n", strace);
1085                 g_free (strace);        
1086                 ((MonoException*)exc)->stack_trace = mono_string_new (domain, tmp);
1087                 g_free (tmp);
1088                 mono_raise_exception ((MonoException*)exc);
1089         }
1090
1091         mono_method_return_message_restore (method, params, out_args);
1092         return res;
1093 }
1094
1095 static void
1096 mono_mb_emit_restore_result (MonoMethodBuilder *mb, MonoType *return_type)
1097 {
1098         if (return_type->byref)
1099                 return_type = &mono_defaults.int_class->byval_arg;
1100         else if (return_type->type == MONO_TYPE_VALUETYPE && return_type->data.klass->enumtype)
1101                 return_type = return_type->data.klass->enum_basetype;
1102
1103         switch (return_type->type) {
1104         case MONO_TYPE_VOID:
1105                 g_assert_not_reached ();
1106                 break;
1107         case MONO_TYPE_STRING:
1108         case MONO_TYPE_CLASS: 
1109         case MONO_TYPE_OBJECT: 
1110         case MONO_TYPE_ARRAY: 
1111         case MONO_TYPE_SZARRAY: 
1112                 /* nothing to do */
1113                 break;
1114         case MONO_TYPE_U1:
1115         case MONO_TYPE_BOOLEAN:
1116                 mono_mb_emit_byte (mb, CEE_UNBOX);
1117                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1118                 mono_mb_emit_byte (mb, CEE_LDIND_U1);
1119                 break;
1120         case MONO_TYPE_I1:
1121                 mono_mb_emit_byte (mb, CEE_UNBOX);
1122                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1123                 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1124                 break;
1125         case MONO_TYPE_U2:
1126         case MONO_TYPE_CHAR:
1127                 mono_mb_emit_byte (mb, CEE_UNBOX);
1128                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1129                 mono_mb_emit_byte (mb, CEE_LDIND_U2);
1130                 break;
1131         case MONO_TYPE_I2:
1132                 mono_mb_emit_byte (mb, CEE_UNBOX);
1133                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1134                 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1135                 break;
1136         case MONO_TYPE_I:
1137         case MONO_TYPE_U:
1138                 mono_mb_emit_byte (mb, CEE_UNBOX);
1139                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1140                 mono_mb_emit_byte (mb, CEE_LDIND_I);
1141                 break;
1142         case MONO_TYPE_I4:
1143                 mono_mb_emit_byte (mb, CEE_UNBOX);
1144                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1145                 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1146                 break;
1147         case MONO_TYPE_U4:
1148                 mono_mb_emit_byte (mb, CEE_UNBOX);
1149                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1150                 mono_mb_emit_byte (mb, CEE_LDIND_U4);
1151                 break;
1152         case MONO_TYPE_U8:
1153         case MONO_TYPE_I8:
1154                 mono_mb_emit_byte (mb, CEE_UNBOX);
1155                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1156                 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1157                 break;
1158         case MONO_TYPE_R4:
1159                 mono_mb_emit_byte (mb, CEE_UNBOX);
1160                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1161                 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1162                 break;
1163         case MONO_TYPE_R8:
1164                 mono_mb_emit_byte (mb, CEE_UNBOX);
1165                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1166                 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1167                 break;
1168         case MONO_TYPE_VALUETYPE: {
1169                 int class;
1170                 mono_mb_emit_byte (mb, CEE_UNBOX);
1171                 class = mono_mb_add_data (mb, mono_class_from_mono_type (return_type));
1172                 mono_mb_emit_i4 (mb, class);
1173                 mono_mb_emit_byte (mb, CEE_LDOBJ);
1174                 mono_mb_emit_i4 (mb, class);
1175                 break;
1176         }
1177         default:
1178                 g_warning ("type 0x%x not handled", return_type->type);
1179                 g_assert_not_reached ();
1180         }
1181
1182         mono_mb_emit_byte (mb, CEE_RET);
1183 }
1184
1185 MonoMethod *
1186 mono_marshal_get_delegate_end_invoke (MonoMethod *method)
1187 {
1188         MonoMethodSignature *sig;
1189         static MonoMethodSignature *csig = NULL;
1190         MonoMethodBuilder *mb;
1191         MonoMethod *res;
1192         GHashTable *cache;
1193         int params_var;
1194         char *name;
1195
1196         g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1197                   !strcmp (method->name, "EndInvoke"));
1198
1199         sig = method->signature;
1200
1201         cache = method->klass->image->delegate_end_invoke_cache;
1202         if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1203                 return res;
1204
1205         g_assert (sig->hasthis);
1206
1207         if (!csig) {
1208                 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1209                 csig = g_malloc0 (sigsize);
1210
1211                 /* MonoObject *end_invoke (MonoDelegate *delegate, gpointer params[]) */
1212                 csig->param_count = 2;
1213                 csig->ret = &mono_defaults.object_class->byval_arg;
1214                 csig->params [0] = &mono_defaults.object_class->byval_arg;
1215                 csig->params [1] = &mono_defaults.int_class->byval_arg;
1216         }
1217
1218         name = mono_signature_to_name (sig, "end_invoke");
1219         mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_END_INVOKE);
1220         g_free (name);
1221
1222         mb->method->save_lmf = 1;
1223
1224         params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1225
1226         mono_mb_emit_ldarg (mb, 0);
1227         mono_mb_emit_ldloc (mb, params_var);
1228         mono_mb_emit_native_call (mb, csig, mono_delegate_end_invoke);
1229
1230         if (sig->ret->type == MONO_TYPE_VOID) {
1231                 mono_mb_emit_byte (mb, CEE_POP);
1232                 mono_mb_emit_byte (mb, CEE_RET);
1233         } else
1234                 mono_mb_emit_restore_result (mb, sig->ret);
1235
1236         res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1237         mono_mb_free (mb);
1238         g_hash_table_insert (cache, sig, res);
1239
1240         return res;
1241 }
1242
1243 static MonoObject *
1244 mono_remoting_wrapper (MonoMethod *method, gpointer *params)
1245 {
1246         MonoMethodMessage *msg;
1247         MonoTransparentProxy *this;
1248         MonoObject *res, *exc;
1249         MonoArray *out_args;
1250
1251         this = *((MonoTransparentProxy **)params [0]);
1252
1253         g_assert (this);
1254         g_assert (((MonoObject *)this)->vtable->klass == mono_defaults.transparent_proxy_class);
1255         
1256         /* skip the this pointer */
1257         params++;
1258
1259         msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1260
1261         res = mono_remoting_invoke ((MonoObject *)this->rp, msg, &exc, &out_args);
1262
1263         if (exc)
1264                 mono_raise_exception ((MonoException *)exc);
1265
1266         mono_method_return_message_restore (method, params, out_args);
1267
1268         return res;
1269
1270
1271 MonoMethod *
1272 mono_marshal_get_remoting_invoke (MonoMethod *method)
1273 {
1274         MonoMethodSignature *sig;
1275         static MonoMethodSignature *csig = NULL;
1276         MonoMethodBuilder *mb;
1277         MonoMethod *res;
1278         GHashTable *cache;
1279         int params_var;
1280
1281         g_assert (method);
1282
1283         if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE)
1284                 return method;
1285
1286         sig = method->signature;
1287
1288         /* we cant remote methods without this pointer */
1289         if (!sig->hasthis)
1290                 return method;
1291
1292         cache = method->klass->image->remoting_invoke_cache;
1293         if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1294                 return res;
1295
1296         if (!csig) {
1297                 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1298                 csig = g_malloc0 (sigsize);
1299
1300                 /* MonoObject *remoting_wrapper (MonoMethod *method, gpointer params[]) */
1301                 csig->param_count = 2;
1302                 csig->ret = &mono_defaults.object_class->byval_arg;
1303                 csig->params [0] = &mono_defaults.int_class->byval_arg;
1304                 csig->params [1] = &mono_defaults.int_class->byval_arg;
1305         }
1306
1307         mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE);
1308         mb->method->save_lmf = 1;
1309
1310         params_var = mono_mb_emit_save_args (mb, sig, TRUE);
1311
1312         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1313         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1314         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
1315         mono_mb_emit_ldloc (mb, params_var);
1316         mono_mb_emit_native_call (mb, csig, mono_remoting_wrapper);
1317
1318         if (sig->ret->type == MONO_TYPE_VOID)
1319                 mono_mb_emit_byte (mb, CEE_POP);
1320         else
1321                 mono_mb_emit_restore_result (mb, sig->ret);
1322
1323         res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1324         mono_mb_free (mb);
1325         g_hash_table_insert (cache, method, res);
1326         return res;
1327 }
1328
1329 /*
1330  * the returned method invokes all methods in a multicast delegate 
1331  */
1332 MonoMethod *
1333 mono_marshal_get_delegate_invoke (MonoMethod *method)
1334 {
1335         MonoMethodSignature *sig, *static_sig;
1336         int i, sigsize;
1337         MonoMethodBuilder *mb;
1338         MonoMethod *res;
1339         GHashTable *cache;
1340         int pos0, pos1;
1341         char *name;
1342
1343         g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1344                   !strcmp (method->name, "Invoke"));
1345                 
1346         sig = method->signature;
1347
1348         cache = method->klass->image->delegate_invoke_cache;
1349         if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1350                 return res;
1351
1352         sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1353         static_sig = g_memdup (sig, sigsize);
1354         static_sig->hasthis = 0;
1355
1356         name = mono_signature_to_name (sig, "invoke");
1357         mb = mono_mb_new (mono_defaults.multicastdelegate_class, name,  MONO_WRAPPER_DELEGATE_INVOKE);
1358         g_free (name);
1359
1360         /* allocate local 0 (object) */
1361         mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1362
1363         g_assert (sig->hasthis);
1364         
1365         /*
1366          * if (prev != null)
1367          *      prev.Invoke( args .. );
1368          * return this.<target>( args .. );
1369          */
1370
1371         /* get this->prev */
1372         mono_mb_emit_ldarg (mb, 0);
1373         mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoMulticastDelegate, prev));
1374         mono_mb_emit_byte (mb, CEE_LDIND_I );
1375         mono_mb_emit_stloc (mb, 0);
1376
1377         /* if prev != null */
1378         mono_mb_emit_ldloc (mb, 0);
1379         mono_mb_emit_byte (mb, CEE_BRFALSE);
1380
1381         pos0 = mb->pos;
1382         mono_mb_emit_i4 (mb, 0);
1383
1384         /* then recurse */
1385         mono_mb_emit_ldloc (mb, 0);
1386         for (i = 0; i < sig->param_count; i++)
1387                 mono_mb_emit_ldarg (mb, i + 1);
1388         mono_mb_emit_managed_call (mb, method, method->signature);
1389         if (sig->ret->type != MONO_TYPE_VOID)
1390                 mono_mb_emit_byte (mb, CEE_POP);
1391
1392         /* continued or prev == null */
1393         mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1394
1395         /* get this->target */
1396         mono_mb_emit_ldarg (mb, 0);
1397         mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, target));
1398         mono_mb_emit_byte (mb, CEE_LDIND_I );
1399         mono_mb_emit_stloc (mb, 0);
1400
1401         /* if target != null */
1402         mono_mb_emit_ldloc (mb, 0);
1403         mono_mb_emit_byte (mb, CEE_BRFALSE);
1404         pos0 = mb->pos;
1405         mono_mb_emit_i4 (mb, 0);
1406         
1407         /* then call this->method_ptr nonstatic */
1408         mono_mb_emit_ldloc (mb, 0); 
1409         for (i = 0; i < sig->param_count; ++i)
1410                 mono_mb_emit_ldarg (mb, i + 1);
1411         mono_mb_emit_ldarg (mb, 0);
1412         mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1413         mono_mb_emit_byte (mb, CEE_LDIND_I );
1414         mono_mb_emit_byte (mb, CEE_CALLI);
1415         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
1416
1417         mono_mb_emit_byte (mb, CEE_BR);
1418         pos1 = mb->pos;
1419         mono_mb_emit_i4 (mb, 0);
1420
1421         /* else [target == null] call this->method_ptr static */
1422         mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1423
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, static_sig));
1431
1432         /* return */
1433         mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
1434         mono_mb_emit_byte (mb, CEE_RET);
1435
1436         res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1437         mono_mb_free (mb);
1438
1439         g_hash_table_insert (cache, sig, res);
1440
1441         return res;     
1442 }
1443
1444 /*
1445  * generates IL code for the runtime invoke function 
1446  * MonoObject *runtime_invoke (MonoObject *this, void **params, MonoObject **exc)
1447  *
1448  * we also catch exceptions if exc != null
1449  */
1450 MonoMethod *
1451 mono_marshal_get_runtime_invoke (MonoMethod *method)
1452 {
1453         MonoMethodSignature *sig, *csig;
1454         MonoExceptionClause *clause;
1455         MonoMethodHeader *header;
1456         MonoMethodBuilder *mb;
1457         MonoMethod *res;
1458         GHashTable *cache;
1459         static MonoString *string_dummy = NULL;
1460         int i, pos, sigsize;
1461
1462         g_assert (method);
1463
1464         cache = method->klass->image->runtime_invoke_cache;
1465         if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1466                 return res;
1467         
1468         /* to make it work with our special string constructors */
1469         if (!string_dummy)
1470                 string_dummy = mono_string_new_wrapper ("dummy");
1471
1472         sig = method->signature;
1473
1474         sigsize = sizeof (MonoMethodSignature) + 3 * sizeof (MonoType *);
1475         csig = g_malloc0 (sigsize);
1476
1477         csig->param_count = 3;
1478         csig->ret = &mono_defaults.object_class->byval_arg;
1479         csig->params [0] = &mono_defaults.object_class->byval_arg;
1480         csig->params [1] = &mono_defaults.int_class->byval_arg;
1481         csig->params [2] = &mono_defaults.int_class->byval_arg;
1482
1483         mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_RUNTIME_INVOKE);
1484
1485         /* allocate local 0 (object) tmp */
1486         mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1487         /* allocate local 1 (object) exc */
1488         mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1489
1490         /* cond set *exc to null */
1491         mono_mb_emit_byte (mb, CEE_LDARG_2);
1492         mono_mb_emit_byte (mb, CEE_BRFALSE_S);
1493         mono_mb_emit_byte (mb, 3);      
1494         mono_mb_emit_byte (mb, CEE_LDARG_2);
1495         mono_mb_emit_byte (mb, CEE_LDNULL);
1496         mono_mb_emit_byte (mb, CEE_STIND_I);
1497
1498         if (sig->hasthis) {
1499                 if (method->string_ctor) {
1500                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1501                         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1502                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, string_dummy));
1503                 } else {
1504                         mono_mb_emit_ldarg (mb, 0);
1505                         if (method->klass->valuetype) {
1506                                 mono_mb_emit_byte (mb, CEE_UNBOX);
1507                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method->klass));
1508                         } 
1509                 }
1510         }
1511
1512         for (i = 0; i < sig->param_count; i++) {
1513                 MonoType *t = sig->params [i];
1514                 int type;
1515
1516                 mono_mb_emit_ldarg (mb, 1);
1517                 if (i) {
1518                         mono_mb_emit_icon (mb, sizeof (gpointer) * i);
1519                         mono_mb_emit_byte (mb, CEE_ADD);
1520                 }
1521                 mono_mb_emit_byte (mb, CEE_LDIND_I);
1522
1523                 if (t->byref)
1524                         continue;
1525
1526                 type = sig->params [i]->type;
1527 handle_enum:
1528                 switch (type) {
1529                 case MONO_TYPE_I1:
1530                         mono_mb_emit_byte (mb, CEE_LDIND_I1);
1531                         break;
1532                 case MONO_TYPE_BOOLEAN:
1533                 case MONO_TYPE_U1:
1534                         mono_mb_emit_byte (mb, CEE_LDIND_U1);
1535                         break;
1536                 case MONO_TYPE_I2:
1537                         mono_mb_emit_byte (mb, CEE_LDIND_I2);
1538                         break;
1539                 case MONO_TYPE_U2:
1540                 case MONO_TYPE_CHAR:
1541                         mono_mb_emit_byte (mb, CEE_LDIND_U2);
1542                         break;
1543                 case MONO_TYPE_I:
1544                 case MONO_TYPE_U:
1545                         mono_mb_emit_byte (mb, CEE_LDIND_I);
1546                         break;
1547                 case MONO_TYPE_I4:
1548                         mono_mb_emit_byte (mb, CEE_LDIND_I4);
1549                         break;
1550                 case MONO_TYPE_U4:
1551                         mono_mb_emit_byte (mb, CEE_LDIND_U4);
1552                         break;
1553                 case MONO_TYPE_R4:
1554                         mono_mb_emit_byte (mb, CEE_LDIND_R4);
1555                         break;
1556                 case MONO_TYPE_R8:
1557                         mono_mb_emit_byte (mb, CEE_LDIND_R8);
1558                         break;
1559                 case MONO_TYPE_I8:
1560                 case MONO_TYPE_U8:
1561                         mono_mb_emit_byte (mb, CEE_LDIND_I8);
1562                         break;
1563                 case MONO_TYPE_STRING:
1564                 case MONO_TYPE_CLASS:  
1565                 case MONO_TYPE_ARRAY:
1566                 case MONO_TYPE_PTR:
1567                 case MONO_TYPE_SZARRAY:
1568                 case MONO_TYPE_OBJECT:
1569                         /* do nothing */
1570                         break;
1571                 case MONO_TYPE_VALUETYPE:
1572                         if (t->data.klass->enumtype) {
1573                                 type = t->data.klass->enum_basetype->type;
1574                                 goto handle_enum;
1575                         }
1576                         mono_mb_emit_byte (mb, CEE_LDOBJ);
1577                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, t->data.klass));
1578                         break;
1579                 default:
1580                         g_assert_not_reached ();
1581                 }               
1582         }
1583
1584         if (method->string_ctor) {
1585                 MonoMethodSignature *strsig;
1586
1587                 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1588                 strsig = g_memdup (sig, sigsize);
1589                 strsig->ret = &mono_defaults.string_class->byval_arg;
1590
1591                 mono_mb_emit_managed_call (mb, method, strsig);         
1592         } else 
1593                 mono_mb_emit_managed_call (mb, method, NULL);
1594
1595         if (sig->ret->byref) {
1596                 /* fixme: */
1597                 g_assert_not_reached ();
1598         }
1599
1600
1601         switch (sig->ret->type) {
1602         case MONO_TYPE_VOID:
1603                 if (!method->string_ctor)
1604                         mono_mb_emit_byte (mb, CEE_LDNULL);
1605                 break;
1606         case MONO_TYPE_BOOLEAN:
1607         case MONO_TYPE_CHAR:
1608         case MONO_TYPE_I1:
1609         case MONO_TYPE_U1:
1610         case MONO_TYPE_I2:
1611         case MONO_TYPE_U2:
1612         case MONO_TYPE_I4:
1613         case MONO_TYPE_U4:
1614         case MONO_TYPE_I:
1615         case MONO_TYPE_U:
1616         case MONO_TYPE_R4:
1617         case MONO_TYPE_R8:
1618         case MONO_TYPE_I8:
1619         case MONO_TYPE_U8:
1620         case MONO_TYPE_VALUETYPE:
1621                 /* box value types */
1622                 mono_mb_emit_byte (mb, CEE_BOX);
1623                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (sig->ret)));
1624                 break;
1625         case MONO_TYPE_STRING:
1626         case MONO_TYPE_CLASS:  
1627         case MONO_TYPE_ARRAY:
1628         case MONO_TYPE_SZARRAY:
1629         case MONO_TYPE_OBJECT:
1630                 /* nothing to do */
1631                 break;
1632         case MONO_TYPE_PTR:
1633         default:
1634                 g_assert_not_reached ();
1635         }
1636
1637         mono_mb_emit_stloc (mb, 0);
1638                 
1639         mono_mb_emit_byte (mb, CEE_LEAVE);
1640         pos = mb->pos;
1641         mono_mb_emit_i4 (mb, 0);
1642
1643         clause = g_new0 (MonoExceptionClause, 1);
1644         clause->flags = MONO_EXCEPTION_CLAUSE_FILTER;
1645         clause->try_len = mb->pos;
1646
1647         /* filter code */
1648         clause->token_or_filter = mb->pos;
1649         
1650         mono_mb_emit_byte (mb, CEE_POP);
1651         mono_mb_emit_byte (mb, CEE_LDARG_2);
1652         mono_mb_emit_byte (mb, CEE_LDC_I4_0);
1653         mono_mb_emit_byte (mb, CEE_PREFIX1);
1654         mono_mb_emit_byte (mb, CEE_CGT_UN);
1655         mono_mb_emit_byte (mb, CEE_PREFIX1);
1656         mono_mb_emit_byte (mb, CEE_ENDFILTER);
1657
1658         clause->handler_offset = mb->pos;
1659
1660         /* handler code */
1661         /* store exception */
1662         mono_mb_emit_stloc (mb, 1);
1663         
1664         mono_mb_emit_byte (mb, CEE_LDARG_2);
1665         mono_mb_emit_ldloc (mb, 1);
1666         mono_mb_emit_byte (mb, CEE_STIND_I);
1667
1668         mono_mb_emit_byte (mb, CEE_LEAVE);
1669         mono_mb_emit_i4 (mb, 0);
1670
1671         clause->handler_len = mb->pos - clause->handler_offset;
1672
1673         /* return result */
1674         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1675         mono_mb_emit_ldloc (mb, 0);
1676         mono_mb_emit_byte (mb, CEE_RET);
1677         
1678         res = mono_mb_create_method (mb, csig, sig->param_count + 16);
1679         mono_mb_free (mb);
1680
1681         header = ((MonoMethodNormal *)res)->header;
1682         header->num_clauses = 1;
1683         header->clauses = clause;
1684
1685         g_hash_table_insert (cache, method, res);
1686
1687         return res;     
1688 }
1689
1690 /*
1691  * generates IL code to call managed methods from unmanaged code 
1692  */
1693 MonoMethod *
1694 mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this)
1695 {
1696         MonoMethodSignature *sig, *csig;
1697         MonoMethodBuilder *mb;
1698         MonoClass *klass;
1699         MonoMethod *res;
1700         GHashTable *cache;
1701         int i, pos, sigsize, *tmp_locals;
1702
1703         g_assert (method != NULL);
1704
1705         cache = method->klass->image->managed_wrapper_cache;
1706         if (!this && (res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1707                 return res;
1708
1709         if (this) {
1710                 /* fime: howto free that memory ? */
1711         }
1712         
1713         sig = method->signature;
1714
1715         mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_NATIVE_TO_MANAGED);
1716
1717         /* allocate local 0 (pointer) src_ptr */
1718         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1719         /* allocate local 1 (pointer) dst_ptr */
1720         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1721         /* allocate local 2 (boolean) delete_old */
1722         mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
1723
1724         mono_mb_emit_byte (mb, CEE_LDNULL);
1725         mono_mb_emit_byte (mb, CEE_STLOC_2);
1726
1727         /* we copy the signature, so that we can modify it */
1728         sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1729         csig = g_memdup (sig, sigsize);
1730         csig->hasthis = 0;
1731         csig->pinvoke = 1;
1732
1733         /* fixme: howto handle this ? */
1734         if (sig->hasthis) {
1735
1736                 if (this) {
1737                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1738                         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1739                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, this));
1740
1741
1742                 } else {
1743                         /* fixme: */
1744                         g_assert_not_reached ();
1745                 }
1746         } 
1747
1748
1749         /* we first do all conversions */
1750         tmp_locals = alloca (sizeof (int) * sig->param_count);
1751         for (i = 0; i < sig->param_count; i ++) {
1752                 MonoType *t = sig->params [i];
1753
1754                 tmp_locals [i] = 0;
1755                 
1756                 switch (t->type) {
1757                 case MONO_TYPE_VALUETYPE:
1758                         
1759                         klass = sig->params [i]->data.klass;
1760                         if (klass->blittable || klass->enumtype)
1761                                 break;
1762
1763                         tmp_locals [i] = mono_mb_add_local (mb, &klass->byval_arg);
1764
1765                         if (t->byref) 
1766                                 mono_mb_emit_ldarg (mb, i);
1767                         else
1768                                 mono_mb_emit_ldarg_addr (mb, i);
1769                         mono_mb_emit_byte (mb, CEE_STLOC_0);
1770
1771                         if (t->byref) {
1772                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1773                                 mono_mb_emit_byte (mb, CEE_BRFALSE);
1774                                 pos = mb->pos;
1775                                 mono_mb_emit_i4 (mb, 0);
1776                         }                       
1777
1778                         mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
1779                         mono_mb_emit_byte (mb, CEE_STLOC_1);
1780
1781                         /* emit valuetype convnversion code code */
1782                         emit_struct_conv (mb, klass, TRUE);
1783
1784                         if (t->byref)
1785                                 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1786                         break;
1787                 case MONO_TYPE_STRING:
1788                         if (t->byref)
1789                                 continue;
1790
1791                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1792                         csig->params [i] = &mono_defaults.int_class->byval_arg;
1793
1794                         mono_mb_emit_ldarg (mb, i);
1795                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1796                         mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1797                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
1798                         mono_mb_emit_stloc (mb, tmp_locals [i]);
1799                         break;  
1800                 case MONO_TYPE_ARRAY:
1801                 case MONO_TYPE_SZARRAY:
1802                         if (t->byref)
1803                                 continue;
1804
1805                         klass = mono_class_from_mono_type (t);
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                         g_warning ("array marshaling not implemented");
1811                         g_assert_not_reached ();
1812                         break;
1813                 }
1814         }
1815
1816         for (i = 0; i < sig->param_count; i++) {
1817                 MonoType *t = sig->params [i];
1818
1819                 switch (t->type) {
1820                 case MONO_TYPE_BOOLEAN:
1821                 case MONO_TYPE_I1:
1822                 case MONO_TYPE_U1:
1823                 case MONO_TYPE_I2:
1824                 case MONO_TYPE_U2:
1825                 case MONO_TYPE_I4:
1826                 case MONO_TYPE_U4:
1827                 case MONO_TYPE_I:
1828                 case MONO_TYPE_U:
1829                 case MONO_TYPE_PTR:
1830                 case MONO_TYPE_R4:
1831                 case MONO_TYPE_R8:
1832                 case MONO_TYPE_I8:
1833                 case MONO_TYPE_U8:
1834                         mono_mb_emit_ldarg (mb, i);
1835                         break;
1836                 case MONO_TYPE_STRING:
1837                         if (t->byref) {
1838                                 mono_mb_emit_ldarg (mb, i);
1839                         } else {
1840                                 g_assert (tmp_locals [i]);
1841                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
1842                         }
1843                         break;  
1844                 case MONO_TYPE_CLASS:  
1845                 case MONO_TYPE_ARRAY:
1846                 case MONO_TYPE_SZARRAY:
1847                 case MONO_TYPE_OBJECT:
1848                         /* fixme: conversions ? */
1849                         mono_mb_emit_ldarg (mb, i);
1850                         break;
1851                 case MONO_TYPE_VALUETYPE:
1852                         klass = sig->params [i]->data.klass;
1853                         if (klass->blittable || klass->enumtype) {
1854                                 mono_mb_emit_ldarg (mb, i);
1855                                 break;
1856                         }
1857
1858                         g_assert (tmp_locals [i]);
1859                         if (t->byref)
1860                                 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
1861                         else
1862                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
1863                         break;
1864                 default:
1865                         g_warning ("type 0x%02x unknown", t->type);     
1866                         g_assert_not_reached ();
1867                 }
1868         }
1869
1870         mono_mb_emit_managed_call (mb, method, NULL);
1871
1872         if (!sig->ret->byref) { 
1873                 switch (sig->ret->type) {
1874                 case MONO_TYPE_VOID:
1875                 case MONO_TYPE_BOOLEAN:
1876                 case MONO_TYPE_I1:
1877                 case MONO_TYPE_U1:
1878                 case MONO_TYPE_I2:
1879                 case MONO_TYPE_U2:
1880                 case MONO_TYPE_I4:
1881                 case MONO_TYPE_U4:
1882                 case MONO_TYPE_I:
1883                 case MONO_TYPE_U:
1884                 case MONO_TYPE_PTR:
1885                 case MONO_TYPE_R4:
1886                 case MONO_TYPE_R8:
1887                 case MONO_TYPE_I8:
1888                 case MONO_TYPE_U8:
1889                         /* do nothing */
1890                         break;
1891                 case MONO_TYPE_STRING:          
1892                         csig->ret = &mono_defaults.int_class->byval_arg;
1893
1894                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1895                         mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1896                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
1897                         break;
1898                 case MONO_TYPE_VALUETYPE: {
1899                         int tmp;
1900                         klass = sig->ret->data.klass;
1901                         if (klass->blittable || klass->enumtype)
1902                                 break;
1903                         
1904                         /* load pointer to returned value type */
1905                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1906                         mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
1907                         
1908                         /* store the address of the source into local variable 0 */
1909                         mono_mb_emit_byte (mb, CEE_STLOC_0);
1910                         /* allocate space for the native struct and
1911                          * store the address into dst_ptr */
1912                         tmp = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1913                         g_assert (tmp);
1914                         mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
1915                         mono_mb_emit_byte (mb, CEE_PREFIX1);
1916                         mono_mb_emit_byte (mb, CEE_LOCALLOC);
1917                         mono_mb_emit_byte (mb, CEE_STLOC_1);
1918                         mono_mb_emit_byte (mb, CEE_LDLOC_1);
1919                         mono_mb_emit_stloc (mb, tmp);
1920
1921                         /* emit valuetype conversion code */
1922                         emit_struct_conv (mb, klass, FALSE);
1923                         mono_mb_emit_ldloc (mb, tmp);
1924                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1925                         mono_mb_emit_byte (mb, CEE_MONO_RETOBJ);
1926                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
1927                         break;
1928                 }
1929                 default:
1930                         g_warning ("return type 0x%02x unknown", sig->ret->type);       
1931                         g_assert_not_reached ();
1932                 }
1933         }
1934
1935         mono_mb_emit_byte (mb, CEE_RET);
1936
1937         res = mono_mb_create_method (mb, csig, sig->param_count + 16);
1938         mono_mb_free (mb);
1939
1940         if (!this)
1941                 g_hash_table_insert (cache, method, res);
1942
1943         return res;
1944 }
1945
1946 /*
1947  * generates IL code for the icall wrapper (the generated method
1948  * calls the unamnaged code in func)
1949  */
1950 MonoMethod *
1951 mono_marshal_get_icall_wrapper (MonoMethodSignature *sig, const char *name, gpointer func)
1952 {
1953         MonoMethodSignature *csig;
1954         MonoMethodBuilder *mb;
1955         MonoMethod *res;
1956         int i, sigsize;
1957
1958         mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_MANAGED_TO_NATIVE);
1959
1960         mb->method->save_lmf = 1;
1961
1962         /* we copy the signature, so that we can modify it */
1963         sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1964
1965         if (sig->hasthis)
1966                 mono_mb_emit_byte (mb, CEE_LDARG_0);
1967
1968         for (i = 0; i < sig->param_count; i++)
1969                 mono_mb_emit_ldarg (mb, i + sig->hasthis);
1970
1971         csig = g_memdup (sig, sigsize);
1972         csig->pinvoke = 1;
1973
1974         mono_mb_emit_native_call (mb, csig, func);
1975
1976         mono_mb_emit_byte (mb, CEE_RET);
1977
1978         res = mono_mb_create_method (mb, csig, csig->param_count + 16);
1979         mono_mb_free (mb);
1980         
1981         return res;
1982 }
1983
1984 /*
1985  * generates IL code for the pinvoke wrapper (the generated method
1986  * calls the unamnage code in method->addr)
1987  */
1988 MonoMethod *
1989 mono_marshal_get_native_wrapper (MonoMethod *method)
1990 {
1991         MonoMethodSignature *sig, *csig;
1992         MonoMethodBuilder *mb;
1993         MonoMarshalSpec **mspecs;
1994         MonoMethod *res;
1995         GHashTable *cache;
1996         MonoClass *klass;
1997         gboolean pinvoke = FALSE;
1998         int i, pos, argnum, *tmp_locals;
1999         int type, sigsize;
2000
2001         g_assert (method != NULL);
2002
2003         cache = method->klass->image->native_wrapper_cache;
2004         if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
2005                 return res;
2006
2007         sig = method->signature;
2008
2009         if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
2010             (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2011                 pinvoke = TRUE;
2012
2013         mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_MANAGED_TO_NATIVE);
2014
2015         mb->method->save_lmf = 1;
2016
2017         if (pinvoke && !method->addr)
2018                 mono_lookup_pinvoke_call (method);
2019
2020         if (!method->addr) {
2021                 mono_mb_emit_exception (mb);
2022                 res = mono_mb_create_method (mb, sig, sig->param_count + 16);
2023                 mono_mb_free (mb);
2024                 g_hash_table_insert (cache, method, res);
2025                 return res;
2026         }
2027
2028         /* we copy the signature, so that we can modify it */
2029         sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
2030
2031         /* internal calls: we simply push all arguments and call the method (no conversions) */
2032         if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
2033
2034                 MonoMethodSignature *call_sig;
2035
2036                 /* hack - string constructors returns a value */
2037                 if (method->string_ctor) {
2038                         csig = g_memdup (sig, sigsize);
2039                         csig->ret = &mono_defaults.string_class->byval_arg;
2040                 } else
2041                         csig = sig;
2042
2043                 if (sig->hasthis)
2044                         mono_mb_emit_byte (mb, CEE_LDARG_0);
2045
2046                 for (i = 0; i < sig->param_count; i++)
2047                         mono_mb_emit_ldarg (mb, i + sig->hasthis);
2048
2049                 call_sig = g_memdup (csig, sigsize);
2050                 call_sig->pinvoke = 1;
2051
2052                 g_assert (method->addr);
2053                 mono_mb_emit_native_call (mb, call_sig, method->addr);
2054
2055                 mono_mb_emit_byte (mb, CEE_RET);
2056
2057                 res = mono_mb_create_method (mb, csig, sig->param_count + 16);
2058                 mono_mb_free (mb);
2059                 g_hash_table_insert (cache, method, res);
2060                 return res;
2061         }
2062
2063         g_assert (pinvoke);
2064
2065         mspecs = g_new (MonoMarshalSpec, sig->param_count + 1);
2066         mono_method_get_marshal_info (method, mspecs);
2067
2068         /* pinvoke: we need to convert the arguments if necessary */
2069
2070         csig = g_memdup (sig, sigsize);
2071         csig->pinvoke = 1;
2072
2073         /* we allocate local for use with emit_struct_conv() */
2074         /* allocate local 0 (pointer) src_ptr */
2075         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2076         /* allocate local 1 (pointer) dst_ptr */
2077         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2078         /* allocate local 2 (boolean) delete_old */
2079         mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2080
2081         /* delete_old = FALSE */
2082         mono_mb_emit_icon (mb, 0);
2083         mono_mb_emit_byte (mb, CEE_STLOC_2);
2084
2085         if (sig->ret->type != MONO_TYPE_VOID) {
2086                 /* allocate local 3 to store the return value */
2087                 mono_mb_add_local (mb, sig->ret);
2088         }
2089
2090         /* we first do all conversions */
2091         tmp_locals = alloca (sizeof (int) * sig->param_count);
2092         for (i = 0; i < sig->param_count; i ++) {
2093                 MonoType *t = sig->params [i];
2094                 MonoMarshalSpec *spec = mspecs [i + 1];
2095
2096                 argnum = i + sig->hasthis;
2097                 tmp_locals [i] = 0;
2098
2099                 switch (t->type) {
2100                 case MONO_TYPE_VALUETYPE:                       
2101                         klass = t->data.klass;
2102                         if (klass->blittable || klass->enumtype)
2103                                 break;
2104
2105                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2106                         
2107                         /* store the address of the source into local variable 0 */
2108                         if (t->byref)
2109                                 mono_mb_emit_ldarg (mb, argnum);
2110                         else
2111                                 mono_mb_emit_ldarg_addr (mb, argnum);
2112
2113                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2114                         
2115                         if (t->byref) {
2116                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2117                                 mono_mb_emit_byte (mb, CEE_BRFALSE);
2118                                 pos = mb->pos;
2119                                 mono_mb_emit_i4 (mb, 0);
2120                         }
2121
2122                         /* allocate space for the native struct and
2123                          * store the address into local variable 1 (dest) */
2124                         mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2125                         mono_mb_emit_byte (mb, CEE_PREFIX1);
2126                         mono_mb_emit_byte (mb, CEE_LOCALLOC);
2127                         mono_mb_emit_stloc (mb, tmp_locals [i]);
2128                         /* set dst_ptr */
2129                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
2130                         mono_mb_emit_byte (mb, CEE_STLOC_1);
2131
2132                         /* emit valuetype conversion code */
2133                         emit_struct_conv (mb, klass, FALSE);
2134                         
2135                         if (t->byref)
2136                                 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2137                         break;
2138                 case MONO_TYPE_STRING:
2139                         if (t->byref)
2140                                 continue;
2141
2142                         csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2143                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2144
2145                         mono_mb_emit_ldarg (mb, argnum);
2146                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2147                         mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2148
2149                         if (spec) {
2150                                 switch (spec->native) {
2151                                 case MONO_NATIVE_LPWSTR:
2152                                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPWSTR);
2153                                         break;
2154                                 default:
2155                                         g_warning ("marshalling conversion not implemented");
2156                                         g_assert_not_reached ();
2157                                 }
2158                         } else {
2159                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
2160                         }
2161
2162                         mono_mb_emit_stloc (mb, tmp_locals [i]);
2163                         break;
2164                 case MONO_TYPE_CLASS:
2165                 case MONO_TYPE_OBJECT:
2166                         if (t->byref)
2167                                 continue;
2168
2169                         csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2170                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2171
2172                         if (t->data.klass->delegate) {
2173                                 mono_mb_emit_ldarg (mb, argnum);
2174                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2175                                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2176                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_DEL_FTN);
2177                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
2178                         } else if (t->data.klass == mono_defaults.stringbuilder_class) {
2179                                 mono_mb_emit_ldarg (mb, argnum);
2180                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2181                                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2182                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_SB_LPSTR);
2183                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
2184                         } else {
2185                                 mono_mb_emit_ldarg (mb, argnum);
2186                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2187                                 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2188                                 /* fixme: convert to what ? */
2189                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
2190                         }
2191
2192                         break;
2193                 case MONO_TYPE_ARRAY:
2194                 case MONO_TYPE_SZARRAY:
2195                         if (t->byref)
2196                                 continue;
2197
2198                         klass = mono_class_from_mono_type (t);
2199
2200                         csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2201                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2202
2203                         mono_mb_emit_ldarg (mb, argnum);
2204                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2205                         mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2206                         if (klass->element_class == mono_defaults.string_class) 
2207                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STRARRAY_STRLPARRAY);
2208                         else
2209                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_ARRAY_LPARRAY);
2210                         mono_mb_emit_stloc (mb, tmp_locals [i]);
2211                         break;
2212                 }
2213         }
2214
2215         /* push all arguments */
2216
2217         if (sig->hasthis)
2218                 mono_mb_emit_byte (mb, CEE_LDARG_0);
2219
2220         for (i = 0; i < sig->param_count; i++) {
2221                 MonoType *t = sig->params [i];
2222                 
2223                 argnum = i + sig->hasthis;
2224
2225                 switch (t->type) {
2226                 case MONO_TYPE_BOOLEAN:
2227                         if (t->byref)
2228                                 g_warning ("byref boolean marshalling not inplemented");
2229                         mono_mb_emit_ldarg (mb, argnum);
2230                         break;
2231                 case MONO_TYPE_I1:
2232                 case MONO_TYPE_U1:
2233                 case MONO_TYPE_I2:
2234                 case MONO_TYPE_U2:
2235                 case MONO_TYPE_I4:
2236                 case MONO_TYPE_U4:
2237                 case MONO_TYPE_I:
2238                 case MONO_TYPE_U:
2239                 case MONO_TYPE_PTR:
2240                 case MONO_TYPE_R4:
2241                 case MONO_TYPE_R8:
2242                 case MONO_TYPE_I8:
2243                 case MONO_TYPE_U8:
2244                         mono_mb_emit_ldarg (mb, argnum);
2245                         break;
2246                 case MONO_TYPE_VALUETYPE:
2247                         klass = sig->params [i]->data.klass;
2248                         if (klass->blittable || klass->enumtype) {
2249                                 mono_mb_emit_ldarg (mb, argnum);
2250                                 break;
2251                         }                       
2252                         g_assert (tmp_locals [i]);
2253                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
2254                         if (!t->byref) {
2255                                 mono_mb_emit_byte (mb, CEE_LDOBJ);
2256                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2257                         }
2258                         break;
2259                 case MONO_TYPE_STRING:
2260                         if (t->byref) {
2261                                 mono_mb_emit_ldarg (mb, argnum);
2262                         } else {
2263                                 g_assert (tmp_locals [i]);
2264                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2265                         }
2266                         break;
2267                 case MONO_TYPE_CLASS:
2268                 case MONO_TYPE_OBJECT:
2269                         if (t->byref) {
2270                                 mono_mb_emit_ldarg (mb, argnum);
2271                         } else {
2272                                 g_assert (tmp_locals [i]);
2273                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2274                         }
2275                         break;
2276                 case MONO_TYPE_CHAR:
2277                         /* fixme: dont know how to marshal that. We cant simply
2278                          * convert it to a one byte UTF8 character, because an
2279                          * unicode character may need more that one byte in UTF8 */
2280                         mono_mb_emit_ldarg (mb, argnum);
2281                         break;
2282                 case MONO_TYPE_ARRAY:
2283                 case MONO_TYPE_SZARRAY:
2284                         if (t->byref) {
2285                                 mono_mb_emit_ldarg (mb, argnum);
2286                         } else {
2287                                 g_assert (tmp_locals [i]);
2288                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2289                         }
2290                         break;
2291                 case MONO_TYPE_TYPEDBYREF:
2292                 case MONO_TYPE_FNPTR:
2293                 default:
2294                         g_warning ("type 0x%02x unknown", t->type);     
2295                         g_assert_not_reached ();
2296                 }
2297         }                       
2298
2299         /* call the native method */
2300         mono_mb_emit_native_call (mb, csig, method->addr);
2301
2302         /* return the result */
2303
2304         /* we need to convert byref arguments back and free string arrays */
2305         for (i = 0; i < sig->param_count; i++) {
2306                 MonoType *t = sig->params [i];
2307                 
2308                 argnum = i + sig->hasthis;
2309
2310                 switch (t->type) {
2311                 case MONO_TYPE_CLASS:
2312                 case MONO_TYPE_OBJECT:                  
2313                         if (t->byref)
2314                                 continue;
2315      
2316                         if (t->data.klass == mono_defaults.stringbuilder_class) {
2317                                 mono_mb_emit_ldarg (mb, argnum);
2318                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2319                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2320                                 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
2321                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_SB);
2322                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2323                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2324                                 mono_mb_emit_byte (mb, CEE_MONO_FREE);
2325                         }
2326                         break;
2327                 case MONO_TYPE_VALUETYPE:
2328                         if (!t->byref)
2329                                 continue;
2330         
2331                         klass = t->data.klass;
2332                         if (klass->blittable || klass->enumtype)
2333                                 break;
2334
2335                         /* dst = argument */
2336                         mono_mb_emit_ldarg (mb, argnum);
2337                         mono_mb_emit_byte (mb, CEE_STLOC_1);
2338
2339                         mono_mb_emit_byte (mb, CEE_LDLOC_1);
2340                         mono_mb_emit_byte (mb, CEE_BRFALSE);
2341                         pos = mb->pos;
2342                         mono_mb_emit_i4 (mb, 0);
2343
2344                         /* src = tmp_locals [i] */
2345                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
2346                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2347
2348                         /* emit valuetype conversion code */
2349                         emit_struct_conv (mb, klass, TRUE);
2350                         
2351                         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2352                         break;
2353                 case MONO_TYPE_SZARRAY:
2354                         if (t->byref)
2355                                 continue;
2356  
2357                         klass = mono_class_from_mono_type (t);
2358                         
2359                         if (klass->element_class == mono_defaults.string_class) {
2360                                 g_assert (tmp_locals [i]);
2361                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2362                                 mono_mb_emit_ldarg (mb, argnum);
2363                                 mono_mb_emit_byte (mb, CEE_LDLEN);                              
2364                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2365                                 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
2366                                 mono_mb_emit_byte (mb, MONO_MARSHAL_FREE_ARRAY);
2367                         }
2368
2369                         break;
2370                 }
2371         }
2372
2373         if (!sig->ret->byref) {
2374                 MonoMarshalSpec *spec = mspecs [0];
2375                 type = sig->ret->type;
2376
2377         handle_enum:
2378                 switch (type) {
2379                 case MONO_TYPE_VOID:
2380                 case MONO_TYPE_I1:
2381                 case MONO_TYPE_U1:
2382                 case MONO_TYPE_I2:
2383                 case MONO_TYPE_U2:
2384                 case MONO_TYPE_I4:
2385                 case MONO_TYPE_U4:
2386                 case MONO_TYPE_I:
2387                 case MONO_TYPE_U:
2388                 case MONO_TYPE_PTR:
2389                 case MONO_TYPE_R4:
2390                 case MONO_TYPE_R8:
2391                 case MONO_TYPE_I8:
2392                 case MONO_TYPE_U8:
2393                 /* no conversions necessary */
2394                         break;
2395                 case MONO_TYPE_BOOLEAN:
2396                         /* maybe we need to make sure that it fits within 8 bits */
2397                         break;
2398                 case MONO_TYPE_VALUETYPE: {
2399                         int tmp;
2400
2401                         klass = sig->ret->data.klass;
2402                         if (klass->enumtype) {
2403                                 type = sig->ret->data.klass->enum_basetype->type;
2404                                 goto handle_enum;
2405                         }
2406
2407                         if (klass->blittable)
2408                                 break;
2409
2410                         tmp = mono_mb_add_local (mb, sig->ret);
2411                         g_assert (tmp);
2412                         /* load pointer to returned value type */
2413                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2414                         mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
2415                         /* store the address of the source into local variable 0 */
2416                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2417                         /* set dst_ptr */
2418                         mono_mb_emit_ldloc_addr (mb, tmp);
2419                         mono_mb_emit_byte (mb, CEE_STLOC_1);
2420
2421                         /* emit valuetype conversion code */
2422                         emit_struct_conv (mb, sig->ret->data.klass, TRUE);
2423
2424                         mono_mb_emit_ldloc (mb, tmp);
2425                         break;
2426                 }
2427                 case MONO_TYPE_STRING:
2428                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2429                         mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2430                         if (spec) {
2431                                 switch (spec->native) {
2432                                 case MONO_NATIVE_LPWSTR:
2433                                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPWSTR_STR);
2434                                         break;
2435                                 default:
2436                                         g_warning ("marshalling conversion not implemented");
2437                                         g_assert_not_reached ();
2438                                 }
2439                         } else {
2440                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
2441                         }
2442                         break;
2443                 case MONO_TYPE_ARRAY:
2444                 case MONO_TYPE_SZARRAY:
2445                 case MONO_TYPE_CLASS:
2446                 case MONO_TYPE_OBJECT:
2447                         /* fixme: we need conversions here */
2448                         break;
2449                 case MONO_TYPE_CHAR:
2450                         /* fixme: we need conversions here */
2451                         break;
2452                 case MONO_TYPE_TYPEDBYREF:
2453                 case MONO_TYPE_FNPTR:
2454                 default:
2455                         g_warning ("return type 0x%02x unknown", sig->ret->type);       
2456                         g_assert_not_reached ();
2457                 }
2458         }
2459
2460         mono_mb_emit_byte (mb, CEE_RET);
2461
2462         res = mono_mb_create_method (mb, sig, sig->param_count + 16);
2463         mono_mb_free (mb);
2464
2465         g_hash_table_insert (cache, method, res);
2466
2467         for (i = sig->param_count; i >= 0; i--)
2468                 g_free (mspecs [i]);
2469         g_free (mspecs);
2470
2471         return res;
2472 }
2473
2474 /*
2475  * generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld)
2476  */
2477 MonoMethod *
2478 mono_marshal_get_struct_to_ptr (MonoClass *klass)
2479 {
2480         MonoMethodBuilder *mb;
2481         static MonoMethod *stoptr = NULL;
2482         MonoMethod *res;
2483
2484         g_assert (klass != NULL);
2485
2486         if (klass->str_to_ptr)
2487                 return klass->str_to_ptr;
2488
2489         if (!stoptr) 
2490                 stoptr = mono_find_method_by_name (mono_defaults.marshal_class, "StructureToPtr", 3);
2491         g_assert (stoptr);
2492
2493         mb = mono_mb_new (klass, stoptr->name, MONO_WRAPPER_UNKNOWN);
2494
2495         if (klass->blittable) {
2496                 mono_mb_emit_byte (mb, CEE_LDARG_1);
2497                 mono_mb_emit_byte (mb, CEE_LDARG_0);
2498                 mono_mb_emit_icon (mb, sizeof (MonoObject));
2499                 mono_mb_emit_byte (mb, CEE_ADD);
2500                 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
2501                 mono_mb_emit_byte (mb, CEE_PREFIX1);
2502                 mono_mb_emit_byte (mb, CEE_CPBLK);
2503         } else {
2504
2505                 /* allocate local 0 (pointer) src_ptr */
2506                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2507                 /* allocate local 1 (pointer) dst_ptr */
2508                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2509                 /* allocate local 2 (boolean) delete_old */
2510                 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2511                 mono_mb_emit_byte (mb, CEE_LDARG_2);
2512                 mono_mb_emit_byte (mb, CEE_STLOC_2);
2513
2514                 /* initialize src_ptr to point to the start of object data */
2515                 mono_mb_emit_byte (mb, CEE_LDARG_0);
2516                 mono_mb_emit_icon (mb, sizeof (MonoObject));
2517                 mono_mb_emit_byte (mb, CEE_ADD);
2518                 mono_mb_emit_byte (mb, CEE_STLOC_0);
2519
2520                 /* initialize dst_ptr */
2521                 mono_mb_emit_byte (mb, CEE_LDARG_1);
2522                 mono_mb_emit_byte (mb, CEE_STLOC_1);
2523
2524                 emit_struct_conv (mb, klass, FALSE);
2525         }
2526
2527         mono_mb_emit_byte (mb, CEE_RET);
2528
2529         res = mono_mb_create_method (mb, stoptr->signature, 0);
2530         mono_mb_free (mb);
2531
2532         klass->str_to_ptr = res;
2533         return res;
2534 }
2535
2536 /*
2537  * generates IL code for PtrToStructure (IntPtr src, object structure)
2538  */
2539 MonoMethod *
2540 mono_marshal_get_ptr_to_struct (MonoClass *klass)
2541 {
2542         MonoMethodBuilder *mb;
2543         static MonoMethod *ptostr = NULL;
2544         MonoMethod *res;
2545
2546         g_assert (klass != NULL);
2547
2548         if (klass->ptr_to_str)
2549                 return klass->ptr_to_str;
2550
2551         if (!ptostr) 
2552                 ptostr = mono_find_method_by_name (mono_defaults.marshal_class, "PtrToStructure", 2);
2553         g_assert (ptostr);
2554
2555         mb = mono_mb_new (klass, ptostr->name, MONO_WRAPPER_UNKNOWN);
2556
2557         if (klass->blittable) {
2558                 mono_mb_emit_byte (mb, CEE_LDARG_1);
2559                 mono_mb_emit_icon (mb, sizeof (MonoObject));
2560                 mono_mb_emit_byte (mb, CEE_ADD);
2561                 mono_mb_emit_byte (mb, CEE_LDARG_0);
2562                 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
2563                 mono_mb_emit_byte (mb, CEE_PREFIX1);
2564                 mono_mb_emit_byte (mb, CEE_CPBLK);
2565         } else {
2566
2567                 /* allocate local 0 (pointer) src_ptr */
2568                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2569                 /* allocate local 1 (pointer) dst_ptr */
2570                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2571                 
2572                 /* initialize src_ptr to point to the start of object data */
2573                 mono_mb_emit_byte (mb, CEE_LDARG_0);
2574                 mono_mb_emit_byte (mb, CEE_STLOC_0);
2575
2576                 /* initialize dst_ptr */
2577                 mono_mb_emit_byte (mb, CEE_LDARG_1);
2578                 mono_mb_emit_icon (mb, sizeof (MonoObject));
2579                 mono_mb_emit_byte (mb, CEE_ADD);
2580                 mono_mb_emit_byte (mb, CEE_STLOC_1);
2581
2582                 emit_struct_conv (mb, klass, TRUE);
2583         }
2584
2585         mono_mb_emit_byte (mb, CEE_RET);
2586
2587         res = mono_mb_create_method (mb, ptostr->signature, 0);
2588         mono_mb_free (mb);
2589
2590         klass->ptr_to_str = res;
2591         return res;
2592 }
2593
2594 /* FIXME: on win32 we should probably use GlobalAlloc(). */
2595 void*
2596 mono_marshal_alloc (gpointer size) 
2597 {
2598         MONO_ARCH_SAVE_REGS;
2599
2600         return g_try_malloc ((gulong)size);
2601 }
2602
2603 void
2604 mono_marshal_free (gpointer ptr) 
2605 {
2606         MONO_ARCH_SAVE_REGS;
2607
2608         g_free (ptr);
2609 }
2610
2611 void
2612 mono_marshal_free_array (gpointer *ptr, int size) {
2613         int i;
2614
2615         for (i = 0; i < size; i++)
2616                 if (ptr [i])
2617                         g_free (ptr [i]);
2618 }
2619
2620 void *
2621 mono_marshal_realloc (gpointer ptr, gpointer size) 
2622 {
2623         MONO_ARCH_SAVE_REGS;
2624
2625         return g_try_realloc (ptr, (gulong)size);
2626 }
2627
2628 void *
2629 mono_marshal_string_array (MonoArray *array)
2630 {
2631         char **result;
2632         int i, len;
2633
2634         if (!array)
2635                 return NULL;
2636
2637         len = mono_array_length (array);
2638
2639         result = g_malloc (sizeof (char *) * (len + 1));
2640         for (i = 0; i < len; ++i) {
2641                 MonoString *s = (MonoString *)mono_array_get (array, gpointer, i);
2642                 result [i] = s ? mono_string_to_utf8 (s): NULL;
2643         }
2644         /* null terminate the array */
2645         result [i] = NULL;
2646
2647         return result;
2648 }
2649
2650 void
2651 ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArray *src, gint32 start_index,
2652                                                                     gpointer dest, gint32 length)
2653 {
2654         int element_size;
2655         void *source_addr;
2656
2657         MONO_ARCH_SAVE_REGS;
2658
2659         MONO_CHECK_ARG_NULL (src);
2660         MONO_CHECK_ARG_NULL (dest);
2661
2662         g_assert (src->obj.vtable->klass->rank == 1);
2663         g_assert (start_index >= 0 && start_index < mono_array_length (src));
2664         g_assert (start_index + length <= mono_array_length (src));
2665
2666         element_size = mono_array_element_size (src->obj.vtable->klass);
2667           
2668         source_addr = mono_array_addr_with_size (src, element_size, start_index);
2669
2670         memcpy (dest, source_addr, length * element_size);
2671 }
2672
2673 void
2674 ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer src, gint32 start_index,
2675                                                                       MonoArray *dest, gint32 length)
2676 {
2677         int element_size;
2678         void *dest_addr;
2679
2680         MONO_ARCH_SAVE_REGS;
2681
2682         MONO_CHECK_ARG_NULL (src);
2683         MONO_CHECK_ARG_NULL (dest);
2684
2685         g_assert (dest->obj.vtable->klass->rank == 1);
2686         g_assert (start_index >= 0 && start_index < mono_array_length (dest));
2687         g_assert (start_index + length <= mono_array_length (dest));
2688
2689         element_size = mono_array_element_size (dest->obj.vtable->klass);
2690           
2691         dest_addr = mono_array_addr_with_size (dest, element_size, start_index);
2692
2693         memcpy (dest_addr, src, length * element_size);
2694 }
2695
2696 gpointer
2697 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr, gint32 offset)
2698 {
2699         char *p = ptr;
2700
2701         MONO_ARCH_SAVE_REGS;
2702
2703         return *(gpointer*)(p + offset);
2704 }
2705
2706 unsigned char
2707 ves_icall_System_Runtime_InteropServices_Marshal_ReadByte (gpointer ptr, gint32 offset)
2708 {
2709         char *p = ptr;
2710
2711         MONO_ARCH_SAVE_REGS;
2712
2713         return *(unsigned char*)(p + offset);
2714 }
2715
2716 gint16
2717 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt16 (gpointer ptr, gint32 offset)
2718 {
2719         char *p = ptr;
2720
2721         MONO_ARCH_SAVE_REGS;
2722
2723         return *(gint16*)(p + offset);
2724 }
2725
2726 gint32
2727 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt32 (gpointer ptr, gint32 offset)
2728 {
2729         char *p = ptr;
2730
2731         MONO_ARCH_SAVE_REGS;
2732
2733         return *(gint32*)(p + offset);
2734 }
2735
2736 gint64
2737 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt64 (gpointer ptr, gint32 offset)
2738 {
2739         char *p = ptr;
2740
2741         MONO_ARCH_SAVE_REGS;
2742
2743         return *(gint64*)(p + offset);
2744 }
2745
2746 void
2747 ves_icall_System_Runtime_InteropServices_Marshal_WriteByte (gpointer ptr, gint32 offset, unsigned char val)
2748 {
2749         char *p = ptr;
2750
2751         MONO_ARCH_SAVE_REGS;
2752
2753         *(unsigned char*)(p + offset) = val;
2754 }
2755
2756 void
2757 ves_icall_System_Runtime_InteropServices_Marshal_WriteIntPtr (gpointer ptr, gint32 offset, gpointer val)
2758 {
2759         char *p = ptr;
2760
2761         MONO_ARCH_SAVE_REGS;
2762
2763         *(gpointer*)(p + offset) = val;
2764 }
2765
2766 void
2767 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt16 (gpointer ptr, gint32 offset, gint16 val)
2768 {
2769         char *p = ptr;
2770
2771         MONO_ARCH_SAVE_REGS;
2772
2773         *(gint16*)(p + offset) = val;
2774 }
2775
2776 void
2777 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt32 (gpointer ptr, gint32 offset, gint32 val)
2778 {
2779         char *p = ptr;
2780
2781         MONO_ARCH_SAVE_REGS;
2782
2783         *(gint32*)(p + offset) = val;
2784 }
2785
2786 void
2787 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt64 (gpointer ptr, gint32 offset, gint64 val)
2788 {
2789         char *p = ptr;
2790
2791         MONO_ARCH_SAVE_REGS;
2792
2793         *(gint64*)(p + offset) = val;
2794 }
2795
2796 MonoString *
2797 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (char *ptr)
2798 {
2799         MONO_ARCH_SAVE_REGS;
2800
2801         return mono_string_new (mono_domain_get (), ptr);
2802 }
2803
2804 MonoString *
2805 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len (char *ptr, gint32 len)
2806 {
2807         MONO_ARCH_SAVE_REGS;
2808
2809         return mono_string_new_len (mono_domain_get (), ptr, len);
2810 }
2811
2812 MonoString *
2813 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni (guint16 *ptr)
2814 {
2815         MonoDomain *domain = mono_domain_get (); 
2816         int len = 0;
2817         guint16 *t = ptr;
2818
2819         MONO_ARCH_SAVE_REGS;
2820
2821         while (*t++)
2822                 len++;
2823
2824         return mono_string_new_utf16 (domain, ptr, len);
2825 }
2826
2827 MonoString *
2828 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len (guint16 *ptr, gint32 len)
2829 {
2830         MonoDomain *domain = mono_domain_get (); 
2831
2832         MONO_ARCH_SAVE_REGS;
2833
2834         return mono_string_new_utf16 (domain, ptr, len);
2835 }
2836
2837 MonoString *
2838 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR (gpointer ptr)
2839 {
2840         MONO_ARCH_SAVE_REGS;
2841
2842         g_warning ("PtrToStringBSTR not implemented");
2843         g_assert_not_reached ();
2844
2845         return NULL;
2846 }
2847
2848 guint32 
2849 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
2850 {
2851         MONO_ARCH_SAVE_REGS;
2852
2853         return (GetLastError ());
2854 }
2855
2856 guint32 
2857 ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype)
2858 {
2859         MonoClass *klass;
2860
2861         MONO_ARCH_SAVE_REGS;
2862
2863         MONO_CHECK_ARG_NULL (rtype);
2864
2865         klass = mono_class_from_mono_type (rtype->type);
2866
2867         return mono_class_native_size (klass, NULL);
2868 }
2869
2870 void
2871 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old)
2872 {
2873         MonoMethod *method;
2874         gpointer pa [3];
2875
2876         MONO_ARCH_SAVE_REGS;
2877
2878         MONO_CHECK_ARG_NULL (obj);
2879         MONO_CHECK_ARG_NULL (dst);
2880
2881         method = mono_marshal_get_struct_to_ptr (obj->vtable->klass);
2882
2883         pa [0] = obj;
2884         pa [1] = &dst;
2885         pa [2] = &delete_old;
2886
2887         mono_runtime_invoke (method, NULL, pa, NULL);
2888 }
2889
2890 void
2891 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, MonoObject *dst)
2892 {
2893         MonoMethod *method;
2894         gpointer pa [2];
2895
2896         MONO_ARCH_SAVE_REGS;
2897
2898         MONO_CHECK_ARG_NULL (src);
2899         MONO_CHECK_ARG_NULL (dst);
2900
2901         method = mono_marshal_get_ptr_to_struct (dst->vtable->klass);
2902
2903         pa [0] = &src;
2904         pa [1] = dst;
2905
2906         mono_runtime_invoke (method, NULL, pa, NULL);
2907 }
2908
2909 MonoObject *
2910 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer src, MonoReflectionType *type)
2911 {
2912         MonoDomain *domain = mono_domain_get (); 
2913         MonoObject *res;
2914
2915         MONO_ARCH_SAVE_REGS;
2916
2917         MONO_CHECK_ARG_NULL (src);
2918         MONO_CHECK_ARG_NULL (type);
2919
2920         res = mono_object_new (domain, mono_class_from_mono_type (type->type));
2921
2922         ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (src, res);
2923
2924         return res;
2925 }
2926
2927 int
2928 ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *type, MonoString *field_name)
2929 {
2930         MonoMarshalType *info;
2931         MonoClass *klass;
2932         char *fname;
2933         int i;
2934
2935         MONO_ARCH_SAVE_REGS;
2936
2937         MONO_CHECK_ARG_NULL (type);
2938         MONO_CHECK_ARG_NULL (field_name);
2939
2940         fname = mono_string_to_utf8 (field_name);
2941         klass = mono_class_from_mono_type (type->type);
2942
2943         info = mono_marshal_load_type_info (klass);     
2944         
2945         for (i = 0; i < klass->field.count; ++i) {
2946                 if (*fname == *klass->fields [i].name && 
2947                     strcmp (fname, klass->fields [i].name) == 0)
2948                         break;
2949         }
2950         g_free (fname);
2951
2952         mono_assert (i < klass->field.count);
2953
2954         return info->fields [i].offset;
2955 }
2956
2957 gpointer
2958 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString *string)
2959 {
2960         MONO_ARCH_SAVE_REGS;
2961
2962         return mono_string_to_utf8 (string);
2963 }
2964
2965 gpointer
2966 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni (MonoString *string)
2967 {
2968         MONO_ARCH_SAVE_REGS;
2969
2970         return g_memdup (mono_string_chars (string), mono_string_length (string)*2);
2971 }
2972
2973 static void
2974 mono_struct_delete_old (MonoClass *klass, char *ptr)
2975 {
2976         MonoMarshalType *info;
2977         int i;
2978
2979         info = mono_marshal_load_type_info (klass);
2980
2981         for (i = 0; i < info->num_fields; i++) {
2982                 MonoMarshalNative ntype;
2983                 MonoMarshalConv conv;
2984                 MonoType *ftype = info->fields [i].field->type;
2985                 char *cpos;
2986
2987                 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
2988                         continue;
2989
2990                 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, 
2991                                                 klass->unicode, &conv);
2992                         
2993                 cpos = ptr + info->fields [i].offset;
2994
2995                 switch (conv) {
2996                 case MONO_MARSHAL_CONV_NONE:
2997                         if (MONO_TYPE_ISSTRUCT (ftype)) {
2998                                 mono_struct_delete_old (ftype->data.klass, cpos);
2999                                 continue;
3000                         }
3001                         break;
3002                 case MONO_MARSHAL_CONV_STR_LPWSTR:
3003                 case MONO_MARSHAL_CONV_STR_LPSTR:
3004                 case MONO_MARSHAL_CONV_STR_LPTSTR:
3005                 case MONO_MARSHAL_CONV_STR_BSTR:
3006                 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
3007                 case MONO_MARSHAL_CONV_STR_TBSTR:
3008                         g_free (*(gpointer *)cpos);
3009                         break;
3010                 default:
3011                         continue;
3012                 }
3013         }
3014 }
3015
3016 void
3017 ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure (gpointer src, MonoReflectionType *type)
3018 {
3019         MonoClass *klass;
3020
3021         MONO_ARCH_SAVE_REGS;
3022
3023         MONO_CHECK_ARG_NULL (src);
3024         MONO_CHECK_ARG_NULL (type);
3025
3026         klass = mono_class_from_mono_type (type->type);
3027
3028         mono_struct_delete_old (klass, (char *)src);
3029 }
3030