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