(ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringXXX):
[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
21 //#define DEBUG_RUNTIME_CODE
22
23 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
24         a = i,
25
26 enum {
27 #include "mono/cil/opcode.def"
28         LAST = 0xff
29 };
30 #undef OPDEF
31
32 struct _MonoMethodBuilder {
33         MonoMethod *method;
34         GList *locals_list;
35         int locals;
36         guint32 code_size, pos;
37         unsigned char *code;
38 };
39
40 #ifdef DEBUG_RUNTIME_CODE
41 static char*
42 indenter (MonoDisHelper *dh, MonoMethod *method, guint32 ip_offset)
43 {
44         return g_strdup (" ");
45 }
46
47 static MonoDisHelper marshal_dh = {
48         "\n",
49         NULL,
50         "IL_%04x",
51         indenter, 
52         NULL,
53         NULL
54 };
55 #endif 
56
57 gpointer
58 mono_delegate_to_ftnptr (MonoDelegate *delegate)
59 {
60         MonoMethod *method, *wrapper;
61         MonoClass *klass;
62
63         if (!delegate)
64                 return NULL;
65
66         if (delegate->delegate_trampoline)
67                 return delegate->delegate_trampoline;
68
69         klass = ((MonoObject *)delegate)->vtable->klass;
70         g_assert (klass->delegate);
71         
72         method = delegate->method_info->method;
73         
74         wrapper = mono_marshal_get_managed_wrapper (method, (MonoObject *)delegate);
75
76         delegate->delegate_trampoline =  mono_compile_method (wrapper);
77
78         return delegate->delegate_trampoline;
79 }
80
81 gpointer
82 mono_array_to_savearray (MonoArray *array)
83 {
84         if (!array)
85                 return NULL;
86
87         g_assert_not_reached ();
88         return NULL;
89 }
90
91 gpointer
92 mono_array_to_lparray (MonoArray *array)
93 {
94         if (!array)
95                 return NULL;
96
97         /* fixme: maybe we need to make a copy */
98         return array->vector;
99 }
100
101 gpointer
102 mono_string_to_ansibstr (MonoString *string_obj)
103 {
104         g_error ("implement me");
105         return NULL;
106 }
107
108 gpointer
109 mono_string_to_bstr (MonoString *string_obj)
110 {
111         g_error ("implement me");
112         return NULL;
113 }
114
115 void
116 mono_string_to_byvalstr (gpointer dst, MonoString *src, int size)
117 {
118         char *s;
119         int len;
120
121         g_assert (dst != NULL);
122         g_assert (size > 0);
123
124         if (!src) {
125                 memset (dst, 0, size);
126                 return;
127         }
128
129         s = mono_string_to_utf8 (src);
130         len = MIN (size, strlen (s));
131         memcpy (dst, s, len);
132         g_free (s);
133
134         *((char *)dst + size - 1) = 0;
135 }
136
137 void
138 mono_string_to_byvalwstr (gpointer dst, MonoString *src, int size)
139 {
140         int len;
141
142         g_assert (dst != NULL);
143         g_assert (size > 1);
144
145         if (!src) {
146                 memset (dst, 0, size);
147                 return;
148         }
149
150         len = MIN (size, (mono_string_length (src) * 2));
151         memcpy (dst, mono_string_chars (src), len);
152
153         *((char *)dst + size - 1) = 0;
154         *((char *)dst + size - 2) = 0;
155 }
156
157
158 static MonoMethod *
159 mono_find_method_by_name (MonoClass *klass, const char *name, int param_count)
160 {
161         MonoMethod *res = NULL;
162         int i;
163
164         for (i = 0; i < klass->method.count; ++i) {
165                 if ((klass->methods [i]->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
166                     klass->methods [i]->name[0] == name [0] && 
167                     !strcmp (name, klass->methods [i]->name) &&
168                     klass->methods [i]->signature->param_count == param_count) {
169                         res = klass->methods [i];
170                         break;
171                 }
172         }
173         return res;
174 }
175
176 void
177 mono_mb_free (MonoMethodBuilder *mb)
178 {
179         g_list_free (mb->locals_list);
180         g_free (mb);
181 }
182
183 MonoMethodBuilder *
184 mono_mb_new (MonoClass *klass, const char *name)
185 {
186         MonoMethodBuilder *mb;
187         MonoMethod *m;
188
189         g_assert (klass != NULL);
190         g_assert (name != NULL);
191
192         mb = g_new0 (MonoMethodBuilder, 1);
193
194         mb->method = m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
195
196         m->klass = klass;
197         m->name = g_strdup (name);
198         m->inline_info = 1;
199         m->inline_count = -1;
200         m->wrapper_type = MONO_WRAPPER_UNKNOWN;
201
202         mb->code_size = 256;
203         mb->code = g_malloc (mb->code_size);
204         
205         return mb;
206 }
207
208 int
209 mono_mb_add_local (MonoMethodBuilder *mb, MonoType *type)
210 {
211         int res = mb->locals;
212
213         g_assert (mb != NULL);
214         g_assert (type != NULL);
215
216         mb->locals_list = g_list_append (mb->locals_list, type);
217         mb->locals++;
218
219         return res;
220 }
221
222 MonoMethod *
223 mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack)
224 {
225         MonoMethodHeader *header;
226         GList *l;
227         int i;
228
229         g_assert (mb != NULL);
230
231         ((MonoMethodNormal *)mb->method)->header = header = (MonoMethodHeader *) 
232                 g_malloc0 (sizeof (MonoMethodHeader) + mb->locals * sizeof (MonoType *));
233
234         if (max_stack < 8)
235                 max_stack = 8;
236
237         header->max_stack = max_stack;
238
239         for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
240                 header->locals [i] = (MonoType *)l->data;
241         }
242
243         mb->method->signature = signature;
244         header->code = mb->code;
245         header->code_size = mb->pos;
246         header->num_locals = mb->locals;
247
248 #ifdef DEBUG_RUNTIME_CODE
249         printf ("RUNTIME CODE FOR %s\n", mono_method_full_name (mb->method, TRUE));
250         printf ("%s\n", mono_disasm_code (&marshal_dh, mb->method, mb->code, mb->code + mb->pos));
251 #endif
252
253         return mb->method;
254 }
255
256 guint32
257 mono_mb_add_data (MonoMethodBuilder *mb, gpointer data)
258 {
259         MonoMethodWrapper *mw;
260
261         g_assert (mb != NULL);
262
263         mw = (MonoMethodWrapper *)mb->method;
264
265         mw->data = g_list_append (mw->data, data);
266
267         return g_list_length (mw->data);
268 }
269
270 void
271 mono_mb_patch_addr (MonoMethodBuilder *mb, int pos, int value)
272 {
273         *((gint32 *)(&mb->code [pos])) = value;
274 }
275
276 void
277 mono_mb_emit_byte (MonoMethodBuilder *mb, guint8 op)
278 {
279         if (mb->pos >= mb->code_size) {
280                 mb->code_size += 64;
281                 mb->code = g_realloc (mb->code, mb->code_size);
282         }
283
284         mb->code [mb->pos++] = op;
285 }
286
287 void
288 mono_mb_emit_i4 (MonoMethodBuilder *mb, gint32 data)
289 {
290         if ((mb->pos + 4) >= mb->code_size) {
291                 mb->code_size += 64;
292                 mb->code = g_realloc (mb->code, mb->code_size);
293         }
294
295         *((gint32 *)(&mb->code [mb->pos])) = data;
296         mb->pos += 4;
297 }
298
299 void
300 mono_mb_emit_i2 (MonoMethodBuilder *mb, gint16 data)
301 {
302         if ((mb->pos + 2) >= mb->code_size) {
303                 mb->code_size += 64;
304                 mb->code = g_realloc (mb->code, mb->code_size);
305         }
306
307         *((gint16 *)(&mb->code [mb->pos])) = data;
308         mb->pos += 2;
309 }
310
311 void
312 mono_mb_emit_ldarg (MonoMethodBuilder *mb, guint argnum)
313 {
314         if (argnum < 4) {
315                 mono_mb_emit_byte (mb, CEE_LDARG_0 + argnum);
316         } else if (argnum < 256) {
317                 mono_mb_emit_byte (mb, CEE_LDARG_S);
318                 mono_mb_emit_byte (mb, argnum);
319         } else {
320                 mono_mb_emit_byte (mb, CEE_PREFIX1);
321                 mono_mb_emit_byte (mb, CEE_LDARG);
322                 mono_mb_emit_i4 (mb, argnum);
323         }
324 }
325
326 void
327 mono_mb_emit_ldarg_addr (MonoMethodBuilder *mb, guint argnum)
328 {
329         if (argnum < 256) {
330                 mono_mb_emit_byte (mb, CEE_LDARGA_S);
331                 mono_mb_emit_byte (mb, argnum);
332         } else {
333                 mono_mb_emit_byte (mb, CEE_PREFIX1);
334                 mono_mb_emit_byte (mb, CEE_LDARGA);
335                 mono_mb_emit_i4 (mb, argnum);
336         }
337 }
338
339 void
340 mono_mb_emit_ldloc_addr (MonoMethodBuilder *mb, guint locnum)
341 {
342         if (locnum < 256) {
343                 mono_mb_emit_byte (mb, CEE_LDLOCA_S);
344                 mono_mb_emit_byte (mb, locnum);
345         } else {
346                 mono_mb_emit_byte (mb, CEE_PREFIX1);
347                 mono_mb_emit_byte (mb, CEE_LDLOCA);
348                 mono_mb_emit_i4 (mb, locnum);
349         }
350 }
351
352 void
353 mono_mb_emit_ldloc (MonoMethodBuilder *mb, guint num)
354 {
355         if (num < 4) {
356                 mono_mb_emit_byte (mb, CEE_LDLOC_0 + num);
357         } else if (num < 256) {
358                 mono_mb_emit_byte (mb, CEE_LDLOC_S);
359                 mono_mb_emit_byte (mb, num);
360         } else {
361                 mono_mb_emit_byte (mb, CEE_PREFIX1);
362                 mono_mb_emit_byte (mb, CEE_LDLOC);
363                 mono_mb_emit_i4 (mb, num);
364         }
365 }
366
367 void
368 mono_mb_emit_stloc (MonoMethodBuilder *mb, guint num)
369 {
370         if (num < 4) {
371                 mono_mb_emit_byte (mb, CEE_STLOC_0 + num);
372         } else if (num < 256) {
373                 mono_mb_emit_byte (mb, CEE_STLOC_S);
374                 mono_mb_emit_byte (mb, num);
375         } else {
376                 mono_mb_emit_byte (mb, CEE_PREFIX1);
377                 mono_mb_emit_byte (mb, CEE_STLOC);
378                 mono_mb_emit_i4 (mb, num);
379         }
380 }
381
382 void
383 mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value)
384 {
385         if (value >= -1 && value < 8) {
386                 mono_mb_emit_byte (mb, CEE_LDC_I4_0 + value);
387         } else if (value >= -128 && value <= 127) {
388                 mono_mb_emit_byte (mb, CEE_LDC_I4_S);
389                 mono_mb_emit_byte (mb, value);
390         } else {
391                 mono_mb_emit_byte (mb, CEE_LDC_I4);
392                 mono_mb_emit_i4 (mb, value);
393         }
394 }
395
396 void
397 mono_mb_emit_managed_call (MonoMethodBuilder *mb, MonoMethod *method, MonoMethodSignature *opt_sig)
398 {
399         if (!opt_sig)
400                 opt_sig = method->signature;
401         mono_mb_emit_byte (mb, CEE_PREFIX1);
402         mono_mb_emit_byte (mb, CEE_LDFTN);
403         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
404         mono_mb_emit_byte (mb, CEE_CALLI);
405         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, opt_sig));
406 }
407
408 void
409 mono_mb_emit_native_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, gpointer func)
410 {
411         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
412         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
413         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, func));
414         mono_mb_emit_byte (mb, CEE_CALLI);
415         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
416 }
417
418 void
419 mono_mb_emit_exception (MonoMethodBuilder *mb)
420 {
421         mono_mb_emit_byte (mb, CEE_LDNULL);
422         mono_mb_emit_byte (mb, CEE_THROW);
423         
424 }
425
426 void
427 mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint8 local, gint8 incr)
428 {
429         mono_mb_emit_ldloc (mb, local); 
430         mono_mb_emit_icon (mb, incr);
431         mono_mb_emit_byte (mb, CEE_ADD);
432         mono_mb_emit_stloc (mb, local); 
433 }
434
435 static void
436 emit_ptr_to_str_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, 
437                       int usize, int msize)
438 {
439         switch (conv) {
440         case MONO_MARSHAL_CONV_BOOL_I4:
441                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
442                 mono_mb_emit_byte (mb, CEE_LDIND_I);
443                 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
444                 mono_mb_emit_byte (mb, 5);
445                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
446                 mono_mb_emit_byte (mb, CEE_LDC_I4_1);
447                 mono_mb_emit_byte (mb, CEE_STIND_I1);
448                 mono_mb_emit_byte (mb, CEE_BR_S);
449                 mono_mb_emit_byte (mb, 3);
450                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
451                 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
452                 mono_mb_emit_byte (mb, CEE_STIND_I1);
453                 break;
454         case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
455                 MonoClass *eclass;
456                 int esize;
457
458                 if (type->type == MONO_TYPE_ARRAY)
459                         eclass = mono_class_from_mono_type (type->data.array->type);
460                 else if (type->type == MONO_TYPE_SZARRAY) {
461                         eclass = mono_class_from_mono_type (type->data.type);
462                 } else {
463                         g_assert_not_reached ();
464                 }
465
466                 if (eclass->valuetype)
467                         esize = mono_class_instance_size (eclass) - sizeof (MonoObject);
468                 else
469                         esize = sizeof (gpointer);
470
471                 /* create a new array */
472                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
473                 mono_mb_emit_icon (mb, msize / esize);
474                 mono_mb_emit_byte (mb, CEE_NEWARR);     
475                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eclass));
476                 mono_mb_emit_byte (mb, CEE_STIND_I);
477
478                 /* copy the elements */
479                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
480                 mono_mb_emit_byte (mb, CEE_LDIND_I);
481                 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
482                 mono_mb_emit_byte (mb, CEE_ADD);
483                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
484                 mono_mb_emit_icon (mb, usize);
485                 mono_mb_emit_byte (mb, CEE_PREFIX1);
486                 mono_mb_emit_byte (mb, CEE_CPBLK);                      
487
488                 break;
489         }
490         case MONO_MARSHAL_CONV_STR_BYVALSTR: 
491                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
492                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
493                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
494                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
495                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
496                 mono_mb_emit_byte (mb, CEE_STIND_I);            
497                 break;
498         case MONO_MARSHAL_CONV_STR_LPTSTR:
499         case MONO_MARSHAL_CONV_STR_LPSTR:
500                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
501                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
502                 mono_mb_emit_byte (mb, CEE_LDIND_I);
503                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
504                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
505                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
506                 mono_mb_emit_byte (mb, CEE_STIND_I);            
507                 break;
508         case MONO_MARSHAL_CONV_STR_LPWSTR:
509         case MONO_MARSHAL_CONV_STR_BSTR:
510         case MONO_MARSHAL_CONV_STR_ANSIBSTR:
511         case MONO_MARSHAL_CONV_STR_TBSTR:
512         case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
513         case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
514         case MONO_MARSHAL_CONV_STR_BYVALWSTR: 
515         case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
516         default:
517                 g_warning ("marshalling conversion %d not implemented", conv);
518                 g_assert_not_reached ();
519         }
520 }
521
522 static void
523 emit_str_to_ptr_conv (MonoMethodBuilder *mb, MonoMarshalConv conv, int usize, int msize)
524 {
525         switch (conv) {
526         case MONO_MARSHAL_CONV_BOOL_I4:
527                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
528                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
529                 mono_mb_emit_byte (mb, CEE_LDIND_U1);
530                 mono_mb_emit_byte (mb, CEE_STIND_I4);
531                 break;
532         case MONO_MARSHAL_CONV_STR_LPWSTR:
533         case MONO_MARSHAL_CONV_STR_LPSTR:
534         case MONO_MARSHAL_CONV_STR_LPTSTR:
535         case MONO_MARSHAL_CONV_STR_BSTR:
536         case MONO_MARSHAL_CONV_STR_ANSIBSTR:
537         case MONO_MARSHAL_CONV_STR_TBSTR:
538         case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
539         case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
540                 /* free space if free == true */
541                 mono_mb_emit_byte (mb, CEE_LDLOC_2);
542                 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
543                 mono_mb_emit_byte (mb, 4);
544                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
545                 mono_mb_emit_byte (mb, CEE_LDIND_I);
546                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
547                 mono_mb_emit_byte (mb, CEE_MONO_FREE);
548
549                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
550                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
551                 mono_mb_emit_byte (mb, CEE_LDIND_I);
552                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
553                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
554                 mono_mb_emit_byte (mb, conv);
555                 mono_mb_emit_byte (mb, CEE_STIND_I);    
556                 break;
557         case MONO_MARSHAL_CONV_STR_BYVALSTR: 
558         case MONO_MARSHAL_CONV_STR_BYVALWSTR: {
559                 if (!usize)
560                         break;
561
562                 mono_mb_emit_byte (mb, CEE_LDLOC_1); /* dst */
563                 mono_mb_emit_byte (mb, CEE_LDLOC_0);    
564                 mono_mb_emit_byte (mb, CEE_LDIND_I); /* src String */
565                 mono_mb_emit_icon (mb, usize);
566                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
567                 mono_mb_emit_byte (mb, CEE_MONO_PROC3);
568                 mono_mb_emit_byte (mb, conv);
569                 break;
570         }
571         case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
572                 if (!usize) 
573                         break;
574
575                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
576                 mono_mb_emit_byte (mb, CEE_LDIND_I);            
577                 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
578                 mono_mb_emit_byte (mb, 15);
579
580                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
581                 mono_mb_emit_byte (mb, CEE_LDLOC_0);    
582                 mono_mb_emit_byte (mb, CEE_LDIND_I);    
583                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
584                 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
585                 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
586                 mono_mb_emit_byte (mb, CEE_ADD);
587                 mono_mb_emit_icon (mb, usize);
588                 mono_mb_emit_byte (mb, CEE_PREFIX1);
589                 mono_mb_emit_byte (mb, CEE_CPBLK);                      
590                 break;
591         }
592         case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
593         default:
594                 g_warning ("marshalling conversion %d not implemented", conv);
595                 g_assert_not_reached ();
596         }
597 }
598
599 static void
600 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
601 {
602         MonoMarshalType *info;
603         int i;
604
605         info = mono_marshal_load_type_info (klass);
606
607         for (i = 0; i < info->num_fields; i++) {
608                 MonoMarshalNative ntype;
609                 MonoMarshalConv conv;
610                 MonoType *ftype = info->fields [i].field->type;
611                 int msize = 0;
612                 int usize = 0;
613                 gboolean last_field = i < (info->num_fields -1) ? 0 : 1;
614
615                 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
616                         continue;
617
618                 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, klass->unicode, &conv);
619                         
620                 if (last_field) {
621                         msize = klass->instance_size - info->fields [i].field->offset;
622                         usize = info->native_size - info->fields [i].offset;
623                 } else {
624                         msize = klass->fields [i + 1].offset - info->fields [i].field->offset;
625                         usize = info->fields [i + 1].offset - info->fields [i].offset;
626                 }
627                 g_assert (msize > 0 && usize > 0);
628
629                 switch (conv) {
630                 case MONO_MARSHAL_CONV_NONE:
631
632                         if (ftype->byref || ftype->type == MONO_TYPE_I ||
633                             ftype->type == MONO_TYPE_U) {
634                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
635                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
636                                 mono_mb_emit_byte (mb, CEE_LDIND_I);
637                                 mono_mb_emit_byte (mb, CEE_STIND_I);
638                                 break;
639                         }
640
641                         switch (ftype->type) {
642                         case MONO_TYPE_I4:
643                         case MONO_TYPE_U4:
644                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
645                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
646                                 mono_mb_emit_byte (mb, CEE_LDIND_I4);
647                                 mono_mb_emit_byte (mb, CEE_STIND_I4);
648                                 break;
649                         case MONO_TYPE_I1:
650                         case MONO_TYPE_U1:
651                         case MONO_TYPE_BOOLEAN:
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_I1);
655                                 mono_mb_emit_byte (mb, CEE_STIND_I1);
656                                 break;
657                         case MONO_TYPE_I2:
658                         case MONO_TYPE_U2:
659                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
660                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
661                                 mono_mb_emit_byte (mb, CEE_LDIND_I2);
662                                 mono_mb_emit_byte (mb, CEE_STIND_I2);
663                                 break;
664                         case MONO_TYPE_I8:
665                         case MONO_TYPE_U8:
666                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
667                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
668                                 mono_mb_emit_byte (mb, CEE_LDIND_I8);
669                                 mono_mb_emit_byte (mb, CEE_STIND_I8);
670                                 break;
671                         case MONO_TYPE_R4:
672                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
673                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
674                                 mono_mb_emit_byte (mb, CEE_LDIND_R4);
675                                 mono_mb_emit_byte (mb, CEE_STIND_R4);
676                                 break;
677                         case MONO_TYPE_R8:
678                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
679                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
680                                 mono_mb_emit_byte (mb, CEE_LDIND_R8);
681                                 mono_mb_emit_byte (mb, CEE_STIND_R8);
682                                 break;
683                         case MONO_TYPE_VALUETYPE:
684                                 emit_struct_conv (mb, ftype->data.klass, to_object);
685                                 continue;
686                         default:
687                                 g_error ("marshalling type %02x not implemented", ftype->type);
688                         }
689                         break;
690
691                 default:
692                         if (to_object) 
693                                 emit_ptr_to_str_conv (mb, ftype, conv, usize, msize);
694                         else
695                                 emit_str_to_ptr_conv (mb, conv, usize, msize);  
696                 }
697
698                 if (to_object) {
699                         mono_mb_emit_add_to_local (mb, 0, usize);
700                         mono_mb_emit_add_to_local (mb, 1, msize);
701                 } else {
702                         mono_mb_emit_add_to_local (mb, 0, msize);
703                         mono_mb_emit_add_to_local (mb, 1, usize);
704                 }               
705         }
706 }
707
708 static MonoAsyncResult *
709 mono_delegate_begin_invoke (MonoDelegate *delegate, gpointer *params)
710 {
711         MonoMethodMessage *msg;
712         MonoDelegate *async_callback;
713         MonoObject *state;
714         MonoMethod *im;
715         MonoClass *klass;
716         MonoMethod *method = NULL;
717         int i;
718
719         g_assert (delegate);
720
721         klass = delegate->object.vtable->klass;
722
723         method = mono_get_delegate_invoke (klass);
724         for (i = 0; i < klass->method.count; ++i) {
725                 if (klass->methods [i]->name[0] == 'B' && 
726                     !strcmp ("BeginInvoke", klass->methods [i]->name)) {
727                         method = klass->methods [i];
728                         break;
729                 }
730         }
731
732         g_assert (method != NULL);
733
734         im = mono_get_delegate_invoke (method->klass);
735         
736         msg = mono_method_call_message_new (method, params, im, &async_callback, &state);
737
738         return mono_thread_pool_add ((MonoObject *)delegate, msg, async_callback, state);
739 }
740
741 static int
742 mono_mb_emit_save_args (MonoMethodBuilder *mb, MonoMethodSignature *sig, gboolean save_this)
743 {
744         int i, params_var, tmp_var;
745
746         /* allocate local (pointer) *params[] */
747         params_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
748         /* allocate local (pointer) tmp */
749         tmp_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
750
751         /* alloate space on stack to store an array of pointers to the arguments */
752         mono_mb_emit_icon (mb, sizeof (gpointer) * (sig->param_count + 1));
753         mono_mb_emit_byte (mb, CEE_PREFIX1);
754         mono_mb_emit_byte (mb, CEE_LOCALLOC);
755         mono_mb_emit_stloc (mb, params_var);
756
757         /* tmp = params */
758         mono_mb_emit_ldloc (mb, params_var);
759         mono_mb_emit_stloc (mb, tmp_var);
760
761         if (save_this && sig->hasthis) {
762                 mono_mb_emit_ldloc (mb, tmp_var);
763                 mono_mb_emit_ldarg_addr (mb, 0);
764                 mono_mb_emit_byte (mb, CEE_STIND_I);
765                 /* tmp = tmp + sizeof (gpointer) */
766                 if (sig->param_count)
767                         mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
768
769         }
770
771         for (i = 0; i < sig->param_count; i++) {
772                 mono_mb_emit_ldloc (mb, tmp_var);
773                 mono_mb_emit_ldarg_addr (mb, i + sig->hasthis);
774                 mono_mb_emit_byte (mb, CEE_STIND_I);
775                 /* tmp = tmp + sizeof (gpointer) */
776                 if (i < (sig->param_count - 1))
777                         mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
778         }
779
780         return params_var;
781 }
782
783 static char*
784 mono_signature_to_name (MonoMethodSignature *sig, const char *prefix)
785 {
786         int i;
787         char *result;
788         GString *res = g_string_new ("");
789
790         if (prefix) {
791                 g_string_append (res, prefix);
792                 g_string_append_c (res, '_');
793         }
794
795         mono_type_get_desc (res, sig->ret, FALSE);
796
797         for (i = 0; i < sig->param_count; ++i) {
798                 g_string_append_c (res, '_');
799                 mono_type_get_desc (res, sig->params [i], FALSE);
800         }
801         result = res->str;
802         g_string_free (res, FALSE);
803         return result;
804 }
805
806 MonoMethod *
807 mono_marshal_get_delegate_begin_invoke (MonoMethod *method)
808 {
809         MonoMethodSignature *sig;
810         static MonoMethodSignature *csig = NULL;
811         MonoMethodBuilder *mb;
812         MonoMethod *res;
813         GHashTable *cache;
814         int params_var;
815         char *name;
816
817         g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
818                   !strcmp (method->name, "BeginInvoke"));
819
820         sig = method->signature;
821
822         cache = method->klass->image->delegate_begin_invoke_cache;
823         if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
824                 return res;
825
826         g_assert (sig->hasthis);
827
828         if (!csig) {
829                 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
830                 csig = g_malloc0 (sigsize);
831
832                 /* MonoAsyncResult * begin_invoke (MonoDelegate *delegate, gpointer params[]) */
833                 csig->param_count = 2;
834                 csig->ret = &mono_defaults.object_class->byval_arg;
835                 csig->params [0] = &mono_defaults.object_class->byval_arg;
836                 csig->params [1] = &mono_defaults.int_class->byval_arg;
837         }
838
839         name = mono_signature_to_name (sig, "begin_invoke");
840         mb = mono_mb_new (mono_defaults.multicastdelegate_class, name);
841         g_free (name);
842
843         mb->method->wrapper_type = MONO_WRAPPER_DELEGATE_BEGIN_INVOKE;
844         mb->method->save_lmf = 1;
845
846         params_var = mono_mb_emit_save_args (mb, sig, FALSE);
847
848         mono_mb_emit_ldarg (mb, 0);
849         mono_mb_emit_ldloc (mb, params_var);
850         mono_mb_emit_native_call (mb, csig, mono_delegate_begin_invoke);
851         mono_mb_emit_byte (mb, CEE_RET);
852
853         res = mono_mb_create_method (mb, sig, 0);
854         mono_mb_free (mb);
855         g_hash_table_insert (cache, sig, res);
856         return res;
857 }
858
859 static MonoObject *
860 mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params)
861 {
862         MonoDomain *domain = mono_domain_get ();
863         MonoAsyncResult *ares;
864         MonoMethod *method = NULL;
865         MonoMethodSignature *sig;
866         MonoMethodMessage *msg;
867         MonoObject *res, *exc;
868         MonoArray *out_args;
869         MonoClass *klass;
870         int i;
871
872         g_assert (delegate);
873
874         if (!delegate->method_info || !delegate->method_info->method)
875                 g_assert_not_reached ();
876
877         klass = delegate->object.vtable->klass;
878
879         for (i = 0; i < klass->method.count; ++i) {
880                 if (klass->methods [i]->name[0] == 'E' && 
881                     !strcmp ("EndInvoke", klass->methods [i]->name)) {
882                         method = klass->methods [i];
883                         break;
884                 }
885         }
886
887         g_assert (method != NULL);
888
889         sig = method->signature;
890
891         msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
892
893         ares = mono_array_get (msg->args, gpointer, sig->param_count - 1);
894         g_assert (ares);
895
896         res = mono_thread_pool_finish (ares, &out_args, &exc);
897
898         if (exc) {
899                 char *strace = mono_string_to_utf8 (((MonoException*)exc)->stack_trace);
900                 char  *tmp;
901                 tmp = g_strdup_printf ("%s\nException Rethrown at:\n", strace);
902                 g_free (strace);        
903                 ((MonoException*)exc)->stack_trace = mono_string_new (domain, tmp);
904                 g_free (tmp);
905                 mono_raise_exception ((MonoException*)exc);
906         }
907
908         mono_method_return_message_restore (method, params, out_args);
909         return res;
910 }
911
912 static void
913 mono_mb_emit_restore_result (MonoMethodBuilder *mb, MonoType *return_type)
914 {
915         if (return_type->byref)
916                 return_type = &mono_defaults.int_class->byval_arg;
917         else if (return_type->type == MONO_TYPE_VALUETYPE && return_type->data.klass->enumtype)
918                 return_type = return_type->data.klass->enum_basetype;
919
920         switch (return_type->type) {
921         case MONO_TYPE_VOID:
922                 g_assert_not_reached ();
923                 break;
924         case MONO_TYPE_STRING:
925         case MONO_TYPE_CLASS: 
926         case MONO_TYPE_OBJECT: 
927         case MONO_TYPE_ARRAY: 
928         case MONO_TYPE_SZARRAY: 
929                 /* nothing to do */
930                 break;
931         case MONO_TYPE_U1:
932         case MONO_TYPE_BOOLEAN:
933                 mono_mb_emit_byte (mb, CEE_UNBOX);
934                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
935                 mono_mb_emit_byte (mb, CEE_LDIND_U1);
936                 break;
937         case MONO_TYPE_I1:
938                 mono_mb_emit_byte (mb, CEE_UNBOX);
939                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
940                 mono_mb_emit_byte (mb, CEE_LDIND_I1);
941                 break;
942         case MONO_TYPE_U2:
943         case MONO_TYPE_CHAR:
944                 mono_mb_emit_byte (mb, CEE_UNBOX);
945                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
946                 mono_mb_emit_byte (mb, CEE_LDIND_U2);
947                 break;
948         case MONO_TYPE_I2:
949                 mono_mb_emit_byte (mb, CEE_UNBOX);
950                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
951                 mono_mb_emit_byte (mb, CEE_LDIND_I2);
952                 break;
953 #if SIZEOF_VOID_P == 4
954         case MONO_TYPE_I:
955 #endif
956         case MONO_TYPE_I4:
957                 mono_mb_emit_byte (mb, CEE_UNBOX);
958                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
959                 mono_mb_emit_byte (mb, CEE_LDIND_I4);
960                 break;
961 #if SIZEOF_VOID_P == 4
962         case MONO_TYPE_U:
963 #endif
964         case MONO_TYPE_U4:
965                 mono_mb_emit_byte (mb, CEE_UNBOX);
966                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
967                 mono_mb_emit_byte (mb, CEE_LDIND_U4);
968                 break;
969         case MONO_TYPE_U8:
970         case MONO_TYPE_I8:
971                 mono_mb_emit_byte (mb, CEE_UNBOX);
972                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
973                 mono_mb_emit_byte (mb, CEE_LDIND_I8);
974                 break;
975         case MONO_TYPE_R4:
976                 mono_mb_emit_byte (mb, CEE_UNBOX);
977                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
978                 mono_mb_emit_byte (mb, CEE_LDIND_R4);
979                 break;
980         case MONO_TYPE_R8:
981                 mono_mb_emit_byte (mb, CEE_UNBOX);
982                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
983                 mono_mb_emit_byte (mb, CEE_LDIND_R8);
984                 break;
985         case MONO_TYPE_VALUETYPE: {
986                 int class;
987                 mono_mb_emit_byte (mb, CEE_UNBOX);
988                 class = mono_mb_add_data (mb, mono_class_from_mono_type (return_type));
989                 mono_mb_emit_i4 (mb, class);
990                 mono_mb_emit_byte (mb, CEE_LDOBJ);
991                 mono_mb_emit_i4 (mb, class);
992                 break;
993         }
994         default:
995                 g_warning ("type 0x%x not handled", return_type->type);
996                 g_assert_not_reached ();
997         }
998
999         mono_mb_emit_byte (mb, CEE_RET);
1000 }
1001
1002 MonoMethod *
1003 mono_marshal_get_delegate_end_invoke (MonoMethod *method)
1004 {
1005         MonoMethodSignature *sig;
1006         static MonoMethodSignature *csig = NULL;
1007         MonoMethodBuilder *mb;
1008         MonoMethod *res;
1009         GHashTable *cache;
1010         int params_var;
1011         char *name;
1012
1013         g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1014                   !strcmp (method->name, "EndInvoke"));
1015
1016         sig = method->signature;
1017
1018         cache = method->klass->image->delegate_end_invoke_cache;
1019         if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1020                 return res;
1021
1022         g_assert (sig->hasthis);
1023
1024         if (!csig) {
1025                 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1026                 csig = g_malloc0 (sigsize);
1027
1028                 /* MonoObject *end_invoke (MonoDelegate *delegate, gpointer params[]) */
1029                 csig->param_count = 2;
1030                 csig->ret = &mono_defaults.object_class->byval_arg;
1031                 csig->params [0] = &mono_defaults.object_class->byval_arg;
1032                 csig->params [1] = &mono_defaults.int_class->byval_arg;
1033         }
1034
1035         name = mono_signature_to_name (sig, "end_invoke");
1036         mb = mono_mb_new (mono_defaults.multicastdelegate_class, name);
1037         g_free (name);
1038
1039         mb->method->wrapper_type = MONO_WRAPPER_DELEGATE_END_INVOKE;
1040         mb->method->save_lmf = 1;
1041
1042         params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1043
1044         mono_mb_emit_ldarg (mb, 0);
1045         mono_mb_emit_ldloc (mb, params_var);
1046         mono_mb_emit_native_call (mb, csig, mono_delegate_end_invoke);
1047
1048         if (sig->ret->type == MONO_TYPE_VOID)
1049                 mono_mb_emit_byte (mb, CEE_POP);
1050         else
1051                 mono_mb_emit_restore_result (mb, sig->ret);
1052
1053         res = mono_mb_create_method (mb, sig, 0);
1054         mono_mb_free (mb);
1055         g_hash_table_insert (cache, sig, res);
1056         return res;
1057 }
1058
1059 static MonoObject *
1060 mono_remoting_wrapper (MonoMethod *method, gpointer *params)
1061 {
1062         MonoMethodMessage *msg;
1063         MonoTransparentProxy *this;
1064         MonoObject *res, *exc;
1065         MonoArray *out_args;
1066
1067         this = *((MonoTransparentProxy **)params [0]);
1068
1069         g_assert (this);
1070         g_assert (((MonoObject *)this)->vtable->klass == mono_defaults.transparent_proxy_class);
1071         
1072         /* skip the this pointer */
1073         params++;
1074
1075         msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1076
1077         res = mono_remoting_invoke ((MonoObject *)this->rp, msg, &exc, &out_args);
1078
1079         if (exc)
1080                 mono_raise_exception ((MonoException *)exc);
1081
1082         mono_method_return_message_restore (method, params, out_args);
1083
1084         return res;
1085
1086
1087 MonoMethod *
1088 mono_marshal_get_remoting_invoke (MonoMethod *method)
1089 {
1090         MonoMethodSignature *sig;
1091         static MonoMethodSignature *csig = NULL;
1092         MonoMethodBuilder *mb;
1093         MonoMethod *res;
1094         GHashTable *cache;
1095         int params_var;
1096
1097         g_assert (method);
1098
1099         if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE)
1100                 return method;
1101
1102         sig = method->signature;
1103
1104         /* we cant remote methods without this pointer */
1105         if (!sig->hasthis)
1106                 return method;
1107
1108         cache = method->klass->image->remoting_invoke_cache;
1109         if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1110                 return res;
1111
1112         if (!csig) {
1113                 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1114                 csig = g_malloc0 (sigsize);
1115
1116                 /* MonoObject *remoting_wrapper (MonoMethod *method, gpointer params[]) */
1117                 csig->param_count = 2;
1118                 csig->ret = &mono_defaults.object_class->byval_arg;
1119                 csig->params [0] = &mono_defaults.int_class->byval_arg;
1120                 csig->params [1] = &mono_defaults.int_class->byval_arg;
1121         }
1122
1123         mb = mono_mb_new (method->klass, method->name);
1124         mb->method->wrapper_type = MONO_WRAPPER_REMOTING_INVOKE;
1125
1126         params_var = mono_mb_emit_save_args (mb, sig, TRUE);
1127
1128         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1129         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1130         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
1131         mono_mb_emit_ldloc (mb, params_var);
1132         mono_mb_emit_native_call (mb, csig, mono_remoting_wrapper);
1133
1134         if (sig->ret->type == MONO_TYPE_VOID)
1135                 mono_mb_emit_byte (mb, CEE_POP);
1136         else
1137                 mono_mb_emit_restore_result (mb, sig->ret);
1138
1139         res = mono_mb_create_method (mb, sig, 0);
1140         mono_mb_free (mb);
1141         g_hash_table_insert (cache, method, res);
1142         return res;
1143 }
1144
1145 /*
1146  * the returned method invokes all methods in a multicast delegate 
1147  */
1148 MonoMethod *
1149 mono_marshal_get_delegate_invoke (MonoMethod *method)
1150 {
1151         MonoMethodSignature *sig, *static_sig;
1152         int i, sigsize;
1153         MonoMethodBuilder *mb;
1154         MonoMethod *res;
1155         GHashTable *cache;
1156         int pos [3];
1157         char *name;
1158
1159         g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1160                   !strcmp (method->name, "Invoke"));
1161                 
1162         sig = method->signature;
1163
1164         cache = method->klass->image->delegate_invoke_cache;
1165         if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1166                 return res;
1167
1168         sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1169         static_sig = g_memdup (sig, sigsize);
1170         static_sig->hasthis = 0;
1171
1172         name = mono_signature_to_name (sig, "invoke");
1173         mb = mono_mb_new (mono_defaults.multicastdelegate_class, name);
1174         g_free (name);
1175
1176         mb->method->wrapper_type = MONO_WRAPPER_DELEGATE_INVOKE;
1177
1178         /* allocate local 0 (object) prev */
1179         mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1180         /* allocate local 1 (object) target */
1181         mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1182         /* allocate local 2 (pointer) mptr */
1183         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1184
1185         /* allocate local 3 to store the return value */
1186         if (sig->ret->type != MONO_TYPE_VOID)
1187                 mono_mb_add_local (mb, sig->ret);
1188
1189         g_assert (sig->hasthis);
1190
1191         /* prev = addr of delegate */
1192         mono_mb_emit_ldarg (mb, 0);
1193         mono_mb_emit_stloc (mb, 0);
1194
1195         /* loop */
1196         pos [0] = mb->pos;
1197         /* target = delegate->target */
1198         mono_mb_emit_ldloc (mb, 0);
1199         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1200         mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
1201         mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoDelegate, target));
1202         mono_mb_emit_byte (mb, CEE_ADD);
1203         mono_mb_emit_byte (mb, CEE_LDIND_I);
1204         mono_mb_emit_stloc (mb, 1);
1205
1206         /* mptr = delegate->method_ptr */
1207         mono_mb_emit_ldloc (mb, 0);
1208         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1209         mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
1210         mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1211         mono_mb_emit_byte (mb, CEE_ADD);
1212         mono_mb_emit_byte (mb, CEE_LDIND_I);
1213         mono_mb_emit_stloc (mb, 2);
1214
1215         /* target == null ? */
1216         mono_mb_emit_ldloc (mb, 1);
1217         mono_mb_emit_byte (mb, CEE_BRTRUE); 
1218         pos [1] = mb->pos;
1219         mono_mb_emit_i4 (mb, 0);
1220
1221         /* emit static method call */
1222
1223         for (i = 0; i < sig->param_count; i++)
1224                 mono_mb_emit_ldarg (mb, i + 1);
1225
1226         mono_mb_emit_ldloc (mb, 2);
1227         mono_mb_emit_byte (mb, CEE_CALLI);
1228         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, static_sig));
1229
1230         if (sig->ret->type != MONO_TYPE_VOID)
1231                 mono_mb_emit_stloc (mb, 3);
1232
1233         mono_mb_emit_byte (mb, CEE_BR);
1234         pos [2] = mb->pos;
1235         mono_mb_emit_i4 (mb, 0);
1236    
1237         /* target != null, emit non static method call */
1238
1239         mono_mb_patch_addr (mb, pos [1], mb->pos - (pos [1] + 4));
1240         mono_mb_emit_ldloc (mb, 1);
1241
1242         for (i = 0; i < sig->param_count; i++)
1243                 mono_mb_emit_ldarg (mb, i + 1);
1244         
1245         mono_mb_emit_ldloc (mb, 2);
1246         mono_mb_emit_byte (mb, CEE_CALLI);
1247         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
1248
1249         if (sig->ret->type != MONO_TYPE_VOID)
1250                 mono_mb_emit_stloc (mb, 3);
1251
1252         mono_mb_patch_addr (mb, pos [2], mb->pos - (pos [2] + 4));
1253
1254         /* prev = delegate->prev */
1255         mono_mb_emit_ldloc (mb, 0);
1256         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1257         mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
1258         mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoMulticastDelegate, prev));
1259         mono_mb_emit_byte (mb, CEE_ADD);
1260         mono_mb_emit_byte (mb, CEE_LDIND_I);
1261         mono_mb_emit_stloc (mb, 0);
1262
1263         /* if prev != null goto loop */
1264         mono_mb_emit_ldloc (mb, 0);
1265         mono_mb_emit_byte (mb, CEE_BRTRUE);
1266         mono_mb_emit_i4 (mb, pos [0] - (mb->pos + 4));
1267
1268         if (sig->ret->type != MONO_TYPE_VOID)
1269                 mono_mb_emit_ldloc (mb, 3);
1270
1271         mono_mb_emit_byte (mb, CEE_RET);
1272
1273         res = mono_mb_create_method (mb, sig, 0);
1274         mono_mb_free (mb);
1275
1276         g_hash_table_insert (cache, sig, res);
1277
1278         return res;     
1279 }
1280
1281 /*
1282  * generates IL code for the runtime invoke function 
1283  * MonoObject *runtime_invoke (MonoObject *this, void **params, MonoObject **exc)
1284  *
1285  * we also catch exceptions if exc != null
1286  */
1287 MonoMethod *
1288 mono_marshal_get_runtime_invoke (MonoMethod *method)
1289 {
1290         MonoMethodSignature *sig, *csig;
1291         MonoExceptionClause *clause;
1292         MonoMethodHeader *header;
1293         MonoMethodBuilder *mb;
1294         MonoMethod *res;
1295         GHashTable *cache;
1296         static MonoString *string_dummy = NULL;
1297         int i, pos, sigsize;
1298
1299         g_assert (method);
1300
1301         cache = method->klass->image->runtime_invoke_cache;
1302         if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1303                 return res;
1304         
1305         /* to make it work with our special string constructors */
1306         if (!string_dummy)
1307                 string_dummy = mono_string_new_wrapper ("dummy");
1308
1309         sig = method->signature;
1310
1311         sigsize = sizeof (MonoMethodSignature) + 3 * sizeof (MonoType *);
1312         csig = g_malloc0 (sigsize);
1313
1314         csig->param_count = 3;
1315         csig->ret = &mono_defaults.object_class->byval_arg;
1316         csig->params [0] = &mono_defaults.object_class->byval_arg;
1317         csig->params [1] = &mono_defaults.int_class->byval_arg;
1318         csig->params [2] = &mono_defaults.int_class->byval_arg;
1319
1320         mb = mono_mb_new (method->klass, method->name);
1321         mb->method->wrapper_type = MONO_WRAPPER_RUNTIME_INVOKE;
1322
1323         /* allocate local 0 (object) tmp */
1324         mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1325         /* allocate local 1 (object) exc */
1326         mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1327
1328         /* cond set *exc to null */
1329         mono_mb_emit_byte (mb, CEE_LDARG_2);
1330         mono_mb_emit_byte (mb, CEE_BRFALSE_S);
1331         mono_mb_emit_byte (mb, 3);      
1332         mono_mb_emit_byte (mb, CEE_LDARG_2);
1333         mono_mb_emit_byte (mb, CEE_LDNULL);
1334         mono_mb_emit_byte (mb, CEE_STIND_I);
1335
1336         if (sig->hasthis) {
1337                 if (method->string_ctor) {
1338                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1339                         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1340                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, string_dummy));
1341                 } else {
1342                         mono_mb_emit_ldarg (mb, 0);
1343                 }
1344         }
1345
1346         for (i = 0; i < sig->param_count; i++) {
1347                 MonoType *t = sig->params [i];
1348                 int type;
1349
1350                 mono_mb_emit_ldarg (mb, 1);
1351                 if (i) {
1352                         mono_mb_emit_icon (mb, sizeof (gpointer) * i);
1353                         mono_mb_emit_byte (mb, CEE_ADD);
1354                 }
1355                 mono_mb_emit_byte (mb, CEE_LDIND_I);
1356
1357                 if (t->byref)
1358                         continue;
1359
1360                 type = sig->params [i]->type;
1361 handle_enum:
1362                 switch (type) {
1363                 case MONO_TYPE_I1:
1364                         mono_mb_emit_byte (mb, CEE_LDIND_I1);
1365                         break;
1366                 case MONO_TYPE_BOOLEAN:
1367                 case MONO_TYPE_U1:
1368                         mono_mb_emit_byte (mb, CEE_LDIND_U1);
1369                         break;
1370                 case MONO_TYPE_I2:
1371                         mono_mb_emit_byte (mb, CEE_LDIND_I2);
1372                         break;
1373                 case MONO_TYPE_U2:
1374                 case MONO_TYPE_CHAR:
1375                         mono_mb_emit_byte (mb, CEE_LDIND_U2);
1376                         break;
1377 #if SIZEOF_VOID_P == 4
1378                 case MONO_TYPE_I:
1379 #endif
1380                 case MONO_TYPE_I4:
1381                         mono_mb_emit_byte (mb, CEE_LDIND_I4);
1382                         break;
1383 #if SIZEOF_VOID_P == 4
1384                 case MONO_TYPE_U:
1385 #endif
1386                 case MONO_TYPE_U4:
1387                         mono_mb_emit_byte (mb, CEE_LDIND_U4);
1388                         break;
1389                 case MONO_TYPE_R4:
1390                         mono_mb_emit_byte (mb, CEE_LDIND_R4);
1391                         break;
1392                 case MONO_TYPE_R8:
1393                         mono_mb_emit_byte (mb, CEE_LDIND_R8);
1394                         break;
1395 #if SIZEOF_VOID_P == 8
1396                 case MONO_TYPE_I:
1397                 case MONO_TYPE_U:
1398 #endif
1399                 case MONO_TYPE_I8:
1400                 case MONO_TYPE_U8:
1401                         mono_mb_emit_byte (mb, CEE_LDIND_I8);
1402                         break;
1403                 case MONO_TYPE_STRING:
1404                 case MONO_TYPE_CLASS:  
1405                 case MONO_TYPE_ARRAY:
1406                 case MONO_TYPE_PTR:
1407                 case MONO_TYPE_SZARRAY:
1408                 case MONO_TYPE_OBJECT:
1409                         /* do nothing */
1410                         break;
1411                 case MONO_TYPE_VALUETYPE:
1412                         if (t->data.klass->enumtype) {
1413                                 type = t->data.klass->enum_basetype->type;
1414                                 goto handle_enum;
1415                         }
1416                         g_assert_not_reached ();
1417                         break;
1418                 default:
1419                         g_assert_not_reached ();
1420                 }               
1421         }
1422
1423         if (method->string_ctor) {
1424                 MonoMethodSignature *strsig;
1425
1426                 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1427                 strsig = g_memdup (sig, sigsize);
1428                 strsig->ret = &mono_defaults.string_class->byval_arg;
1429
1430                 mono_mb_emit_managed_call (mb, method, strsig);         
1431         } else 
1432                 mono_mb_emit_managed_call (mb, method, NULL);
1433         
1434         switch (sig->ret->type) {
1435         case MONO_TYPE_VOID:
1436                 if (!method->string_ctor)
1437                         mono_mb_emit_byte (mb, CEE_LDNULL);
1438                 break;
1439         case MONO_TYPE_I1:
1440         case MONO_TYPE_U1:
1441         case MONO_TYPE_I2:
1442         case MONO_TYPE_U2:
1443         case MONO_TYPE_I4:
1444         case MONO_TYPE_U4:
1445         case MONO_TYPE_I:
1446         case MONO_TYPE_U:
1447         case MONO_TYPE_R4:
1448         case MONO_TYPE_R8:
1449         case MONO_TYPE_I8:
1450         case MONO_TYPE_U8:
1451         case MONO_TYPE_VALUETYPE:
1452                 /* box value types */
1453                 mono_mb_emit_byte (mb, CEE_BOX);
1454                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (sig->ret)));
1455                 break;
1456         case MONO_TYPE_STRING:
1457         case MONO_TYPE_CLASS:  
1458         case MONO_TYPE_ARRAY:
1459         case MONO_TYPE_SZARRAY:
1460         case MONO_TYPE_OBJECT:
1461                 /* nothing to do */
1462                 break;
1463         case MONO_TYPE_PTR:
1464         default:
1465                 g_assert_not_reached ();
1466         }
1467
1468         mono_mb_emit_stloc (mb, 0);
1469                 
1470         mono_mb_emit_byte (mb, CEE_LEAVE);
1471         pos = mb->pos;
1472         mono_mb_emit_i4 (mb, 0);
1473
1474         /* fixme: use a filter clause and only catch exceptions
1475          * when exc != null. With RETHROW we get wrong stack 
1476          * traces. */
1477         clause = g_new0 (MonoExceptionClause, 1);
1478         clause->flags = MONO_EXCEPTION_CLAUSE_NONE;
1479         clause->try_offset = 0;
1480         clause->try_len = mb->pos;
1481         clause->handler_offset = mb->pos;
1482
1483         /* handler code */
1484
1485         /* store exception */
1486         mono_mb_emit_stloc (mb, 1);
1487         
1488         mono_mb_emit_byte (mb, CEE_LDARG_2);
1489         mono_mb_emit_byte (mb, CEE_BRTRUE_S);
1490         mono_mb_emit_byte (mb, 2);
1491         mono_mb_emit_byte (mb, CEE_PREFIX1);
1492         mono_mb_emit_byte (mb, CEE_RETHROW);
1493         
1494         mono_mb_emit_byte (mb, CEE_LDARG_2);
1495         mono_mb_emit_ldloc (mb, 1);
1496         mono_mb_emit_byte (mb, CEE_STIND_I);
1497
1498         mono_mb_emit_byte (mb, CEE_LEAVE);
1499         mono_mb_emit_i4 (mb, 0);
1500
1501         clause->handler_len = mb->pos - clause->handler_offset;
1502
1503         /* return result */
1504         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1505         mono_mb_emit_ldloc (mb, 0);
1506         mono_mb_emit_byte (mb, CEE_RET);
1507         
1508         res = mono_mb_create_method (mb, csig, 0);
1509         mono_mb_free (mb);
1510
1511         header = ((MonoMethodNormal *)res)->header;
1512         header->num_clauses = 1;
1513         header->clauses = clause;
1514
1515         g_hash_table_insert (cache, method, res);
1516
1517         return res;     
1518 }
1519
1520 /*
1521  * generates IL code to call managed methods from unmanaged code 
1522  */
1523 MonoMethod *
1524 mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this)
1525 {
1526         MonoMethodSignature *sig, *csig;
1527         MonoMethodBuilder *mb;
1528         MonoClass *klass;
1529         MonoMethod *res;
1530         GHashTable *cache;
1531         int i, sigsize, *tmp_locals;
1532
1533         g_assert (method != NULL);
1534
1535         cache = method->klass->image->managed_wrapper_cache;
1536         if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1537                 return res;
1538
1539         sig = method->signature;
1540
1541         mb = mono_mb_new (method->klass, method->name);
1542         mb->method->wrapper_type = MONO_WRAPPER_NATIVE_TO_MANAGED;
1543
1544         /* allocate local 0 (pointer) src_ptr */
1545         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1546         /* allocate local 1 (pointer) dst_ptr */
1547         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1548         /* allocate local 2 (boolean) delete_old */
1549         mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
1550
1551         mono_mb_emit_byte (mb, CEE_LDNULL);
1552         mono_mb_emit_byte (mb, CEE_STLOC_2);
1553
1554         /* we copy the signature, so that we can modify it */
1555         sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1556         csig = g_memdup (sig, sigsize);
1557         csig->hasthis = 0;
1558         csig->pinvoke = 1;
1559
1560         /* fixme: howto handle this ? */
1561         if (sig->hasthis) {
1562
1563                 if (this) {
1564                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1565                         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1566                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, this));
1567
1568
1569                 } else {
1570                         /* fixme: */
1571                         g_assert_not_reached ();
1572                 }
1573         } 
1574
1575
1576         /* we first do all conversions */
1577         tmp_locals = alloca (sizeof (int) * sig->param_count);
1578         for (i = 0; i < sig->param_count; i ++) {
1579                 MonoType *t = sig->params [i];
1580
1581                 tmp_locals [i] = 0;
1582
1583                 switch (t->type) {
1584                 case MONO_TYPE_VALUETYPE:
1585                         
1586                         klass = sig->params [i]->data.klass;
1587                         if (klass->enumtype)
1588                                 break;
1589
1590                         tmp_locals [i] = mono_mb_add_local (mb, &klass->byval_arg);
1591
1592                         mono_mb_emit_ldarg_addr (mb, i);
1593                         mono_mb_emit_byte (mb, CEE_STLOC_0);
1594                         mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
1595                         mono_mb_emit_byte (mb, CEE_STLOC_1);
1596
1597                         /* emit valuetype convnversion code code */
1598                         emit_struct_conv (mb, klass, TRUE);
1599                         break;
1600                 case MONO_TYPE_STRING:
1601
1602                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1603
1604                         csig->params [i] = &mono_defaults.int_class->byval_arg;
1605                         mono_mb_emit_ldarg (mb, i);
1606                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1607                         mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1608                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
1609                         mono_mb_emit_stloc (mb, tmp_locals [i]);
1610                         break;  
1611                 }
1612
1613         }
1614
1615         for (i = 0; i < sig->param_count; i++) {
1616                 MonoType *t = sig->params [i];
1617
1618                 if (t->byref) {
1619                         /* fixme: */
1620                         g_assert_not_reached ();
1621                 }
1622
1623                 switch (t->type) {
1624                 case MONO_TYPE_I1:
1625                 case MONO_TYPE_U1:
1626                 case MONO_TYPE_I2:
1627                 case MONO_TYPE_U2:
1628                 case MONO_TYPE_I4:
1629                 case MONO_TYPE_U4:
1630                 case MONO_TYPE_I:
1631                 case MONO_TYPE_U:
1632                 case MONO_TYPE_PTR:
1633                 case MONO_TYPE_R4:
1634                 case MONO_TYPE_R8:
1635                 case MONO_TYPE_I8:
1636                 case MONO_TYPE_U8:
1637                         mono_mb_emit_ldarg (mb, i);
1638                         break;
1639                 case MONO_TYPE_STRING:
1640                         g_assert (tmp_locals [i]);
1641                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
1642                         break;  
1643                 case MONO_TYPE_CLASS:  
1644                 case MONO_TYPE_ARRAY:
1645                 case MONO_TYPE_SZARRAY:
1646                 case MONO_TYPE_OBJECT:
1647                         /* fixme: conversions ? */
1648                         mono_mb_emit_ldarg (mb, i);
1649                         break;
1650                 case MONO_TYPE_VALUETYPE:
1651                         klass = sig->params [i]->data.klass;
1652                         if (klass->enumtype) {
1653                                 mono_mb_emit_ldarg (mb, i);
1654                                 break;
1655                         }
1656
1657                         g_assert (tmp_locals [i]);
1658                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
1659                         break;
1660                 default:
1661                         g_warning ("type 0x%02x unknown", t->type);     
1662                         g_assert_not_reached ();
1663                 }
1664         }
1665
1666         mono_mb_emit_managed_call (mb, method, NULL);
1667         
1668         /* fixme: add return type conversions */
1669
1670         mono_mb_emit_byte (mb, CEE_RET);
1671
1672         res = mono_mb_create_method (mb, csig, 0);
1673         mono_mb_free (mb);
1674
1675         g_hash_table_insert (cache, method, res);
1676
1677         return res;
1678 }
1679
1680 /*
1681  * generates IL code for the pinvoke wrapper (the generated method
1682  * calls the unamnage code in method->addr)
1683  */
1684 MonoMethod *
1685 mono_marshal_get_native_wrapper (MonoMethod *method)
1686 {
1687         MonoMethodSignature *sig, *csig;
1688         MonoMethodBuilder *mb;
1689         MonoMethod *res;
1690         GHashTable *cache;
1691         MonoClass *klass;
1692         gboolean pinvoke = FALSE;
1693         int i, argnum, *tmp_locals;
1694         int type, sigsize;
1695
1696         g_assert (method != NULL);
1697
1698         cache = method->klass->image->native_wrapper_cache;
1699         if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1700                 return res;
1701
1702         sig = method->signature;
1703
1704         if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
1705             (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
1706                 pinvoke = TRUE;
1707
1708         mb = mono_mb_new (method->klass, method->name);
1709         mb->method->wrapper_type = MONO_WRAPPER_MANAGED_TO_NATIVE;
1710
1711         mb->method->save_lmf = 1;
1712
1713         if (pinvoke && !method->addr)
1714                 mono_lookup_pinvoke_call (method);
1715
1716         if (!method->addr) {
1717                 mono_mb_emit_exception (mb);
1718                 res = mono_mb_create_method (mb, sig, 0);
1719                 mono_mb_free (mb);
1720                 g_hash_table_insert (cache, method, res);
1721                 return res;
1722         }
1723
1724         /* we copy the signature, so that we can modify it */
1725         sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1726         csig = g_memdup (sig, sigsize);
1727
1728         /* internal calls: we simply push all arguments and call the method (no conversions) */
1729         if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
1730
1731                 /* hack - string constructors returns a value */
1732                 if (method->string_ctor)
1733                         csig->ret = &mono_defaults.string_class->byval_arg;
1734
1735                 if (sig->hasthis)
1736                         mono_mb_emit_byte (mb, CEE_LDARG_0);
1737
1738                 for (i = 0; i < sig->param_count; i++)
1739                         mono_mb_emit_ldarg (mb, i + sig->hasthis);
1740
1741                 g_assert (method->addr);
1742                 mono_mb_emit_native_call (mb, csig, method->addr);
1743
1744                 mono_mb_emit_byte (mb, CEE_RET);
1745
1746                 res = mono_mb_create_method (mb, csig, 0);
1747                 mono_mb_free (mb);
1748                 g_hash_table_insert (cache, method, res);
1749                 return res;
1750         }
1751
1752         g_assert (pinvoke);
1753
1754         /* pinvoke: we need to convert the arguments if necessary */
1755
1756         csig->pinvoke = 1;
1757
1758         /* we allocate local for use with emit_struct_conv() */
1759         /* allocate local 0 (pointer) src_ptr */
1760         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1761         /* allocate local 1 (pointer) dst_ptr */
1762         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1763         /* allocate local 2 (boolean) delete_old */
1764         mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
1765
1766         mono_mb_emit_icon (mb, 0);
1767         mono_mb_emit_byte (mb, CEE_STLOC_2);
1768
1769         if (sig->ret->type != MONO_TYPE_VOID) {
1770                 /* allocate local 3 to store the return value */
1771                 mono_mb_add_local (mb, sig->ret);
1772         }
1773
1774         /* we first do all conversions */
1775         tmp_locals = alloca (sizeof (int) * sig->param_count);
1776         for (i = 0; i < sig->param_count; i ++) {
1777                 MonoType *t = sig->params [i];
1778
1779                 argnum = i + sig->hasthis;
1780                 tmp_locals [i] = 0;
1781
1782                 if (t->byref) {
1783                         /* fixme: what to do here? */
1784                         continue;
1785                 }
1786
1787                 switch (t->type) {
1788                 case MONO_TYPE_VALUETYPE:
1789                         
1790                         klass = sig->params [i]->data.klass;
1791                         if (klass->enumtype)
1792                                 break;
1793
1794                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1795                         
1796                         /* store the address of the source into local variable 0 */
1797                         mono_mb_emit_ldarg_addr (mb, argnum);
1798                         mono_mb_emit_byte (mb, CEE_STLOC_0);
1799                         
1800                         /* allocate space for the native struct and
1801                          * store the address into local variable 1 (dest) */
1802                         mono_mb_emit_icon (mb, mono_class_native_size (klass));
1803                         mono_mb_emit_byte (mb, CEE_PREFIX1);
1804                         mono_mb_emit_byte (mb, CEE_LOCALLOC);
1805                         mono_mb_emit_stloc (mb, tmp_locals [i]);
1806                         /* set dst_ptr */
1807                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
1808                         mono_mb_emit_byte (mb, CEE_STLOC_1);
1809
1810                         /* emit valuetype convnversion code code */
1811                         emit_struct_conv (mb, klass, FALSE);
1812                         break;
1813                 case MONO_TYPE_STRING:
1814                         csig->params [argnum] = &mono_defaults.int_class->byval_arg;
1815                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1816
1817                         mono_mb_emit_ldarg (mb, argnum);
1818                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1819                         mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1820                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
1821                         mono_mb_emit_stloc (mb, tmp_locals [i]);
1822                         break;
1823                 case MONO_TYPE_CLASS:
1824                 case MONO_TYPE_OBJECT:
1825                         csig->params [argnum] = &mono_defaults.int_class->byval_arg;
1826                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1827
1828                         if (t->data.klass->delegate) {
1829                                 mono_mb_emit_ldarg (mb, argnum);
1830                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1831                                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1832                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_DEL_FTN);
1833                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
1834                         } else {
1835                                 mono_mb_emit_ldarg (mb, argnum);
1836                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1837                                 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
1838                                 /* fixme: convert to what ? */
1839                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
1840                         }
1841                         break;
1842                 case MONO_TYPE_ARRAY:
1843                 case MONO_TYPE_SZARRAY:
1844                         csig->params [argnum] = &mono_defaults.int_class->byval_arg;
1845                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1846
1847                         mono_mb_emit_ldarg (mb, argnum);
1848                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1849                         mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1850                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_ARRAY_LPARRAY);
1851                         mono_mb_emit_stloc (mb, tmp_locals [i]);
1852                         break;
1853                 }
1854         }
1855
1856         /* push all arguments */
1857
1858         if (sig->hasthis)
1859                 mono_mb_emit_byte (mb, CEE_LDARG_0);
1860
1861         for (i = 0; i < sig->param_count; i++) {
1862                 MonoType *t = sig->params [i];
1863                 
1864                 argnum = i + sig->hasthis;
1865
1866                 if (t->byref) {
1867                         /* fixme: ?? */
1868                         mono_mb_emit_ldarg (mb, argnum);
1869                         continue;
1870                 }
1871
1872                 switch (t->type) {
1873                 case MONO_TYPE_BOOLEAN:
1874                         mono_mb_emit_ldarg (mb, argnum);
1875                         break;
1876                 case MONO_TYPE_I1:
1877                 case MONO_TYPE_U1:
1878                 case MONO_TYPE_I2:
1879                 case MONO_TYPE_U2:
1880                 case MONO_TYPE_I4:
1881                 case MONO_TYPE_U4:
1882                 case MONO_TYPE_I:
1883                 case MONO_TYPE_U:
1884                 case MONO_TYPE_PTR:
1885                 case MONO_TYPE_R4:
1886                 case MONO_TYPE_R8:
1887                 case MONO_TYPE_I8:
1888                 case MONO_TYPE_U8:
1889                         mono_mb_emit_ldarg (mb, argnum);
1890                         break;
1891                 case MONO_TYPE_VALUETYPE:
1892                         klass = sig->params [i]->data.klass;
1893                         if (klass->enumtype) {
1894                                 mono_mb_emit_ldarg (mb, argnum);
1895                                 break;
1896                         }                       
1897                         g_assert (tmp_locals [i]);
1898                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
1899                         mono_mb_emit_byte (mb, CEE_LDOBJ);
1900                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
1901                         break;
1902                 case MONO_TYPE_STRING:
1903                         /* fixme: load the address instead */
1904                         g_assert (tmp_locals [i]);
1905                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
1906                         break;
1907                 case MONO_TYPE_CLASS:
1908                 case MONO_TYPE_OBJECT:
1909                         g_assert (tmp_locals [i]);
1910                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
1911                         break;
1912                 case MONO_TYPE_CHAR:
1913                         /* fixme: dont know how to marshal that. We cant simply
1914                          * convert it to a one byte UTF8 character, because an
1915                          * unicode character may need more that one byte in UTF8 */
1916                         mono_mb_emit_ldarg (mb, argnum);
1917                         break;
1918                 case MONO_TYPE_ARRAY:
1919                 case MONO_TYPE_SZARRAY:
1920                         g_assert (tmp_locals [i]);
1921                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
1922                         break;
1923                 case MONO_TYPE_TYPEDBYREF:
1924                 case MONO_TYPE_FNPTR:
1925                 default:
1926                         g_warning ("type 0x%02x unknown", t->type);     
1927                         g_assert_not_reached ();
1928                 }
1929         }                       
1930
1931         /* call the native method */
1932         mono_mb_emit_native_call (mb, csig, method->addr);
1933
1934         /* return the result */
1935
1936         if (!sig->ret->byref) {
1937                 type = sig->ret->type;
1938         handle_enum:
1939                 switch (type) {
1940                 case MONO_TYPE_VOID:
1941                 case MONO_TYPE_I1:
1942                 case MONO_TYPE_U1:
1943                 case MONO_TYPE_I2:
1944                 case MONO_TYPE_U2:
1945                 case MONO_TYPE_I4:
1946                 case MONO_TYPE_U4:
1947                 case MONO_TYPE_I:
1948                 case MONO_TYPE_U:
1949                 case MONO_TYPE_PTR:
1950                 case MONO_TYPE_R4:
1951                 case MONO_TYPE_R8:
1952                 case MONO_TYPE_I8:
1953                 case MONO_TYPE_U8:
1954                 /* no conversions necessary */
1955                         break;
1956                 case MONO_TYPE_BOOLEAN:
1957                         /* maybe we need to make sure that it fits within 8 bits */
1958                         break;
1959                 case MONO_TYPE_VALUETYPE:
1960                         if (sig->ret->data.klass->enumtype) {
1961                                 type = sig->ret->data.klass->enum_basetype->type;
1962                                 goto handle_enum;
1963                         } else {
1964                                 g_warning ("generic valutype %s not handled", 
1965                                            sig->ret->data.klass->name);
1966                                 g_assert_not_reached ();
1967                         }
1968                         break;
1969                 case MONO_TYPE_STRING:
1970                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1971                         mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1972                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
1973                         break;
1974                 case MONO_TYPE_ARRAY:
1975                 case MONO_TYPE_SZARRAY:
1976                 case MONO_TYPE_CLASS:
1977                 case MONO_TYPE_OBJECT:
1978                         /* fixme: we need conversions here */
1979                         break;
1980                 case MONO_TYPE_CHAR:
1981                         /* fixme: we need conversions here */
1982                         break;
1983                 case MONO_TYPE_TYPEDBYREF:
1984                 case MONO_TYPE_FNPTR:
1985                 default:
1986                         g_warning ("return type 0x%02x unknown", sig->ret->type);       
1987                         g_assert_not_reached ();
1988                 }
1989         }
1990
1991         mono_mb_emit_byte (mb, CEE_RET);
1992
1993         res = mono_mb_create_method (mb, sig, 0);
1994         mono_mb_free (mb);
1995
1996         g_hash_table_insert (cache, method, res);
1997
1998         return res;
1999 }
2000
2001 /*
2002  * generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld)
2003  */
2004 MonoMethod *
2005 mono_marshal_get_struct_to_ptr (MonoClass *klass)
2006 {
2007         MonoMethodBuilder *mb;
2008         static MonoMethod *stoptr = NULL;
2009         MonoMethod *res;
2010
2011         g_assert (klass != NULL);
2012
2013         if (klass->str_to_ptr)
2014                 return klass->str_to_ptr;
2015
2016         if (!stoptr) 
2017                 stoptr = mono_find_method_by_name (mono_defaults.marshal_class, "StructureToPtr", 3);
2018         g_assert (stoptr);
2019
2020         mb = mono_mb_new (stoptr->klass, stoptr->name);
2021
2022         /* allocate local 0 (pointer) src_ptr */
2023         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2024         /* allocate local 1 (pointer) dst_ptr */
2025         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2026         /* allocate local 2 (boolean) delete_old */
2027         mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2028         mono_mb_emit_byte (mb, CEE_LDARG_2);
2029         mono_mb_emit_byte (mb, CEE_STLOC_2);
2030
2031         /* initialize src_ptr to point to the start of object data */
2032         mono_mb_emit_byte (mb, CEE_LDARG_0);
2033         mono_mb_emit_icon (mb, sizeof (MonoObject));
2034         mono_mb_emit_byte (mb, CEE_ADD);
2035         mono_mb_emit_byte (mb, CEE_STLOC_0);
2036
2037         /* initialize dst_ptr */
2038         mono_mb_emit_byte (mb, CEE_LDARG_1);
2039         mono_mb_emit_byte (mb, CEE_STLOC_1);
2040
2041         emit_struct_conv (mb, klass, FALSE);
2042
2043         mono_mb_emit_byte (mb, CEE_RET);
2044
2045         res = mono_mb_create_method (mb, stoptr->signature, 0);
2046         mono_mb_free (mb);
2047
2048         klass->str_to_ptr = res;
2049         return res;
2050 }
2051
2052 /*
2053  * generates IL code for PtrToStructure (IntPtr src, object structure)
2054  */
2055 MonoMethod *
2056 mono_marshal_get_ptr_to_struct (MonoClass *klass)
2057 {
2058         MonoMethodBuilder *mb;
2059         static MonoMethod *ptostr = NULL;
2060         MonoMethod *res;
2061
2062         g_assert (klass != NULL);
2063
2064         if (klass->ptr_to_str)
2065                 return klass->ptr_to_str;
2066
2067         if (!ptostr) 
2068                 ptostr = mono_find_method_by_name (mono_defaults.marshal_class, "PtrToStructure", 2);
2069         g_assert (ptostr);
2070
2071         mb = mono_mb_new (ptostr->klass, ptostr->name);
2072
2073         /* allocate local 0 (pointer) src_ptr */
2074         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2075         /* allocate local 1 (pointer) dst_ptr */
2076         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2077         /* allocate local 2 (boolean) delete_old */
2078         mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2079
2080         mono_mb_emit_byte (mb, CEE_LDNULL);
2081         mono_mb_emit_byte (mb, CEE_STLOC_2);
2082
2083         /* initialize src_ptr to point to the start of object data */
2084         mono_mb_emit_byte (mb, CEE_LDARG_0);
2085         mono_mb_emit_byte (mb, CEE_STLOC_0);
2086
2087         /* initialize dst_ptr */
2088         mono_mb_emit_byte (mb, CEE_LDARG_1);
2089         mono_mb_emit_icon (mb, sizeof (MonoObject));
2090         mono_mb_emit_byte (mb, CEE_ADD);
2091         mono_mb_emit_byte (mb, CEE_STLOC_1);
2092
2093         emit_struct_conv (mb, klass, TRUE);
2094
2095         mono_mb_emit_byte (mb, CEE_RET);
2096
2097         res = mono_mb_create_method (mb, ptostr->signature, 0);
2098         mono_mb_free (mb);
2099
2100         klass->ptr_to_str = res;
2101         return res;
2102 }
2103
2104 /* FIXME: on win32 we should probably use GlobalAlloc(). */
2105 void*
2106 mono_marshal_alloc (gpointer size) {
2107         return g_try_malloc ((gulong)size);
2108 }
2109
2110 void
2111 mono_marshal_free (gpointer ptr) {
2112         g_free (ptr);
2113 }
2114
2115 void*
2116 mono_marshal_realloc (gpointer ptr, gpointer size) {
2117         return g_try_realloc (ptr, (gulong)size);
2118 }
2119
2120 void*
2121 mono_marshal_string_array (MonoArray *array)
2122 {
2123         char **result;
2124         int i, len;
2125
2126         if (!array)
2127                 return NULL;
2128
2129         len = mono_array_length (array);
2130
2131         result = g_malloc (sizeof (char*) * len);
2132         for (i = 0; i < len; ++i) {
2133                 MonoString *s = (MonoString*)mono_array_get (array, gpointer, i);
2134                 result [i] = s ? mono_string_to_utf8 (s): NULL;
2135         }
2136         return result;
2137 }
2138
2139 void
2140 ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArray *src, gint32 start_index,
2141                                                                     gpointer dest, gint32 length)
2142 {
2143         int element_size;
2144         void *source_addr;
2145
2146         MONO_CHECK_ARG_NULL (src);
2147         MONO_CHECK_ARG_NULL (dest);
2148
2149         g_assert (src->obj.vtable->klass->rank == 1);
2150         g_assert (start_index >= 0 && start_index < mono_array_length (src));
2151         g_assert (start_index + length <= mono_array_length (src));
2152
2153         element_size = mono_array_element_size (src->obj.vtable->klass);
2154           
2155         source_addr = mono_array_addr_with_size (src, element_size, start_index);
2156
2157         memcpy (dest, source_addr, length * element_size);
2158 }
2159
2160 void
2161 ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer src, gint32 start_index,
2162                                                                       MonoArray *dest, gint32 length)
2163 {
2164         int element_size;
2165         void *dest_addr;
2166
2167         MONO_CHECK_ARG_NULL (src);
2168         MONO_CHECK_ARG_NULL (dest);
2169
2170         g_assert (dest->obj.vtable->klass->rank == 1);
2171         g_assert (start_index >= 0 && start_index < mono_array_length (dest));
2172         g_assert (start_index + length <= mono_array_length (dest));
2173
2174         element_size = mono_array_element_size (dest->obj.vtable->klass);
2175           
2176         dest_addr = mono_array_addr_with_size (dest, element_size, start_index);
2177
2178         memcpy (dest_addr, src, length * element_size);
2179 }
2180
2181 gpointer
2182 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr, gint32 offset)
2183 {
2184         char *p = ptr;
2185         return *(gpointer*)(p + offset);
2186 }
2187
2188 unsigned char
2189 ves_icall_System_Runtime_InteropServices_Marshal_ReadByte (gpointer ptr, gint32 offset)
2190 {
2191         char *p = ptr;
2192         return *(unsigned char*)(p + offset);
2193 }
2194
2195 gint16
2196 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt16 (gpointer ptr, gint32 offset)
2197 {
2198         char *p = ptr;
2199         return *(gint16*)(p + offset);
2200 }
2201
2202 gint32
2203 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt32 (gpointer ptr, gint32 offset)
2204 {
2205         char *p = ptr;
2206         return *(gint32*)(p + offset);
2207 }
2208
2209 gint64
2210 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt64 (gpointer ptr, gint32 offset)
2211 {
2212         char *p = ptr;
2213         return *(gint64*)(p + offset);
2214 }
2215
2216 void
2217 ves_icall_System_Runtime_InteropServices_Marshal_WriteByte (gpointer ptr, gint32 offset, unsigned char val)
2218 {
2219         char *p = ptr;
2220         *(unsigned char*)(p + offset) = val;
2221 }
2222
2223 void
2224 ves_icall_System_Runtime_InteropServices_Marshal_WriteIntPtr (gpointer ptr, gint32 offset, gpointer val)
2225 {
2226         char *p = ptr;
2227         *(gpointer*)(p + offset) = val;
2228 }
2229
2230 void
2231 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt16 (gpointer ptr, gint32 offset, gint16 val)
2232 {
2233         char *p = ptr;
2234         *(gint16*)(p + offset) = val;
2235 }
2236
2237 void
2238 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt32 (gpointer ptr, gint32 offset, gint32 val)
2239 {
2240         char *p = ptr;
2241         *(gint32*)(p + offset) = val;
2242 }
2243
2244 void
2245 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt64 (gpointer ptr, gint32 offset, gint64 val)
2246 {
2247         char *p = ptr;
2248         *(gint64*)(p + offset) = val;
2249 }
2250
2251 MonoString *
2252 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (char *ptr)
2253 {
2254         return mono_string_new (mono_domain_get (), ptr);
2255 }
2256
2257 MonoString *
2258 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len (char *ptr, gint32 len)
2259 {
2260         return mono_string_new_len (mono_domain_get (), ptr, len);
2261 }
2262
2263 MonoString *
2264 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni (guint16 *ptr)
2265 {
2266         MonoDomain *domain = mono_domain_get (); 
2267         int len = 0;
2268         guint16 *t = ptr;
2269
2270         while (t++)
2271                 len++;
2272
2273         return mono_string_new_utf16 (domain, ptr, len);
2274 }
2275
2276 MonoString *
2277 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len (guint16 *ptr, gint32 len)
2278 {
2279         MonoDomain *domain = mono_domain_get (); 
2280
2281         return mono_string_new_utf16 (domain, ptr, len);
2282 }
2283
2284 MonoString *
2285 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR (gpointer ptr)
2286 {
2287         g_warning ("PtrToStringBSTR not implemented");
2288         g_assert_not_reached ();
2289
2290         return NULL;
2291 }
2292
2293 guint32 
2294 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
2295 {
2296         return (GetLastError ());
2297 }
2298
2299 guint32 
2300 ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype)
2301 {
2302         MonoClass *klass;
2303
2304         MONO_CHECK_ARG_NULL (rtype);
2305
2306         klass = mono_class_from_mono_type (rtype->type);
2307
2308         return mono_class_native_size (klass);
2309 }
2310
2311 void
2312 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old)
2313 {
2314         MonoMethod *method;
2315         gpointer pa [3];
2316
2317         MONO_CHECK_ARG_NULL (obj);
2318         MONO_CHECK_ARG_NULL (dst);
2319
2320         method = mono_marshal_get_struct_to_ptr (obj->vtable->klass);
2321
2322         pa [0] = obj;
2323         pa [1] = &dst;
2324         pa [2] = &delete_old;
2325
2326         mono_runtime_invoke (method, NULL, pa, NULL);
2327 }
2328
2329 void
2330 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, MonoObject *dst)
2331 {
2332         MonoMethod *method;
2333         gpointer pa [2];
2334
2335         MONO_CHECK_ARG_NULL (src);
2336         MONO_CHECK_ARG_NULL (dst);
2337
2338         method = mono_marshal_get_ptr_to_struct (dst->vtable->klass);
2339
2340         pa [0] = &src;
2341         pa [1] = dst;
2342
2343         mono_runtime_invoke (method, NULL, pa, NULL);
2344 }
2345
2346 MonoObject *
2347 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer src, MonoReflectionType *type)
2348 {
2349         MonoDomain *domain = mono_domain_get (); 
2350         MonoMethod *method;
2351         MonoObject *res;
2352
2353         MONO_CHECK_ARG_NULL (src);
2354         MONO_CHECK_ARG_NULL (type);
2355
2356         res = mono_object_new (domain, mono_class_from_mono_type (type->type));
2357
2358         ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (src, res);
2359
2360         return res;
2361 }