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