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