2003-02-21 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mono / metadata / marshal.c
1 /*
2  * marshal.c: Routines for marshaling complex types in P/Invoke methods.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
7  * (C) 2002 Ximian, Inc.  http://www.ximian.com
8  *
9  */
10
11 #include "config.h"
12 #include "object.h"
13 #include "loader.h"
14 #include "metadata/marshal.h"
15 #include "metadata/tabledefs.h"
16 #include "metadata/exception.h"
17 #include "metadata/appdomain.h"
18 #include "mono/metadata/debug-helpers.h"
19 #include "mono/metadata/threadpool.h"
20 #include <string.h>
21
22 //#define DEBUG_RUNTIME_CODE
23
24 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
25         a = i,
26
27 enum {
28 #include "mono/cil/opcode.def"
29         LAST = 0xff
30 };
31 #undef OPDEF
32
33 struct _MonoMethodBuilder {
34         MonoMethod *method;
35         GList *locals_list;
36         int locals;
37         guint32 code_size, pos;
38         unsigned char *code;
39 };
40
41 static void
42 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object);
43
44 #ifdef DEBUG_RUNTIME_CODE
45 static char*
46 indenter (MonoDisHelper *dh, MonoMethod *method, guint32 ip_offset)
47 {
48         return g_strdup (" ");
49 }
50
51 static MonoDisHelper marshal_dh = {
52         "\n",
53         "IL_%04x: ",
54         "IL_%04x",
55         indenter, 
56         NULL,
57         NULL
58 };
59 #endif 
60
61 gpointer
62 mono_delegate_to_ftnptr (MonoDelegate *delegate)
63 {
64         MonoMethod *method, *wrapper;
65         MonoClass *klass;
66
67         if (!delegate)
68                 return NULL;
69
70         if (delegate->delegate_trampoline)
71                 return delegate->delegate_trampoline;
72
73         klass = ((MonoObject *)delegate)->vtable->klass;
74         g_assert (klass->delegate);
75         
76         method = delegate->method_info->method;
77         wrapper = mono_marshal_get_managed_wrapper (method, delegate->target);
78
79         delegate->delegate_trampoline =  mono_compile_method (wrapper);
80
81         return delegate->delegate_trampoline;
82 }
83
84 gpointer
85 mono_array_to_savearray (MonoArray *array)
86 {
87         if (!array)
88                 return NULL;
89
90         g_assert_not_reached ();
91         return NULL;
92 }
93
94 gpointer
95 mono_array_to_lparray (MonoArray *array)
96 {
97         if (!array)
98                 return NULL;
99
100         /* fixme: maybe we need to make a copy */
101         return array->vector;
102 }
103
104 void
105 mono_string_utf8_to_builder (MonoStringBuilder *sb, char *text)
106 {
107         GError *error = NULL;
108         guint16 *ut;
109         glong items_written;
110         int l;
111
112         if (!sb || !text)
113                 return;
114
115         l = strlen (text);
116
117         ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
118
119         if (items_written > sb->capacity)
120                 items_written = sb->capacity;
121         
122         if (!error) {
123                 memcpy (sb->chars->vector, ut, items_written * 2);
124                 sb->length = items_written;
125         } else 
126                 g_error_free (error);
127
128         g_free (ut);
129 }
130
131 gpointer
132 mono_string_builder_to_utf8 (MonoStringBuilder *sb)
133 {
134         char *res;
135
136         if (!sb)
137                 return NULL;
138
139         res = g_malloc (sb->capacity + 1);
140
141         /* fixme: copy the content of the string builder? */
142         res [0] = 0;
143
144         return res;
145 }
146
147 gpointer
148 mono_string_to_ansibstr (MonoString *string_obj)
149 {
150         g_error ("implement me");
151         return NULL;
152 }
153
154 gpointer
155 mono_string_to_bstr (MonoString *string_obj)
156 {
157         g_error ("implement me");
158         return NULL;
159 }
160
161 void
162 mono_string_to_byvalstr (gpointer dst, MonoString *src, int size)
163 {
164         char *s;
165         int len;
166
167         g_assert (dst != NULL);
168         g_assert (size > 0);
169
170         if (!src) {
171                 memset (dst, 0, size);
172                 return;
173         }
174
175         s = mono_string_to_utf8 (src);
176         len = MIN (size, strlen (s));
177         memcpy (dst, s, len);
178         g_free (s);
179
180         *((char *)dst + size - 1) = 0;
181 }
182
183 void
184 mono_string_to_byvalwstr (gpointer dst, MonoString *src, int size)
185 {
186         int len;
187
188         g_assert (dst != NULL);
189         g_assert (size > 1);
190
191         if (!src) {
192                 memset (dst, 0, size);
193                 return;
194         }
195
196         len = MIN (size, (mono_string_length (src) * 2));
197         memcpy (dst, mono_string_chars (src), len);
198
199         *((char *)dst + size - 1) = 0;
200         *((char *)dst + size - 2) = 0;
201 }
202
203
204 static MonoMethod *
205 mono_find_method_by_name (MonoClass *klass, const char *name, int param_count)
206 {
207         MonoMethod *res = NULL;
208         int i;
209
210         for (i = 0; i < klass->method.count; ++i) {
211                 if ((klass->methods [i]->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
212                     klass->methods [i]->name[0] == name [0] && 
213                     !strcmp (name, klass->methods [i]->name) &&
214                     klass->methods [i]->signature->param_count == param_count) {
215                         res = klass->methods [i];
216                         break;
217                 }
218         }
219         return res;
220 }
221
222 void
223 mono_mb_free (MonoMethodBuilder *mb)
224 {
225         g_list_free (mb->locals_list);
226         g_free (mb);
227 }
228
229 MonoMethodBuilder *
230 mono_mb_new (MonoClass *klass, const char *name, MonoWrapperType type)
231 {
232         MonoMethodBuilder *mb;
233         MonoMethod *m;
234
235         g_assert (klass != NULL);
236         g_assert (name != NULL);
237
238         mb = g_new0 (MonoMethodBuilder, 1);
239
240         mb->method = m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
241
242         m->klass = klass;
243         m->name = g_strdup (name);
244         m->inline_info = 1;
245         m->inline_count = -1;
246         m->wrapper_type = type;
247
248         mb->code_size = 256;
249         mb->code = g_malloc (mb->code_size);
250         
251         return mb;
252 }
253
254 int
255 mono_mb_add_local (MonoMethodBuilder *mb, MonoType *type)
256 {
257         int res = mb->locals;
258
259         g_assert (mb != NULL);
260         g_assert (type != NULL);
261
262         mb->locals_list = g_list_append (mb->locals_list, type);
263         mb->locals++;
264
265         return res;
266 }
267
268 MonoMethod *
269 mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack)
270 {
271         MonoMethodHeader *header;
272         GList *l;
273         int i;
274
275         g_assert (mb != NULL);
276
277         ((MonoMethodNormal *)mb->method)->header = header = (MonoMethodHeader *) 
278                 g_malloc0 (sizeof (MonoMethodHeader) + mb->locals * sizeof (MonoType *));
279
280         if (max_stack < 8)
281                 max_stack = 8;
282
283         header->max_stack = max_stack;
284
285         for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
286                 header->locals [i] = (MonoType *)l->data;
287         }
288
289         mb->method->signature = signature;
290         header->code = mb->code;
291         header->code_size = mb->pos;
292         header->num_locals = mb->locals;
293
294 #ifdef DEBUG_RUNTIME_CODE
295         printf ("RUNTIME CODE FOR %s\n", mono_method_full_name (mb->method, TRUE));
296         printf ("%s\n", mono_disasm_code (&marshal_dh, mb->method, mb->code, mb->code + mb->pos));
297 #endif
298
299         return mb->method;
300 }
301
302 guint32
303 mono_mb_add_data (MonoMethodBuilder *mb, gpointer data)
304 {
305         MonoMethodWrapper *mw;
306
307         g_assert (mb != NULL);
308
309         mw = (MonoMethodWrapper *)mb->method;
310
311         mw->data = g_list_append (mw->data, data);
312
313         return g_list_length (mw->data);
314 }
315
316 void
317 mono_mb_patch_addr (MonoMethodBuilder *mb, int pos, int value)
318 {
319         mb->code [pos] = value & 0xff;
320         mb->code [pos + 1] = (value >> 8) & 0xff;
321         mb->code [pos + 2] = (value >> 16) & 0xff;
322         mb->code [pos + 3] = (value >> 24) & 0xff;
323 }
324
325 void
326 mono_mb_patch_addr_s (MonoMethodBuilder *mb, int pos, gint8 value)
327 {
328         *((gint8 *)(&mb->code [pos])) = value;
329 }
330
331 void
332 mono_mb_emit_byte (MonoMethodBuilder *mb, guint8 op)
333 {
334         if (mb->pos >= mb->code_size) {
335                 mb->code_size += 64;
336                 mb->code = g_realloc (mb->code, mb->code_size);
337         }
338
339         mb->code [mb->pos++] = op;
340 }
341
342 void
343 mono_mb_emit_ldflda (MonoMethodBuilder *mb, gint32 offset)
344 {
345         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
346         mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
347
348         if (offset) {
349                 mono_mb_emit_icon (mb, offset);
350                 mono_mb_emit_byte (mb, CEE_ADD);
351         }
352 }
353
354 static int
355 mono_mb_emit_proxy_check (MonoMethodBuilder *mb, int branch_code)
356 {
357         int pos;
358         mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoObject, vtable));
359         mono_mb_emit_byte (mb, CEE_LDIND_I);
360         mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoVTable, klass));
361         mono_mb_emit_byte (mb, CEE_ADD);
362         mono_mb_emit_byte (mb, CEE_LDIND_I);
363         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
364         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
365         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_defaults.transparent_proxy_class));
366         mono_mb_emit_byte (mb, branch_code);
367         pos = mb->pos;
368         mono_mb_emit_i4 (mb, 0);
369         return pos;
370 }
371
372 void
373 mono_mb_emit_i4 (MonoMethodBuilder *mb, gint32 data)
374 {
375         if ((mb->pos + 4) >= mb->code_size) {
376                 mb->code_size += 64;
377                 mb->code = g_realloc (mb->code, mb->code_size);
378         }
379
380         mono_mb_patch_addr (mb, mb->pos, data);
381         mb->pos += 4;
382 }
383
384 void
385 mono_mb_emit_i2 (MonoMethodBuilder *mb, gint16 data)
386 {
387         if ((mb->pos + 2) >= mb->code_size) {
388                 mb->code_size += 64;
389                 mb->code = g_realloc (mb->code, mb->code_size);
390         }
391
392         mb->code [mb->pos] = data & 0xff;
393         mb->code [mb->pos + 1] = (data >> 8) & 0xff;
394         mb->pos += 2;
395 }
396
397 void
398 mono_mb_emit_ldarg (MonoMethodBuilder *mb, guint argnum)
399 {
400         if (argnum < 4) {
401                 mono_mb_emit_byte (mb, CEE_LDARG_0 + argnum);
402         } else if (argnum < 256) {
403                 mono_mb_emit_byte (mb, CEE_LDARG_S);
404                 mono_mb_emit_byte (mb, argnum);
405         } else {
406                 mono_mb_emit_byte (mb, CEE_PREFIX1);
407                 mono_mb_emit_byte (mb, CEE_LDARG);
408                 mono_mb_emit_i2 (mb, argnum);
409         }
410 }
411
412 void
413 mono_mb_emit_ldarg_addr (MonoMethodBuilder *mb, guint argnum)
414 {
415         if (argnum < 256) {
416                 mono_mb_emit_byte (mb, CEE_LDARGA_S);
417                 mono_mb_emit_byte (mb, argnum);
418         } else {
419                 mono_mb_emit_byte (mb, CEE_PREFIX1);
420                 mono_mb_emit_byte (mb, CEE_LDARGA);
421                 mono_mb_emit_i2 (mb, argnum);
422         }
423 }
424
425 void
426 mono_mb_emit_ldloc_addr (MonoMethodBuilder *mb, guint locnum)
427 {
428         if (locnum < 256) {
429                 mono_mb_emit_byte (mb, CEE_LDLOCA_S);
430                 mono_mb_emit_byte (mb, locnum);
431         } else {
432                 mono_mb_emit_byte (mb, CEE_PREFIX1);
433                 mono_mb_emit_byte (mb, CEE_LDLOCA);
434                 mono_mb_emit_i2 (mb, locnum);
435         }
436 }
437
438 void
439 mono_mb_emit_ldloc (MonoMethodBuilder *mb, guint num)
440 {
441         if (num < 4) {
442                 mono_mb_emit_byte (mb, CEE_LDLOC_0 + num);
443         } else if (num < 256) {
444                 mono_mb_emit_byte (mb, CEE_LDLOC_S);
445                 mono_mb_emit_byte (mb, num);
446         } else {
447                 mono_mb_emit_byte (mb, CEE_PREFIX1);
448                 mono_mb_emit_byte (mb, CEE_LDLOC);
449                 mono_mb_emit_i2 (mb, num);
450         }
451 }
452
453 void
454 mono_mb_emit_stloc (MonoMethodBuilder *mb, guint num)
455 {
456         if (num < 4) {
457                 mono_mb_emit_byte (mb, CEE_STLOC_0 + num);
458         } else if (num < 256) {
459                 mono_mb_emit_byte (mb, CEE_STLOC_S);
460                 mono_mb_emit_byte (mb, num);
461         } else {
462                 mono_mb_emit_byte (mb, CEE_PREFIX1);
463                 mono_mb_emit_byte (mb, CEE_STLOC);
464                 mono_mb_emit_i2 (mb, num);
465         }
466 }
467
468 void
469 mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value)
470 {
471         if (value >= -1 && value < 8) {
472                 mono_mb_emit_byte (mb, CEE_LDC_I4_0 + value);
473         } else if (value >= -128 && value <= 127) {
474                 mono_mb_emit_byte (mb, CEE_LDC_I4_S);
475                 mono_mb_emit_byte (mb, value);
476         } else {
477                 mono_mb_emit_byte (mb, CEE_LDC_I4);
478                 mono_mb_emit_i4 (mb, value);
479         }
480 }
481
482 void
483 mono_mb_emit_managed_call (MonoMethodBuilder *mb, MonoMethod *method, MonoMethodSignature *opt_sig)
484 {
485         if (!opt_sig)
486                 opt_sig = method->signature;
487         mono_mb_emit_byte (mb, CEE_PREFIX1);
488         mono_mb_emit_byte (mb, CEE_LDFTN);
489         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
490         mono_mb_emit_byte (mb, CEE_CALLI);
491         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, opt_sig));
492 }
493
494 void
495 mono_mb_emit_native_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, gpointer func)
496 {
497         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
498         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
499         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, func));
500         mono_mb_emit_byte (mb, CEE_CALLI);
501         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
502 }
503
504 void
505 mono_mb_emit_exception (MonoMethodBuilder *mb)
506 {
507         /* fixme: we need a better way to throw exception,
508          * supporting several exception types and messages */
509         static MonoMethod *missing_method_ctor = NULL;
510
511         if (!missing_method_ctor) {
512                 MonoClass *mme = mono_class_from_name (mono_defaults.corlib, "System", "MissingMethodException");
513                 int i;
514                 mono_class_init (mme);
515                 for (i = 0; i < mme->method.count; ++i) {
516                         if (strcmp (mme->methods [i]->name, ".ctor") == 0 && mme->methods [i]->signature->param_count == 0) {
517                                 missing_method_ctor = mme->methods [i];
518                                 break;
519                         }
520                 }
521         }
522         mono_mb_emit_byte (mb, CEE_NEWOBJ);
523         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, missing_method_ctor));
524         mono_mb_emit_byte (mb, CEE_THROW);
525         
526 }
527
528 void
529 mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint16 local, gint32 incr)
530 {
531         mono_mb_emit_ldloc (mb, local); 
532         mono_mb_emit_icon (mb, incr);
533         mono_mb_emit_byte (mb, CEE_ADD);
534         mono_mb_emit_stloc (mb, local); 
535 }
536
537 static void
538 emit_ptr_to_str_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, 
539                       int usize, int msize)
540 {
541         switch (conv) {
542         case MONO_MARSHAL_CONV_BOOL_I4:
543                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
544                 mono_mb_emit_byte (mb, CEE_LDIND_I);
545                 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
546                 mono_mb_emit_byte (mb, 5);
547                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
548                 mono_mb_emit_byte (mb, CEE_LDC_I4_1);
549                 mono_mb_emit_byte (mb, CEE_STIND_I1);
550                 mono_mb_emit_byte (mb, CEE_BR_S);
551                 mono_mb_emit_byte (mb, 3);
552                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
553                 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
554                 mono_mb_emit_byte (mb, CEE_STIND_I1);
555                 break;
556         case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
557                 MonoClass *eclass;
558                 int esize;
559
560                 if (type->type == MONO_TYPE_ARRAY)
561                         eclass = mono_class_from_mono_type (type->data.array->type);
562                 else if (type->type == MONO_TYPE_SZARRAY) {
563                         eclass = mono_class_from_mono_type (type->data.type);
564                 } else {
565                         g_assert_not_reached ();
566                 }
567
568                 if (eclass->valuetype)
569                         esize = mono_class_instance_size (eclass) - sizeof (MonoObject);
570                 else
571                         esize = sizeof (gpointer);
572
573                 /* create a new array */
574                 /* fixme: this only works for SZARRAYS */
575                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
576                 mono_mb_emit_icon (mb, msize / esize);
577                 mono_mb_emit_byte (mb, CEE_NEWARR);     
578                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eclass));
579                 mono_mb_emit_byte (mb, CEE_STIND_I);
580
581                 /* copy the elements */
582                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
583                 mono_mb_emit_byte (mb, CEE_LDIND_I);
584                 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
585                 mono_mb_emit_byte (mb, CEE_ADD);
586                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
587                 mono_mb_emit_icon (mb, usize);
588                 mono_mb_emit_byte (mb, CEE_PREFIX1);
589                 mono_mb_emit_byte (mb, CEE_CPBLK);                      
590
591                 break;
592         }
593         case MONO_MARSHAL_CONV_STR_BYVALSTR: 
594                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
595                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
596                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
597                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
598                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
599                 mono_mb_emit_byte (mb, CEE_STIND_I);            
600                 break;
601         case MONO_MARSHAL_CONV_STR_LPTSTR:
602         case MONO_MARSHAL_CONV_STR_LPSTR:
603                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
604                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
605                 mono_mb_emit_byte (mb, CEE_LDIND_I);
606                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
607                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
608                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
609                 mono_mb_emit_byte (mb, CEE_STIND_I);            
610                 break;
611         case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
612                 MonoClass *klass = mono_class_from_mono_type (type);
613                 int src_var, dst_var;
614
615                 src_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
616                 dst_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
617                 
618                 /* *dst = new object */
619                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
620                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
621                 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);        
622                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
623                 mono_mb_emit_byte (mb, CEE_STIND_I);
624         
625                 /* save the old src pointer */
626                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
627                 mono_mb_emit_stloc (mb, src_var);
628                 /* save the old dst pointer */
629                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
630                 mono_mb_emit_stloc (mb, dst_var);
631
632                 /* dst = pointer to newly created object data */
633                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
634                 mono_mb_emit_byte (mb, CEE_LDIND_I);
635                 mono_mb_emit_icon (mb, sizeof (MonoObject));
636                 mono_mb_emit_byte (mb, CEE_ADD);
637                 mono_mb_emit_byte (mb, CEE_STLOC_1); 
638
639                 emit_struct_conv (mb, klass, TRUE);
640                 
641                 /* restore the old src pointer */
642                 mono_mb_emit_ldloc (mb, src_var);
643                 mono_mb_emit_byte (mb, CEE_STLOC_0);
644                 /* restore the old dst pointer */
645                 mono_mb_emit_ldloc (mb, dst_var);
646                 mono_mb_emit_byte (mb, CEE_STLOC_1);
647                 break;
648         }
649         case MONO_MARSHAL_CONV_DEL_FTN: {
650                 // fixme: we never convert functions back to delegates, dont 
651                 // know if thats the correct behaviour
652                 break;
653         }
654         case MONO_MARSHAL_CONV_STR_LPWSTR:
655         case MONO_MARSHAL_CONV_STR_BSTR:
656         case MONO_MARSHAL_CONV_STR_ANSIBSTR:
657         case MONO_MARSHAL_CONV_STR_TBSTR:
658         case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
659         case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
660         case MONO_MARSHAL_CONV_STR_BYVALWSTR: 
661         case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
662         default:
663                 g_warning ("marshaling conversion %d not implemented", conv);
664                 g_assert_not_reached ();
665         }
666 }
667
668 static void
669 emit_str_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, int usize, int msize)
670 {
671         int pos;
672
673         switch (conv) {
674         case MONO_MARSHAL_CONV_BOOL_I4:
675                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
676                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
677                 mono_mb_emit_byte (mb, CEE_LDIND_U1);
678                 mono_mb_emit_byte (mb, CEE_STIND_I4);
679                 break;
680         case MONO_MARSHAL_CONV_STR_LPWSTR:
681         case MONO_MARSHAL_CONV_STR_LPSTR:
682         case MONO_MARSHAL_CONV_STR_LPTSTR:
683         case MONO_MARSHAL_CONV_STR_BSTR:
684         case MONO_MARSHAL_CONV_STR_ANSIBSTR:
685         case MONO_MARSHAL_CONV_STR_TBSTR:
686                 /* free space if free == true */
687                 mono_mb_emit_byte (mb, CEE_LDLOC_2);
688                 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
689                 mono_mb_emit_byte (mb, 4);
690                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
691                 mono_mb_emit_byte (mb, CEE_LDIND_I);
692                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
693                 mono_mb_emit_byte (mb, CEE_MONO_FREE);
694
695                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
696                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
697                 mono_mb_emit_byte (mb, CEE_LDIND_I);
698                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
699                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
700                 mono_mb_emit_byte (mb, conv);
701                 mono_mb_emit_byte (mb, CEE_STIND_I);    
702                 break;
703         case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
704         case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
705         case MONO_MARSHAL_CONV_DEL_FTN:
706                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
707                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
708                 mono_mb_emit_byte (mb, CEE_LDIND_I);
709                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
710                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
711                 mono_mb_emit_byte (mb, conv);
712                 mono_mb_emit_byte (mb, CEE_STIND_I);    
713                 break;
714         case MONO_MARSHAL_CONV_STR_BYVALSTR: 
715         case MONO_MARSHAL_CONV_STR_BYVALWSTR: {
716                 if (!usize)
717                         break;
718
719                 mono_mb_emit_byte (mb, CEE_LDLOC_1); /* dst */
720                 mono_mb_emit_byte (mb, CEE_LDLOC_0);    
721                 mono_mb_emit_byte (mb, CEE_LDIND_I); /* src String */
722                 mono_mb_emit_icon (mb, usize);
723                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
724                 mono_mb_emit_byte (mb, CEE_MONO_PROC3);
725                 mono_mb_emit_byte (mb, conv);
726                 break;
727         }
728         case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
729                 if (!usize) 
730                         break;
731
732                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
733                 mono_mb_emit_byte (mb, CEE_LDIND_I);            
734                 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
735                 pos = mb->pos;
736                 mono_mb_emit_byte (mb, 0);
737
738                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
739                 mono_mb_emit_byte (mb, CEE_LDLOC_0);    
740                 mono_mb_emit_byte (mb, CEE_LDIND_I);    
741                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
742                 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
743                 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
744                 mono_mb_emit_byte (mb, CEE_ADD);
745                 mono_mb_emit_icon (mb, usize);
746                 mono_mb_emit_byte (mb, CEE_PREFIX1);
747                 mono_mb_emit_byte (mb, CEE_CPBLK);                      
748                 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
749                 break;
750         }
751         case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
752                 int src_var, dst_var;
753
754                 src_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
755                 dst_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
756                 
757                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
758                 mono_mb_emit_byte (mb, CEE_LDIND_I);            
759                 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
760                 pos = mb->pos;
761                 mono_mb_emit_byte (mb, 0);
762                 
763                 /* save the old src pointer */
764                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
765                 mono_mb_emit_stloc (mb, src_var);
766                 /* save the old dst pointer */
767                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
768                 mono_mb_emit_stloc (mb, dst_var);
769
770                 /* src = pointer to object data */
771                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
772                 mono_mb_emit_byte (mb, CEE_LDIND_I);            
773                 mono_mb_emit_icon (mb, sizeof (MonoObject));
774                 mono_mb_emit_byte (mb, CEE_ADD);
775                 mono_mb_emit_byte (mb, CEE_STLOC_0); 
776
777                 emit_struct_conv (mb, mono_class_from_mono_type (type), FALSE);
778                 
779                 /* restore the old src pointer */
780                 mono_mb_emit_ldloc (mb, src_var);
781                 mono_mb_emit_byte (mb, CEE_STLOC_0);
782                 /* restore the old dst pointer */
783                 mono_mb_emit_ldloc (mb, dst_var);
784                 mono_mb_emit_byte (mb, CEE_STLOC_1);
785
786                 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
787                 break;
788         }
789         case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
790         default:
791                 g_warning ("marshalling conversion %d not implemented", conv);
792                 g_assert_not_reached ();
793         }
794 }
795
796 static void
797 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
798 {
799         MonoMarshalType *info;
800         int i;
801
802         info = mono_marshal_load_type_info (klass);
803
804         if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
805                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
806                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
807                 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
808                 mono_mb_emit_byte (mb, CEE_PREFIX1);
809                 mono_mb_emit_byte (mb, CEE_CPBLK);
810                 return;
811         }
812
813         for (i = 0; i < info->num_fields; i++) {
814                 MonoMarshalNative ntype;
815                 MonoMarshalConv conv;
816                 MonoType *ftype = info->fields [i].field->type;
817                 int msize = 0;
818                 int usize = 0;
819                 gboolean last_field = i < (info->num_fields -1) ? 0 : 1;
820
821                 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
822                         continue;
823
824                 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, klass->unicode, &conv);
825                         
826                 if (last_field) {
827                         msize = klass->instance_size - info->fields [i].field->offset;
828                         usize = info->native_size - info->fields [i].offset;
829                 } else {
830                         msize = klass->fields [i + 1].offset - info->fields [i].field->offset;
831                         usize = info->fields [i + 1].offset - info->fields [i].offset;
832                 }
833                 g_assert (msize > 0 && usize > 0);
834
835                 switch (conv) {
836                 case MONO_MARSHAL_CONV_NONE: {
837                         int t;
838
839                         if (ftype->byref || ftype->type == MONO_TYPE_I ||
840                             ftype->type == MONO_TYPE_U) {
841                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
842                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
843                                 mono_mb_emit_byte (mb, CEE_LDIND_I);
844                                 mono_mb_emit_byte (mb, CEE_STIND_I);
845                                 break;
846                         }
847
848                         t = ftype->type;
849                 handle_enum:
850                         switch (t) {
851                         case MONO_TYPE_I4:
852                         case MONO_TYPE_U4:
853 #if SIZEOF_VOID_P == 4
854                         case MONO_TYPE_PTR:
855 #endif
856                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
857                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
858                                 mono_mb_emit_byte (mb, CEE_LDIND_I4);
859                                 mono_mb_emit_byte (mb, CEE_STIND_I4);
860                                 break;
861                         case MONO_TYPE_I1:
862                         case MONO_TYPE_U1:
863                         case MONO_TYPE_BOOLEAN:
864                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
865                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
866                                 mono_mb_emit_byte (mb, CEE_LDIND_I1);
867                                 mono_mb_emit_byte (mb, CEE_STIND_I1);
868                                 break;
869                         case MONO_TYPE_I2:
870                         case MONO_TYPE_U2:
871                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
872                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
873                                 mono_mb_emit_byte (mb, CEE_LDIND_I2);
874                                 mono_mb_emit_byte (mb, CEE_STIND_I2);
875                                 break;
876                         case MONO_TYPE_I8:
877                         case MONO_TYPE_U8:
878 #if SIZEOF_VOID_P == 8
879                         case MONO_TYPE_PTR:
880 #endif
881                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
882                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
883                                 mono_mb_emit_byte (mb, CEE_LDIND_I8);
884                                 mono_mb_emit_byte (mb, CEE_STIND_I8);
885                                 break;
886                         case MONO_TYPE_R4:
887                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
888                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
889                                 mono_mb_emit_byte (mb, CEE_LDIND_R4);
890                                 mono_mb_emit_byte (mb, CEE_STIND_R4);
891                                 break;
892                         case MONO_TYPE_R8:
893                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
894                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
895                                 mono_mb_emit_byte (mb, CEE_LDIND_R8);
896                                 mono_mb_emit_byte (mb, CEE_STIND_R8);
897                                 break;
898                         case MONO_TYPE_VALUETYPE:
899                                 if (ftype->data.klass->enumtype) {
900                                         t = ftype->data.klass->enum_basetype->type;
901                                         goto handle_enum;
902                                 }
903                                 emit_struct_conv (mb, ftype->data.klass, to_object);
904                                 continue;
905                         default:
906                                 g_warning ("marshaling type %02x not implemented", ftype->type);
907                                 g_assert_not_reached ();
908                         }
909                         break;
910                 }
911                 default:
912                         if (to_object) 
913                                 emit_ptr_to_str_conv (mb, ftype, conv, usize, msize);
914                         else
915                                 emit_str_to_ptr_conv (mb, ftype, conv, usize, msize);   
916                 }
917                 
918                 if (to_object) {
919                         mono_mb_emit_add_to_local (mb, 0, usize);
920                         mono_mb_emit_add_to_local (mb, 1, msize);
921                 } else {
922                         mono_mb_emit_add_to_local (mb, 0, msize);
923                         mono_mb_emit_add_to_local (mb, 1, usize);
924                 }                               
925         }
926 }
927
928 static MonoAsyncResult *
929 mono_delegate_begin_invoke (MonoDelegate *delegate, gpointer *params)
930 {
931         MonoMethodMessage *msg;
932         MonoDelegate *async_callback;
933         MonoObject *state;
934         MonoMethod *im;
935         MonoClass *klass;
936         MonoMethod *method = NULL;
937         int i;
938
939         g_assert (delegate);
940
941         klass = delegate->object.vtable->klass;
942
943         method = mono_get_delegate_invoke (klass);
944         for (i = 0; i < klass->method.count; ++i) {
945                 if (klass->methods [i]->name[0] == 'B' && 
946                     !strcmp ("BeginInvoke", klass->methods [i]->name)) {
947                         method = klass->methods [i];
948                         break;
949                 }
950         }
951
952         g_assert (method != NULL);
953
954         im = mono_get_delegate_invoke (method->klass);
955         
956         msg = mono_method_call_message_new (method, params, im, &async_callback, &state);
957
958         return mono_thread_pool_add ((MonoObject *)delegate, msg, async_callback, state);
959 }
960
961 static int
962 mono_mb_emit_save_args (MonoMethodBuilder *mb, MonoMethodSignature *sig, gboolean save_this)
963 {
964         int i, params_var, tmp_var;
965
966         /* allocate local (pointer) *params[] */
967         params_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
968         /* allocate local (pointer) tmp */
969         tmp_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
970
971         /* alloate space on stack to store an array of pointers to the arguments */
972         mono_mb_emit_icon (mb, sizeof (gpointer) * (sig->param_count + 1));
973         mono_mb_emit_byte (mb, CEE_PREFIX1);
974         mono_mb_emit_byte (mb, CEE_LOCALLOC);
975         mono_mb_emit_stloc (mb, params_var);
976
977         /* tmp = params */
978         mono_mb_emit_ldloc (mb, params_var);
979         mono_mb_emit_stloc (mb, tmp_var);
980
981         if (save_this && sig->hasthis) {
982                 mono_mb_emit_ldloc (mb, tmp_var);
983                 mono_mb_emit_ldarg_addr (mb, 0);
984                 mono_mb_emit_byte (mb, CEE_STIND_I);
985                 /* tmp = tmp + sizeof (gpointer) */
986                 if (sig->param_count)
987                         mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
988
989         }
990
991         for (i = 0; i < sig->param_count; i++) {
992                 mono_mb_emit_ldloc (mb, tmp_var);
993                 mono_mb_emit_ldarg_addr (mb, i + sig->hasthis);
994                 mono_mb_emit_byte (mb, CEE_STIND_I);
995                 /* tmp = tmp + sizeof (gpointer) */
996                 if (i < (sig->param_count - 1))
997                         mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
998         }
999
1000         return params_var;
1001 }
1002
1003 static char*
1004 mono_signature_to_name (MonoMethodSignature *sig, const char *prefix)
1005 {
1006         int i;
1007         char *result;
1008         GString *res = g_string_new ("");
1009
1010         if (prefix) {
1011                 g_string_append (res, prefix);
1012                 g_string_append_c (res, '_');
1013         }
1014
1015         mono_type_get_desc (res, sig->ret, FALSE);
1016
1017         for (i = 0; i < sig->param_count; ++i) {
1018                 g_string_append_c (res, '_');
1019                 mono_type_get_desc (res, sig->params [i], FALSE);
1020         }
1021         result = res->str;
1022         g_string_free (res, FALSE);
1023         return result;
1024 }
1025
1026 MonoMethod *
1027 mono_marshal_get_delegate_begin_invoke (MonoMethod *method)
1028 {
1029         MonoMethodSignature *sig;
1030         static MonoMethodSignature *csig = NULL;
1031         MonoMethodBuilder *mb;
1032         MonoMethod *res;
1033         GHashTable *cache;
1034         int params_var;
1035         char *name;
1036
1037         g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1038                   !strcmp (method->name, "BeginInvoke"));
1039
1040         sig = method->signature;
1041
1042         cache = method->klass->image->delegate_begin_invoke_cache;
1043         if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1044                 return res;
1045
1046         g_assert (sig->hasthis);
1047
1048         if (!csig) {
1049                 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1050                 csig = g_malloc0 (sigsize);
1051
1052                 /* MonoAsyncResult * begin_invoke (MonoDelegate *delegate, gpointer params[]) */
1053                 csig->param_count = 2;
1054                 csig->ret = &mono_defaults.object_class->byval_arg;
1055                 csig->params [0] = &mono_defaults.object_class->byval_arg;
1056                 csig->params [1] = &mono_defaults.int_class->byval_arg;
1057         }
1058
1059         name = mono_signature_to_name (sig, "begin_invoke");
1060         mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_BEGIN_INVOKE);
1061         g_free (name);
1062
1063         mb->method->save_lmf = 1;
1064
1065         params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1066
1067         mono_mb_emit_ldarg (mb, 0);
1068         mono_mb_emit_ldloc (mb, params_var);
1069         mono_mb_emit_native_call (mb, csig, mono_delegate_begin_invoke);
1070         mono_mb_emit_byte (mb, CEE_RET);
1071
1072         res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1073         mono_mb_free (mb);
1074         g_hash_table_insert (cache, sig, res);
1075         return res;
1076 }
1077
1078 static MonoObject *
1079 mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params)
1080 {
1081         MonoDomain *domain = mono_domain_get ();
1082         MonoAsyncResult *ares;
1083         MonoMethod *method = NULL;
1084         MonoMethodSignature *sig;
1085         MonoMethodMessage *msg;
1086         MonoObject *res, *exc;
1087         MonoArray *out_args;
1088         MonoClass *klass;
1089         int i;
1090
1091         g_assert (delegate);
1092
1093         if (!delegate->method_info || !delegate->method_info->method)
1094                 g_assert_not_reached ();
1095
1096         klass = delegate->object.vtable->klass;
1097
1098         for (i = 0; i < klass->method.count; ++i) {
1099                 if (klass->methods [i]->name[0] == 'E' && 
1100                     !strcmp ("EndInvoke", klass->methods [i]->name)) {
1101                         method = klass->methods [i];
1102                         break;
1103                 }
1104         }
1105
1106         g_assert (method != NULL);
1107
1108         sig = method->signature;
1109
1110         msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1111
1112         ares = mono_array_get (msg->args, gpointer, sig->param_count - 1);
1113         g_assert (ares);
1114
1115         res = mono_thread_pool_finish (ares, &out_args, &exc);
1116
1117         if (exc) {
1118                 char *strace = mono_string_to_utf8 (((MonoException*)exc)->stack_trace);
1119                 char  *tmp;
1120                 tmp = g_strdup_printf ("%s\nException Rethrown at:\n", strace);
1121                 g_free (strace);        
1122                 ((MonoException*)exc)->stack_trace = mono_string_new (domain, tmp);
1123                 g_free (tmp);
1124                 mono_raise_exception ((MonoException*)exc);
1125         }
1126
1127         mono_method_return_message_restore (method, params, out_args);
1128         return res;
1129 }
1130
1131 static void
1132 mono_mb_emit_restore_result (MonoMethodBuilder *mb, MonoType *return_type)
1133 {
1134         if (return_type->byref)
1135                 return_type = &mono_defaults.int_class->byval_arg;
1136         else if (return_type->type == MONO_TYPE_VALUETYPE && return_type->data.klass->enumtype)
1137                 return_type = return_type->data.klass->enum_basetype;
1138
1139         switch (return_type->type) {
1140         case MONO_TYPE_VOID:
1141                 g_assert_not_reached ();
1142                 break;
1143         case MONO_TYPE_STRING:
1144         case MONO_TYPE_CLASS: 
1145         case MONO_TYPE_OBJECT: 
1146         case MONO_TYPE_ARRAY: 
1147         case MONO_TYPE_SZARRAY: 
1148                 /* nothing to do */
1149                 break;
1150         case MONO_TYPE_U1:
1151         case MONO_TYPE_BOOLEAN:
1152                 mono_mb_emit_byte (mb, CEE_UNBOX);
1153                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1154                 mono_mb_emit_byte (mb, CEE_LDIND_U1);
1155                 break;
1156         case MONO_TYPE_I1:
1157                 mono_mb_emit_byte (mb, CEE_UNBOX);
1158                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1159                 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1160                 break;
1161         case MONO_TYPE_U2:
1162         case MONO_TYPE_CHAR:
1163                 mono_mb_emit_byte (mb, CEE_UNBOX);
1164                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1165                 mono_mb_emit_byte (mb, CEE_LDIND_U2);
1166                 break;
1167         case MONO_TYPE_I2:
1168                 mono_mb_emit_byte (mb, CEE_UNBOX);
1169                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1170                 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1171                 break;
1172         case MONO_TYPE_I:
1173         case MONO_TYPE_U:
1174                 mono_mb_emit_byte (mb, CEE_UNBOX);
1175                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1176                 mono_mb_emit_byte (mb, CEE_LDIND_I);
1177                 break;
1178         case MONO_TYPE_I4:
1179                 mono_mb_emit_byte (mb, CEE_UNBOX);
1180                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1181                 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1182                 break;
1183         case MONO_TYPE_U4:
1184                 mono_mb_emit_byte (mb, CEE_UNBOX);
1185                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1186                 mono_mb_emit_byte (mb, CEE_LDIND_U4);
1187                 break;
1188         case MONO_TYPE_U8:
1189         case MONO_TYPE_I8:
1190                 mono_mb_emit_byte (mb, CEE_UNBOX);
1191                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1192                 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1193                 break;
1194         case MONO_TYPE_R4:
1195                 mono_mb_emit_byte (mb, CEE_UNBOX);
1196                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1197                 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1198                 break;
1199         case MONO_TYPE_R8:
1200                 mono_mb_emit_byte (mb, CEE_UNBOX);
1201                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1202                 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1203                 break;
1204         case MONO_TYPE_VALUETYPE: {
1205                 int class;
1206                 mono_mb_emit_byte (mb, CEE_UNBOX);
1207                 class = mono_mb_add_data (mb, mono_class_from_mono_type (return_type));
1208                 mono_mb_emit_i4 (mb, class);
1209                 mono_mb_emit_byte (mb, CEE_LDOBJ);
1210                 mono_mb_emit_i4 (mb, class);
1211                 break;
1212         }
1213         default:
1214                 g_warning ("type 0x%x not handled", return_type->type);
1215                 g_assert_not_reached ();
1216         }
1217
1218         mono_mb_emit_byte (mb, CEE_RET);
1219 }
1220
1221 MonoMethod *
1222 mono_marshal_get_delegate_end_invoke (MonoMethod *method)
1223 {
1224         MonoMethodSignature *sig;
1225         static MonoMethodSignature *csig = NULL;
1226         MonoMethodBuilder *mb;
1227         MonoMethod *res;
1228         GHashTable *cache;
1229         int params_var;
1230         char *name;
1231
1232         g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1233                   !strcmp (method->name, "EndInvoke"));
1234
1235         sig = method->signature;
1236
1237         cache = method->klass->image->delegate_end_invoke_cache;
1238         if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1239                 return res;
1240
1241         g_assert (sig->hasthis);
1242
1243         if (!csig) {
1244                 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1245                 csig = g_malloc0 (sigsize);
1246
1247                 /* MonoObject *end_invoke (MonoDelegate *delegate, gpointer params[]) */
1248                 csig->param_count = 2;
1249                 csig->ret = &mono_defaults.object_class->byval_arg;
1250                 csig->params [0] = &mono_defaults.object_class->byval_arg;
1251                 csig->params [1] = &mono_defaults.int_class->byval_arg;
1252         }
1253
1254         name = mono_signature_to_name (sig, "end_invoke");
1255         mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_END_INVOKE);
1256         g_free (name);
1257
1258         mb->method->save_lmf = 1;
1259
1260         params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1261
1262         mono_mb_emit_ldarg (mb, 0);
1263         mono_mb_emit_ldloc (mb, params_var);
1264         mono_mb_emit_native_call (mb, csig, mono_delegate_end_invoke);
1265
1266         if (sig->ret->type == MONO_TYPE_VOID) {
1267                 mono_mb_emit_byte (mb, CEE_POP);
1268                 mono_mb_emit_byte (mb, CEE_RET);
1269         } else
1270                 mono_mb_emit_restore_result (mb, sig->ret);
1271
1272         res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1273         mono_mb_free (mb);
1274         g_hash_table_insert (cache, sig, res);
1275
1276         return res;
1277 }
1278
1279 static MonoObject *
1280 mono_remoting_wrapper (MonoMethod *method, gpointer *params)
1281 {
1282         MonoMethodMessage *msg;
1283         MonoTransparentProxy *this;
1284         MonoObject *res, *exc;
1285         MonoArray *out_args;
1286
1287         this = *((MonoTransparentProxy **)params [0]);
1288
1289         g_assert (this);
1290         g_assert (((MonoObject *)this)->vtable->klass == mono_defaults.transparent_proxy_class);
1291         
1292         /* skip the this pointer */
1293         params++;
1294
1295         msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1296
1297         res = mono_remoting_invoke ((MonoObject *)this->rp, msg, &exc, &out_args);
1298
1299         if (exc)
1300                 mono_raise_exception ((MonoException *)exc);
1301
1302         mono_method_return_message_restore (method, params, out_args);
1303
1304         return res;
1305
1306
1307 MonoMethod *
1308 mono_marshal_get_remoting_invoke (MonoMethod *method)
1309 {
1310         MonoMethodSignature *sig;
1311         static MonoMethodSignature *csig = NULL;
1312         MonoMethodBuilder *mb;
1313         MonoMethod *res;
1314         GHashTable *cache;
1315         int params_var;
1316
1317         g_assert (method);
1318
1319         if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE)
1320                 return method;
1321
1322         sig = method->signature;
1323
1324         /* we cant remote methods without this pointer */
1325         if (!sig->hasthis)
1326                 return method;
1327
1328         cache = method->klass->image->remoting_invoke_cache;
1329         if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1330                 return res;
1331
1332         if (!csig) {
1333                 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
1334                 csig->params [0] = &mono_defaults.int_class->byval_arg;
1335                 csig->params [1] = &mono_defaults.int_class->byval_arg;
1336                 csig->ret = &mono_defaults.object_class->byval_arg;
1337                 csig->pinvoke = 1;
1338         }
1339
1340         mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE);
1341         mb->method->save_lmf = 1;
1342
1343         params_var = mono_mb_emit_save_args (mb, sig, TRUE);
1344
1345         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1346         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1347         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
1348         mono_mb_emit_ldloc (mb, params_var);
1349         mono_mb_emit_native_call (mb, csig, mono_remoting_wrapper);
1350
1351         if (sig->ret->type == MONO_TYPE_VOID) {
1352                 mono_mb_emit_byte (mb, CEE_POP);
1353                 mono_mb_emit_byte (mb, CEE_RET);
1354         } else {
1355                  mono_mb_emit_restore_result (mb, sig->ret);
1356         }
1357
1358         res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1359         mono_mb_free (mb);
1360         g_hash_table_insert (cache, method, res);
1361         return res;
1362 }
1363
1364 MonoMethod *
1365 mono_marshal_get_remoting_invoke_with_check (MonoMethod *method)
1366 {
1367         MonoMethodSignature *sig;
1368         MonoMethodBuilder *mb;
1369         MonoMethod *res, *native;
1370         GHashTable *cache;
1371         int i, pos;
1372
1373         g_assert (method);
1374
1375         if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)
1376                 return method;
1377
1378         sig = method->signature;
1379
1380         /* we cant remote methods without this pointer */
1381         g_assert (sig->hasthis);
1382
1383         cache = method->klass->image->remoting_invoke_cache;
1384         if ((res = (MonoMethod *)g_hash_table_lookup (cache, (char *)method + 1)))
1385                 return res;
1386
1387         mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK);
1388
1389         mono_mb_emit_ldarg (mb, 0);
1390         pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
1391
1392         native = mono_marshal_get_remoting_invoke (method);
1393
1394         for (i = 0; i <= sig->param_count; i++)
1395                 mono_mb_emit_ldarg (mb, i);
1396         
1397         mono_mb_emit_managed_call (mb, native, native->signature);
1398         mono_mb_emit_byte (mb, CEE_RET);
1399
1400         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1401
1402         for (i = 0; i <= sig->param_count; i++)
1403                 mono_mb_emit_ldarg (mb, i);
1404                 
1405         mono_mb_emit_managed_call (mb, method, method->signature);
1406         mono_mb_emit_byte (mb, CEE_RET);
1407
1408         res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1409         mono_mb_free (mb);
1410         g_hash_table_insert (cache, (char *)method + 1, res);
1411         return res;
1412 }
1413
1414 /*
1415  * the returned method invokes all methods in a multicast delegate 
1416  */
1417 MonoMethod *
1418 mono_marshal_get_delegate_invoke (MonoMethod *method)
1419 {
1420         MonoMethodSignature *sig, *static_sig;
1421         int i, sigsize;
1422         MonoMethodBuilder *mb;
1423         MonoMethod *res;
1424         GHashTable *cache;
1425         int pos0, pos1;
1426         char *name;
1427
1428         g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1429                   !strcmp (method->name, "Invoke"));
1430                 
1431         sig = method->signature;
1432
1433         cache = method->klass->image->delegate_invoke_cache;
1434         if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1435                 return res;
1436
1437         sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1438         static_sig = g_memdup (sig, sigsize);
1439         static_sig->hasthis = 0;
1440
1441         name = mono_signature_to_name (sig, "invoke");
1442         mb = mono_mb_new (mono_defaults.multicastdelegate_class, name,  MONO_WRAPPER_DELEGATE_INVOKE);
1443         g_free (name);
1444
1445         /* allocate local 0 (object) */
1446         mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1447
1448         g_assert (sig->hasthis);
1449         
1450         /*
1451          * if (prev != null)
1452          *      prev.Invoke( args .. );
1453          * return this.<target>( args .. );
1454          */
1455
1456         /* get this->prev */
1457         mono_mb_emit_ldarg (mb, 0);
1458         mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoMulticastDelegate, prev));
1459         mono_mb_emit_byte (mb, CEE_LDIND_I );
1460         mono_mb_emit_stloc (mb, 0);
1461
1462         /* if prev != null */
1463         mono_mb_emit_ldloc (mb, 0);
1464         mono_mb_emit_byte (mb, CEE_BRFALSE);
1465
1466         pos0 = mb->pos;
1467         mono_mb_emit_i4 (mb, 0);
1468
1469         /* then recurse */
1470         mono_mb_emit_ldloc (mb, 0);
1471         for (i = 0; i < sig->param_count; i++)
1472                 mono_mb_emit_ldarg (mb, i + 1);
1473         mono_mb_emit_managed_call (mb, method, method->signature);
1474         if (sig->ret->type != MONO_TYPE_VOID)
1475                 mono_mb_emit_byte (mb, CEE_POP);
1476
1477         /* continued or prev == null */
1478         mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1479
1480         /* get this->target */
1481         mono_mb_emit_ldarg (mb, 0);
1482         mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, target));
1483         mono_mb_emit_byte (mb, CEE_LDIND_I );
1484         mono_mb_emit_stloc (mb, 0);
1485
1486         /* if target != null */
1487         mono_mb_emit_ldloc (mb, 0);
1488         mono_mb_emit_byte (mb, CEE_BRFALSE);
1489         pos0 = mb->pos;
1490         mono_mb_emit_i4 (mb, 0);
1491         
1492         /* then call this->method_ptr nonstatic */
1493         mono_mb_emit_ldloc (mb, 0); 
1494         for (i = 0; i < sig->param_count; ++i)
1495                 mono_mb_emit_ldarg (mb, i + 1);
1496         mono_mb_emit_ldarg (mb, 0);
1497         mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1498         mono_mb_emit_byte (mb, CEE_LDIND_I );
1499         mono_mb_emit_byte (mb, CEE_CALLI);
1500         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
1501
1502         mono_mb_emit_byte (mb, CEE_BR);
1503         pos1 = mb->pos;
1504         mono_mb_emit_i4 (mb, 0);
1505
1506         /* else [target == null] call this->method_ptr static */
1507         mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1508
1509         for (i = 0; i < sig->param_count; ++i)
1510                 mono_mb_emit_ldarg (mb, i + 1);
1511         mono_mb_emit_ldarg (mb, 0);
1512         mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1513         mono_mb_emit_byte (mb, CEE_LDIND_I );
1514         mono_mb_emit_byte (mb, CEE_CALLI);
1515         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, static_sig));
1516
1517         /* return */
1518         mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
1519         mono_mb_emit_byte (mb, CEE_RET);
1520
1521         res = mono_mb_create_method (mb, sig, sig->param_count + 16);
1522         mono_mb_free (mb);
1523
1524         g_hash_table_insert (cache, sig, res);
1525
1526         return res;     
1527 }
1528
1529 /*
1530  * generates IL code for the runtime invoke function 
1531  * MonoObject *runtime_invoke (MonoObject *this, void **params, MonoObject **exc)
1532  *
1533  * we also catch exceptions if exc != null
1534  */
1535 MonoMethod *
1536 mono_marshal_get_runtime_invoke (MonoMethod *method)
1537 {
1538         MonoMethodSignature *sig, *csig;
1539         MonoExceptionClause *clause;
1540         MonoMethodHeader *header;
1541         MonoMethodBuilder *mb;
1542         MonoMethod *res;
1543         GHashTable *cache;
1544         static MonoString *string_dummy = NULL;
1545         int i, pos, sigsize;
1546
1547         g_assert (method);
1548
1549         cache = method->klass->image->runtime_invoke_cache;
1550         if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1551                 return res;
1552         
1553         /* to make it work with our special string constructors */
1554         if (!string_dummy)
1555                 string_dummy = mono_string_new_wrapper ("dummy");
1556
1557         sig = method->signature;
1558
1559         sigsize = sizeof (MonoMethodSignature) + 3 * sizeof (MonoType *);
1560         csig = g_malloc0 (sigsize);
1561
1562         csig->param_count = 3;
1563         csig->ret = &mono_defaults.object_class->byval_arg;
1564         csig->params [0] = &mono_defaults.object_class->byval_arg;
1565         csig->params [1] = &mono_defaults.int_class->byval_arg;
1566         csig->params [2] = &mono_defaults.int_class->byval_arg;
1567
1568         mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_RUNTIME_INVOKE);
1569
1570         /* allocate local 0 (object) tmp */
1571         mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1572         /* allocate local 1 (object) exc */
1573         mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1574
1575         /* cond set *exc to null */
1576         mono_mb_emit_byte (mb, CEE_LDARG_2);
1577         mono_mb_emit_byte (mb, CEE_BRFALSE_S);
1578         mono_mb_emit_byte (mb, 3);      
1579         mono_mb_emit_byte (mb, CEE_LDARG_2);
1580         mono_mb_emit_byte (mb, CEE_LDNULL);
1581         mono_mb_emit_byte (mb, CEE_STIND_I);
1582
1583         if (sig->hasthis) {
1584                 if (method->string_ctor) {
1585                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1586                         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1587                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, string_dummy));
1588                 } else {
1589                         mono_mb_emit_ldarg (mb, 0);
1590                         if (method->klass->valuetype) {
1591                                 mono_mb_emit_byte (mb, CEE_UNBOX);
1592                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method->klass));
1593                         } 
1594                 }
1595         }
1596
1597         for (i = 0; i < sig->param_count; i++) {
1598                 MonoType *t = sig->params [i];
1599                 int type;
1600
1601                 mono_mb_emit_ldarg (mb, 1);
1602                 if (i) {
1603                         mono_mb_emit_icon (mb, sizeof (gpointer) * i);
1604                         mono_mb_emit_byte (mb, CEE_ADD);
1605                 }
1606                 mono_mb_emit_byte (mb, CEE_LDIND_I);
1607
1608                 if (t->byref)
1609                         continue;
1610
1611                 type = sig->params [i]->type;
1612 handle_enum:
1613                 switch (type) {
1614                 case MONO_TYPE_I1:
1615                         mono_mb_emit_byte (mb, CEE_LDIND_I1);
1616                         break;
1617                 case MONO_TYPE_BOOLEAN:
1618                 case MONO_TYPE_U1:
1619                         mono_mb_emit_byte (mb, CEE_LDIND_U1);
1620                         break;
1621                 case MONO_TYPE_I2:
1622                         mono_mb_emit_byte (mb, CEE_LDIND_I2);
1623                         break;
1624                 case MONO_TYPE_U2:
1625                 case MONO_TYPE_CHAR:
1626                         mono_mb_emit_byte (mb, CEE_LDIND_U2);
1627                         break;
1628                 case MONO_TYPE_I:
1629                 case MONO_TYPE_U:
1630                         mono_mb_emit_byte (mb, CEE_LDIND_I);
1631                         break;
1632                 case MONO_TYPE_I4:
1633                         mono_mb_emit_byte (mb, CEE_LDIND_I4);
1634                         break;
1635                 case MONO_TYPE_U4:
1636                         mono_mb_emit_byte (mb, CEE_LDIND_U4);
1637                         break;
1638                 case MONO_TYPE_R4:
1639                         mono_mb_emit_byte (mb, CEE_LDIND_R4);
1640                         break;
1641                 case MONO_TYPE_R8:
1642                         mono_mb_emit_byte (mb, CEE_LDIND_R8);
1643                         break;
1644                 case MONO_TYPE_I8:
1645                 case MONO_TYPE_U8:
1646                         mono_mb_emit_byte (mb, CEE_LDIND_I8);
1647                         break;
1648                 case MONO_TYPE_STRING:
1649                 case MONO_TYPE_CLASS:  
1650                 case MONO_TYPE_ARRAY:
1651                 case MONO_TYPE_PTR:
1652                 case MONO_TYPE_SZARRAY:
1653                 case MONO_TYPE_OBJECT:
1654                         /* do nothing */
1655                         break;
1656                 case MONO_TYPE_VALUETYPE:
1657                         if (t->data.klass->enumtype) {
1658                                 type = t->data.klass->enum_basetype->type;
1659                                 goto handle_enum;
1660                         }
1661                         mono_mb_emit_byte (mb, CEE_LDOBJ);
1662                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, t->data.klass));
1663                         break;
1664                 default:
1665                         g_assert_not_reached ();
1666                 }               
1667         }
1668
1669         if (method->string_ctor) {
1670                 MonoMethodSignature *strsig;
1671
1672                 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1673                 strsig = g_memdup (sig, sigsize);
1674                 strsig->ret = &mono_defaults.string_class->byval_arg;
1675
1676                 mono_mb_emit_managed_call (mb, method, strsig);         
1677         } else 
1678                 mono_mb_emit_managed_call (mb, method, NULL);
1679
1680         if (sig->ret->byref) {
1681                 /* fixme: */
1682                 g_assert_not_reached ();
1683         }
1684
1685
1686         switch (sig->ret->type) {
1687         case MONO_TYPE_VOID:
1688                 if (!method->string_ctor)
1689                         mono_mb_emit_byte (mb, CEE_LDNULL);
1690                 break;
1691         case MONO_TYPE_BOOLEAN:
1692         case MONO_TYPE_CHAR:
1693         case MONO_TYPE_I1:
1694         case MONO_TYPE_U1:
1695         case MONO_TYPE_I2:
1696         case MONO_TYPE_U2:
1697         case MONO_TYPE_I4:
1698         case MONO_TYPE_U4:
1699         case MONO_TYPE_I:
1700         case MONO_TYPE_U:
1701         case MONO_TYPE_R4:
1702         case MONO_TYPE_R8:
1703         case MONO_TYPE_I8:
1704         case MONO_TYPE_U8:
1705         case MONO_TYPE_VALUETYPE:
1706                 /* box value types */
1707                 mono_mb_emit_byte (mb, CEE_BOX);
1708                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (sig->ret)));
1709                 break;
1710         case MONO_TYPE_STRING:
1711         case MONO_TYPE_CLASS:  
1712         case MONO_TYPE_ARRAY:
1713         case MONO_TYPE_SZARRAY:
1714         case MONO_TYPE_OBJECT:
1715                 /* nothing to do */
1716                 break;
1717         case MONO_TYPE_PTR:
1718         default:
1719                 g_assert_not_reached ();
1720         }
1721
1722         mono_mb_emit_stloc (mb, 0);
1723                 
1724         mono_mb_emit_byte (mb, CEE_LEAVE);
1725         pos = mb->pos;
1726         mono_mb_emit_i4 (mb, 0);
1727
1728         clause = g_new0 (MonoExceptionClause, 1);
1729         clause->flags = MONO_EXCEPTION_CLAUSE_FILTER;
1730         clause->try_len = mb->pos;
1731
1732         /* filter code */
1733         clause->token_or_filter = mb->pos;
1734         
1735         mono_mb_emit_byte (mb, CEE_POP);
1736         mono_mb_emit_byte (mb, CEE_LDARG_2);
1737         mono_mb_emit_byte (mb, CEE_LDC_I4_0);
1738         mono_mb_emit_byte (mb, CEE_PREFIX1);
1739         mono_mb_emit_byte (mb, CEE_CGT_UN);
1740         mono_mb_emit_byte (mb, CEE_PREFIX1);
1741         mono_mb_emit_byte (mb, CEE_ENDFILTER);
1742
1743         clause->handler_offset = mb->pos;
1744
1745         /* handler code */
1746         /* store exception */
1747         mono_mb_emit_stloc (mb, 1);
1748         
1749         mono_mb_emit_byte (mb, CEE_LDARG_2);
1750         mono_mb_emit_ldloc (mb, 1);
1751         mono_mb_emit_byte (mb, CEE_STIND_I);
1752
1753         mono_mb_emit_byte (mb, CEE_LEAVE);
1754         mono_mb_emit_i4 (mb, 0);
1755
1756         clause->handler_len = mb->pos - clause->handler_offset;
1757
1758         /* return result */
1759         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1760         mono_mb_emit_ldloc (mb, 0);
1761         mono_mb_emit_byte (mb, CEE_RET);
1762         
1763         res = mono_mb_create_method (mb, csig, sig->param_count + 16);
1764         mono_mb_free (mb);
1765
1766         header = ((MonoMethodNormal *)res)->header;
1767         header->num_clauses = 1;
1768         header->clauses = clause;
1769
1770         g_hash_table_insert (cache, method, res);
1771
1772         return res;     
1773 }
1774
1775 /*
1776  * generates IL code to call managed methods from unmanaged code 
1777  */
1778 MonoMethod *
1779 mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this)
1780 {
1781         MonoMethodSignature *sig, *csig;
1782         MonoMethodBuilder *mb;
1783         MonoClass *klass;
1784         MonoMethod *res;
1785         GHashTable *cache;
1786         int i, pos, sigsize, *tmp_locals;
1787
1788         g_assert (method != NULL);
1789         g_assert (!method->signature->pinvoke);
1790
1791         cache = method->klass->image->managed_wrapper_cache;
1792         if (!this && (res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1793                 return res;
1794
1795         if (this) {
1796                 /* fime: howto free that memory ? */
1797         }
1798         
1799         sig = method->signature;
1800
1801         mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_NATIVE_TO_MANAGED);
1802
1803         /* allocate local 0 (pointer) src_ptr */
1804         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1805         /* allocate local 1 (pointer) dst_ptr */
1806         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1807         /* allocate local 2 (boolean) delete_old */
1808         mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
1809
1810         mono_mb_emit_byte (mb, CEE_LDNULL);
1811         mono_mb_emit_byte (mb, CEE_STLOC_2);
1812
1813         /* we copy the signature, so that we can modify it */
1814         sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1815         csig = g_memdup (sig, sigsize);
1816         csig->hasthis = 0;
1817         csig->pinvoke = 1;
1818
1819         /* fixme: howto handle this ? */
1820         if (sig->hasthis) {
1821
1822                 if (this) {
1823                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1824                         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1825                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, this));
1826
1827
1828                 } else {
1829                         /* fixme: */
1830                         g_assert_not_reached ();
1831                 }
1832         } 
1833
1834
1835         /* we first do all conversions */
1836         tmp_locals = alloca (sizeof (int) * sig->param_count);
1837         for (i = 0; i < sig->param_count; i ++) {
1838                 MonoType *t = sig->params [i];
1839
1840                 tmp_locals [i] = 0;
1841                 
1842                 switch (t->type) {
1843                 case MONO_TYPE_VALUETYPE:
1844                         
1845                         klass = sig->params [i]->data.klass;
1846                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
1847                             klass->blittable || klass->enumtype)
1848                                 break;
1849
1850                         tmp_locals [i] = mono_mb_add_local (mb, &klass->byval_arg);
1851
1852                         if (t->byref) 
1853                                 mono_mb_emit_ldarg (mb, i);
1854                         else
1855                                 mono_mb_emit_ldarg_addr (mb, i);
1856                         mono_mb_emit_byte (mb, CEE_STLOC_0);
1857
1858                         if (t->byref) {
1859                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
1860                                 mono_mb_emit_byte (mb, CEE_BRFALSE);
1861                                 pos = mb->pos;
1862                                 mono_mb_emit_i4 (mb, 0);
1863                         }                       
1864
1865                         mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
1866                         mono_mb_emit_byte (mb, CEE_STLOC_1);
1867
1868                         /* emit valuetype convnversion code code */
1869                         emit_struct_conv (mb, klass, TRUE);
1870
1871                         if (t->byref)
1872                                 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1873                         break;
1874                 case MONO_TYPE_STRING:
1875                         if (t->byref)
1876                                 continue;
1877
1878                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1879                         csig->params [i] = &mono_defaults.int_class->byval_arg;
1880
1881                         mono_mb_emit_ldarg (mb, i);
1882                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1883                         mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1884                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
1885                         mono_mb_emit_stloc (mb, tmp_locals [i]);
1886                         break;  
1887                 case MONO_TYPE_ARRAY:
1888                 case MONO_TYPE_SZARRAY:
1889                         if (t->byref)
1890                                 continue;
1891
1892                         klass = mono_class_from_mono_type (t);
1893
1894                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1895                         csig->params [i] = &mono_defaults.int_class->byval_arg;
1896
1897                         g_warning ("array marshaling not implemented");
1898                         g_assert_not_reached ();
1899                         break;
1900                 }
1901         }
1902
1903         for (i = 0; i < sig->param_count; i++) {
1904                 MonoType *t = sig->params [i];
1905
1906                 switch (t->type) {
1907                 case MONO_TYPE_BOOLEAN:
1908                 case MONO_TYPE_I1:
1909                 case MONO_TYPE_U1:
1910                 case MONO_TYPE_I2:
1911                 case MONO_TYPE_U2:
1912                 case MONO_TYPE_I4:
1913                 case MONO_TYPE_U4:
1914                 case MONO_TYPE_I:
1915                 case MONO_TYPE_U:
1916                 case MONO_TYPE_PTR:
1917                 case MONO_TYPE_R4:
1918                 case MONO_TYPE_R8:
1919                 case MONO_TYPE_I8:
1920                 case MONO_TYPE_U8:
1921                         mono_mb_emit_ldarg (mb, i);
1922                         break;
1923                 case MONO_TYPE_STRING:
1924                         if (t->byref) {
1925                                 mono_mb_emit_ldarg (mb, i);
1926                         } else {
1927                                 g_assert (tmp_locals [i]);
1928                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
1929                         }
1930                         break;  
1931                 case MONO_TYPE_CLASS:  
1932                 case MONO_TYPE_ARRAY:
1933                 case MONO_TYPE_SZARRAY:
1934                 case MONO_TYPE_OBJECT:
1935                         /* fixme: conversions ? */
1936                         mono_mb_emit_ldarg (mb, i);
1937                         break;
1938                 case MONO_TYPE_VALUETYPE:
1939                         klass = sig->params [i]->data.klass;
1940                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
1941                             klass->blittable || klass->enumtype) {
1942                                 mono_mb_emit_ldarg (mb, i);
1943                                 break;
1944                         }
1945
1946                         g_assert (tmp_locals [i]);
1947                         if (t->byref)
1948                                 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
1949                         else
1950                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
1951                         break;
1952                 default:
1953                         g_warning ("type 0x%02x unknown", t->type);     
1954                         g_assert_not_reached ();
1955                 }
1956         }
1957
1958         mono_mb_emit_managed_call (mb, method, NULL);
1959
1960         if (!sig->ret->byref) { 
1961                 switch (sig->ret->type) {
1962                 case MONO_TYPE_VOID:
1963                 case MONO_TYPE_BOOLEAN:
1964                 case MONO_TYPE_I1:
1965                 case MONO_TYPE_U1:
1966                 case MONO_TYPE_I2:
1967                 case MONO_TYPE_U2:
1968                 case MONO_TYPE_I4:
1969                 case MONO_TYPE_U4:
1970                 case MONO_TYPE_I:
1971                 case MONO_TYPE_U:
1972                 case MONO_TYPE_PTR:
1973                 case MONO_TYPE_R4:
1974                 case MONO_TYPE_R8:
1975                 case MONO_TYPE_I8:
1976                 case MONO_TYPE_U8:
1977                         mono_mb_emit_byte (mb, CEE_RET);
1978                         break;
1979                 case MONO_TYPE_STRING:          
1980                         csig->ret = &mono_defaults.int_class->byval_arg;
1981
1982                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1983                         mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1984                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
1985                         mono_mb_emit_byte (mb, CEE_RET);
1986                         break;
1987                 case MONO_TYPE_VALUETYPE: {
1988                         int tmp;
1989                         klass = sig->ret->data.klass;
1990                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
1991                             klass->blittable || klass->enumtype)
1992                                 break;
1993                         
1994                         /* load pointer to returned value type */
1995                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1996                         mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
1997                         
1998                         /* store the address of the source into local variable 0 */
1999                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2000                         /* allocate space for the native struct and
2001                          * store the address into dst_ptr */
2002                         tmp = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2003                         g_assert (tmp);
2004                         mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2005                         mono_mb_emit_byte (mb, CEE_PREFIX1);
2006                         mono_mb_emit_byte (mb, CEE_LOCALLOC);
2007                         mono_mb_emit_byte (mb, CEE_STLOC_1);
2008                         mono_mb_emit_byte (mb, CEE_LDLOC_1);
2009                         mono_mb_emit_stloc (mb, tmp);
2010
2011                         /* emit valuetype conversion code */
2012                         emit_struct_conv (mb, klass, FALSE);
2013                         mono_mb_emit_ldloc (mb, tmp);
2014                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2015                         mono_mb_emit_byte (mb, CEE_MONO_RETOBJ);
2016                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2017                         break;
2018                 }
2019                 default:
2020                         g_warning ("return type 0x%02x unknown", sig->ret->type);       
2021                         g_assert_not_reached ();
2022                 }
2023         } else {
2024                 mono_mb_emit_byte (mb, CEE_RET);
2025         }
2026
2027         res = mono_mb_create_method (mb, csig, sig->param_count + 16);
2028         mono_mb_free (mb);
2029
2030         if (!this)
2031                 g_hash_table_insert (cache, method, res);
2032
2033         return res;
2034 }
2035
2036 /*
2037  * mono_marshal_get_ldfld_wrapper:
2038  * @type: the type of the field
2039  *
2040  * This method generates a function which can be use to load a field with type
2041  * @type from an object. The generated function has the following signature:
2042  * <@type> ldfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset)
2043  */
2044 MonoMethod *
2045 mono_marshal_get_ldfld_wrapper (MonoType *type)
2046 {
2047         MonoMethodSignature *sig, *csig;
2048         MonoMethodBuilder *mb;
2049         MonoMethod *res;
2050         MonoClass *klass;
2051         static GHashTable *ldfld_hash = NULL; 
2052         char *name;
2053         int t, pos0, pos1;
2054
2055         if (!ldfld_hash) 
2056                 ldfld_hash = g_hash_table_new (NULL, NULL);
2057
2058
2059         t = type->type;
2060
2061         if (!type->byref) {
2062                 if (type->type == MONO_TYPE_SZARRAY) {
2063                         klass = mono_defaults.array_class;
2064                 } else if (type->type == MONO_TYPE_VALUETYPE) {
2065                         klass = type->data.klass;
2066                         if (klass->enumtype) {
2067                                 t = klass->enum_basetype->type;
2068                                 klass = mono_class_from_mono_type (klass->enum_basetype);
2069                         }
2070                 } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
2071                            t == MONO_TYPE_CLASS) { 
2072                         klass = mono_defaults.object_class;
2073                 } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
2074                         klass = mono_defaults.int_class;
2075                 } else {
2076                         klass = mono_class_from_mono_type (type);                       
2077                 }
2078         } else {
2079                 klass = mono_defaults.int_class;
2080         }
2081
2082         if ((res = g_hash_table_lookup (ldfld_hash, klass)))
2083                 return res;
2084
2085         name = g_strdup_printf ("__ldfld_wrapper_%s.%s", klass->name_space, klass->name); 
2086         mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_LDFLD);
2087         g_free (name);
2088
2089         mb->method->save_lmf = 1;
2090
2091         sig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
2092         sig->params [0] = &mono_defaults.object_class->byval_arg;
2093         sig->params [1] = &mono_defaults.int_class->byval_arg;
2094         sig->params [2] = &mono_defaults.int_class->byval_arg;
2095         sig->params [3] = &mono_defaults.int_class->byval_arg;
2096         sig->ret = &klass->byval_arg;
2097
2098         mono_mb_emit_ldarg (mb, 0);
2099         pos0 = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
2100
2101         mono_mb_emit_ldarg (mb, 0);
2102         mono_mb_emit_ldarg (mb, 1);
2103         mono_mb_emit_ldarg (mb, 2);
2104
2105         csig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
2106         csig->params [0] = &mono_defaults.object_class->byval_arg;
2107         csig->params [1] = &mono_defaults.int_class->byval_arg;
2108         csig->params [2] = &mono_defaults.int_class->byval_arg;
2109         csig->ret = &klass->this_arg;
2110         csig->pinvoke = 1;
2111
2112         mono_mb_emit_native_call (mb, csig, mono_load_remote_field_new);
2113
2114         if (klass->valuetype) {
2115                 mono_mb_emit_byte (mb, CEE_UNBOX);
2116                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));             
2117                 mono_mb_emit_byte (mb, CEE_BR);
2118                 pos1 = mb->pos;
2119                 mono_mb_emit_i4 (mb, 0);
2120         } else {
2121                 mono_mb_emit_byte (mb, CEE_RET);
2122         }
2123
2124
2125         mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
2126
2127         mono_mb_emit_ldarg (mb, 0);
2128         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2129         mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2130         mono_mb_emit_ldarg (mb, 3);
2131         mono_mb_emit_byte (mb, CEE_ADD);
2132
2133         if (klass->valuetype)
2134                 mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
2135
2136         switch (t) {
2137         case MONO_TYPE_I1:
2138         case MONO_TYPE_U1:
2139         case MONO_TYPE_BOOLEAN:
2140                 mono_mb_emit_byte (mb, CEE_LDIND_I1);
2141                 break;
2142         case MONO_TYPE_CHAR:
2143         case MONO_TYPE_I2:
2144         case MONO_TYPE_U2:
2145                 mono_mb_emit_byte (mb, CEE_LDIND_I2);
2146                 break;
2147         case MONO_TYPE_I4:
2148         case MONO_TYPE_U4:
2149                 mono_mb_emit_byte (mb, CEE_LDIND_I4);
2150                 break;
2151         case MONO_TYPE_I8:
2152         case MONO_TYPE_U8:
2153                 mono_mb_emit_byte (mb, CEE_LDIND_I8);
2154                 break;
2155         case MONO_TYPE_R4:
2156                 mono_mb_emit_byte (mb, CEE_LDIND_R4);
2157                 break;
2158         case MONO_TYPE_R8:
2159                 mono_mb_emit_byte (mb, CEE_LDIND_R8);
2160                 break;
2161         case MONO_TYPE_ARRAY:
2162         case MONO_TYPE_PTR:
2163         case MONO_TYPE_FNPTR:
2164         case MONO_TYPE_SZARRAY:
2165         case MONO_TYPE_OBJECT:
2166         case MONO_TYPE_CLASS:
2167         case MONO_TYPE_STRING:
2168         case MONO_TYPE_I:
2169         case MONO_TYPE_U:
2170                 mono_mb_emit_byte (mb, CEE_LDIND_I);
2171                 break;
2172         case MONO_TYPE_VALUETYPE:
2173                 g_assert (!klass->enumtype);
2174                 mono_mb_emit_byte (mb, CEE_LDOBJ);
2175                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2176                 break;
2177         default:
2178                 g_warning ("type %x not implemented", type->type);
2179                 g_assert_not_reached ();
2180         }
2181
2182         mono_mb_emit_byte (mb, CEE_RET);
2183        
2184         res = mono_mb_create_method (mb, sig, sig->param_count + 16);
2185         mono_mb_free (mb);
2186         
2187         g_hash_table_insert (ldfld_hash, klass, res);
2188
2189         return res;
2190 }
2191
2192 /*
2193  * mono_marshal_get_stfld_wrapper:
2194  * @type: the type of the field
2195  *
2196  * This method generates a function which can be use to store a field with type
2197  * @type. The generated function has the following signature:
2198  * void stfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset, <@type> val)
2199  */
2200 MonoMethod *
2201 mono_marshal_get_stfld_wrapper (MonoType *type)
2202 {
2203         MonoMethodSignature *sig, *csig;
2204         MonoMethodBuilder *mb;
2205         MonoMethod *res;
2206         MonoClass *klass;
2207         static GHashTable *stfld_hash = NULL; 
2208         char *name;
2209         int t, pos;
2210
2211         if (!stfld_hash) 
2212                 stfld_hash = g_hash_table_new (NULL, NULL);
2213
2214         t = type->type;
2215
2216         if (!type->byref) {
2217                 if (type->type == MONO_TYPE_SZARRAY) {
2218                         klass = mono_defaults.array_class;
2219                 } else if (type->type == MONO_TYPE_VALUETYPE) {
2220                         klass = type->data.klass;
2221                         if (klass->enumtype) {
2222                                 t = klass->enum_basetype->type;
2223                                 klass = mono_class_from_mono_type (klass->enum_basetype);
2224                         }
2225                 } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
2226                            t == MONO_TYPE_CLASS) { 
2227                         klass = mono_defaults.object_class;
2228                 } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
2229                         klass = mono_defaults.int_class;
2230                 } else {
2231                         klass = mono_class_from_mono_type (type);                       
2232                 }
2233         } else {
2234                 klass = mono_defaults.int_class;
2235         }
2236
2237         if ((res = g_hash_table_lookup (stfld_hash, klass)))
2238                 return res;
2239
2240         name = g_strdup_printf ("__stfld_wrapper_%s.%s", klass->name_space, klass->name); 
2241         mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_STFLD);
2242         g_free (name);
2243
2244         mb->method->save_lmf = 1;
2245
2246         sig = mono_metadata_signature_alloc (mono_defaults.corlib, 5);
2247         sig->params [0] = &mono_defaults.object_class->byval_arg;
2248         sig->params [1] = &mono_defaults.int_class->byval_arg;
2249         sig->params [2] = &mono_defaults.int_class->byval_arg;
2250         sig->params [3] = &mono_defaults.int_class->byval_arg;
2251         sig->params [4] = &klass->byval_arg;
2252         sig->ret = &mono_defaults.void_class->byval_arg;
2253
2254         mono_mb_emit_ldarg (mb, 0);
2255         pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
2256
2257         mono_mb_emit_ldarg (mb, 0);
2258         mono_mb_emit_ldarg (mb, 1);
2259         mono_mb_emit_ldarg (mb, 2);
2260         mono_mb_emit_ldarg (mb, 4);
2261
2262         if (klass->valuetype) {
2263                 mono_mb_emit_byte (mb, CEE_BOX);
2264                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));             
2265         }
2266
2267         csig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
2268         csig->params [0] = &mono_defaults.object_class->byval_arg;
2269         csig->params [1] = &mono_defaults.int_class->byval_arg;
2270         csig->params [2] = &mono_defaults.int_class->byval_arg;
2271         csig->params [3] = &klass->this_arg;
2272         csig->ret = &mono_defaults.void_class->byval_arg;
2273         csig->pinvoke = 1;
2274
2275         mono_mb_emit_native_call (mb, csig, mono_store_remote_field_new);
2276
2277         mono_mb_emit_byte (mb, CEE_RET);
2278
2279         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2280
2281         mono_mb_emit_ldarg (mb, 0);
2282         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2283         mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2284         mono_mb_emit_ldarg (mb, 3);
2285         mono_mb_emit_byte (mb, CEE_ADD);
2286         mono_mb_emit_ldarg (mb, 4);
2287
2288         switch (t) {
2289         case MONO_TYPE_I1:
2290         case MONO_TYPE_U1:
2291         case MONO_TYPE_BOOLEAN:
2292                 mono_mb_emit_byte (mb, CEE_STIND_I1);
2293                 break;
2294         case MONO_TYPE_CHAR:
2295         case MONO_TYPE_I2:
2296         case MONO_TYPE_U2:
2297                 mono_mb_emit_byte (mb, CEE_STIND_I2);
2298                 break;
2299         case MONO_TYPE_I4:
2300         case MONO_TYPE_U4:
2301                 mono_mb_emit_byte (mb, CEE_STIND_I4);
2302                 break;
2303         case MONO_TYPE_I8:
2304         case MONO_TYPE_U8:
2305                 mono_mb_emit_byte (mb, CEE_STIND_I8);
2306                 break;
2307         case MONO_TYPE_R4:
2308                 mono_mb_emit_byte (mb, CEE_STIND_R4);
2309                 break;
2310         case MONO_TYPE_R8:
2311                 mono_mb_emit_byte (mb, CEE_STIND_R8);
2312                 break;
2313         case MONO_TYPE_ARRAY:
2314         case MONO_TYPE_PTR:
2315         case MONO_TYPE_FNPTR:
2316         case MONO_TYPE_SZARRAY:
2317         case MONO_TYPE_OBJECT:
2318         case MONO_TYPE_CLASS:
2319         case MONO_TYPE_STRING:
2320         case MONO_TYPE_I:
2321         case MONO_TYPE_U:
2322                 mono_mb_emit_byte (mb, CEE_STIND_I);
2323                 break;
2324         case MONO_TYPE_VALUETYPE:
2325                 g_assert (!klass->enumtype);
2326                 mono_mb_emit_byte (mb, CEE_STOBJ);
2327                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2328                 break;
2329         default:
2330                 g_warning ("type %x not implemented", type->type);
2331                 g_assert_not_reached ();
2332         }
2333
2334         mono_mb_emit_byte (mb, CEE_RET);
2335        
2336         res = mono_mb_create_method (mb, sig, sig->param_count + 16);
2337         mono_mb_free (mb);
2338         
2339         g_hash_table_insert (stfld_hash, klass, res);
2340
2341         return res;
2342 }
2343
2344 /*
2345  * generates IL code for the icall wrapper (the generated method
2346  * calls the unamnaged code in func)
2347  */
2348 MonoMethod *
2349 mono_marshal_get_icall_wrapper (MonoMethodSignature *sig, const char *name, gconstpointer func)
2350 {
2351         MonoMethodSignature *csig;
2352         MonoMethodBuilder *mb;
2353         MonoMethod *res;
2354         int i, sigsize;
2355
2356         g_assert (sig->pinvoke);
2357
2358         mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_MANAGED_TO_NATIVE);
2359
2360         mb->method->save_lmf = 1;
2361
2362         /* we copy the signature, so that we can modify it */
2363         sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
2364
2365         if (sig->hasthis)
2366                 mono_mb_emit_byte (mb, CEE_LDARG_0);
2367
2368         for (i = 0; i < sig->param_count; i++)
2369                 mono_mb_emit_ldarg (mb, i + sig->hasthis);
2370
2371         mono_mb_emit_native_call (mb, sig, func);
2372
2373         mono_mb_emit_byte (mb, CEE_RET);
2374
2375         csig = g_memdup (sig, sigsize);
2376         csig->pinvoke = 0;
2377
2378         res = mono_mb_create_method (mb, csig, csig->param_count + 16);
2379         mono_mb_free (mb);
2380         
2381         return res;
2382 }
2383
2384 /*
2385  * generates IL code for the pinvoke wrapper (the generated method
2386  * calls the unamnage code in method->addr)
2387  */
2388 MonoMethod *
2389 mono_marshal_get_native_wrapper (MonoMethod *method)
2390 {
2391         MonoMethodSignature *sig, *csig;
2392         MonoMethodBuilder *mb;
2393         MonoMarshalSpec **mspecs;
2394         MonoMethod *res;
2395         GHashTable *cache;
2396         MonoClass *klass;
2397         gboolean pinvoke = FALSE;
2398         int i, pos, argnum, *tmp_locals;
2399         int type, sigsize;
2400
2401         g_assert (method != NULL);
2402         g_assert (method->signature->pinvoke);
2403
2404         cache = method->klass->image->native_wrapper_cache;
2405         if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
2406                 return res;
2407
2408         sig = method->signature;
2409         sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
2410
2411         if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
2412             (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2413                 pinvoke = TRUE;
2414
2415         mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_MANAGED_TO_NATIVE);
2416
2417         mb->method->save_lmf = 1;
2418
2419         if (pinvoke && !method->addr)
2420                 mono_lookup_pinvoke_call (method);
2421
2422         if (!method->addr) {
2423                 mono_mb_emit_exception (mb);
2424                 csig = g_memdup (sig, sigsize);
2425                 csig->pinvoke = 0;
2426                 res = mono_mb_create_method (mb, csig, csig->param_count + 16);
2427                 mono_mb_free (mb);
2428                 g_hash_table_insert (cache, method, res);
2429                 return res;
2430         }
2431
2432         /* internal calls: we simply push all arguments and call the method (no conversions) */
2433         if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
2434
2435                 /* hack - string constructors returns a value */
2436                 if (method->string_ctor) {
2437                         csig = g_memdup (sig, sigsize);
2438                         csig->ret = &mono_defaults.string_class->byval_arg;
2439                 } else
2440                         csig = sig;
2441
2442                 if (sig->hasthis)
2443                         mono_mb_emit_byte (mb, CEE_LDARG_0);
2444
2445                 for (i = 0; i < sig->param_count; i++)
2446                         mono_mb_emit_ldarg (mb, i + sig->hasthis);
2447
2448                 g_assert (method->addr);
2449                 mono_mb_emit_native_call (mb, csig, method->addr);
2450
2451                 mono_mb_emit_byte (mb, CEE_RET);
2452
2453                 csig = g_memdup (csig, sigsize);
2454                 csig->pinvoke = 0;
2455                 res = mono_mb_create_method (mb, csig, csig->param_count + 16);
2456                 mono_mb_free (mb);
2457                 g_hash_table_insert (cache, method, res);
2458                 return res;
2459         }
2460
2461         g_assert (pinvoke);
2462
2463         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
2464         mono_method_get_marshal_info (method, mspecs);
2465
2466         /* pinvoke: we need to convert the arguments if necessary */
2467
2468         /* we copy the signature, so that we can set pinvoke to 0 */
2469         csig = g_memdup (sig, sigsize);
2470         csig->pinvoke = 1;
2471
2472         /* we allocate local for use with emit_struct_conv() */
2473         /* allocate local 0 (pointer) src_ptr */
2474         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2475         /* allocate local 1 (pointer) dst_ptr */
2476         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2477         /* allocate local 2 (boolean) delete_old */
2478         mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2479
2480         /* delete_old = FALSE */
2481         mono_mb_emit_icon (mb, 0);
2482         mono_mb_emit_byte (mb, CEE_STLOC_2);
2483
2484         if (sig->ret->type != MONO_TYPE_VOID) {
2485                 /* allocate local 3 to store the return value */
2486                 mono_mb_add_local (mb, sig->ret);
2487         }
2488
2489         /* we first do all conversions */
2490         tmp_locals = alloca (sizeof (int) * sig->param_count);
2491         for (i = 0; i < sig->param_count; i ++) {
2492                 MonoType *t = sig->params [i];
2493                 MonoMarshalSpec *spec = mspecs [i + 1];
2494
2495                 argnum = i + sig->hasthis;
2496                 tmp_locals [i] = 0;
2497
2498                 switch (t->type) {
2499                 case MONO_TYPE_VALUETYPE:                       
2500                         klass = t->data.klass;
2501
2502                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2503                             klass->blittable || klass->enumtype)
2504                                 break;
2505
2506                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2507                         
2508                         /* store the address of the source into local variable 0 */
2509                         if (t->byref)
2510                                 mono_mb_emit_ldarg (mb, argnum);
2511                         else
2512                                 mono_mb_emit_ldarg_addr (mb, argnum);
2513
2514                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2515                         
2516                         /* allocate space for the native struct and
2517                          * store the address into local variable 1 (dest) */
2518                         mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2519                         mono_mb_emit_byte (mb, CEE_PREFIX1);
2520                         mono_mb_emit_byte (mb, CEE_LOCALLOC);
2521                         mono_mb_emit_stloc (mb, tmp_locals [i]);
2522
2523                         if (t->byref) {
2524                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2525                                 mono_mb_emit_byte (mb, CEE_BRFALSE);
2526                                 pos = mb->pos;
2527                                 mono_mb_emit_i4 (mb, 0);
2528                         }
2529
2530                         /* set dst_ptr */
2531                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
2532                         mono_mb_emit_byte (mb, CEE_STLOC_1);
2533
2534                         /* emit valuetype conversion code */
2535                         emit_struct_conv (mb, klass, FALSE);
2536                         
2537                         if (t->byref)
2538                                 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2539                         break;
2540                 case MONO_TYPE_STRING:
2541                         if (t->byref)
2542                                 continue;
2543
2544                         csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2545                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2546
2547                         mono_mb_emit_ldarg (mb, argnum);
2548                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2549                         mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2550
2551                         if (spec) {
2552                                 switch (spec->native) {
2553                                 case MONO_NATIVE_LPWSTR:
2554                                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPWSTR);
2555                                         break;
2556                                 case MONO_NATIVE_LPSTR:
2557                                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
2558                                         break;
2559                                 default:
2560                                         g_warning ("marshalling conversion %d not implemented", spec->native);
2561                                         g_assert_not_reached ();
2562                                 }
2563                         } else {
2564                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
2565                         }
2566
2567                         mono_mb_emit_stloc (mb, tmp_locals [i]);
2568                         break;
2569                 case MONO_TYPE_CLASS:
2570                         if (t->byref)
2571                                 continue;
2572
2573                         csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2574                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2575
2576                         if (t->data.klass->delegate) {
2577                                 mono_mb_emit_ldarg (mb, argnum);
2578                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2579                                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2580                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_DEL_FTN);
2581                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
2582                         } else if (t->data.klass == mono_defaults.stringbuilder_class) {
2583                                 mono_mb_emit_ldarg (mb, argnum);
2584                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2585                                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2586                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_SB_LPSTR);
2587                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
2588                         } else {
2589                                 mono_mb_emit_ldarg (mb, argnum);
2590                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2591                                 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2592                                 /* fixme: convert to what ? */
2593                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
2594                         }
2595
2596                         break;
2597                 case MONO_TYPE_OBJECT:
2598                         if (t->byref)
2599                                 continue;
2600                         csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2601                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2602                         /* 
2603                          * FIXME: this may need special handling to inspect the type
2604                          * at runtime.
2605                          */
2606                         mono_mb_emit_ldarg (mb, argnum);
2607                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2608                         mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2609                         /* fixme: convert to what ? */
2610                         mono_mb_emit_stloc (mb, tmp_locals [i]);
2611                         break;
2612                 case MONO_TYPE_ARRAY:
2613                 case MONO_TYPE_SZARRAY:
2614                         if (t->byref)
2615                                 continue;
2616
2617                         klass = mono_class_from_mono_type (t);
2618
2619                         csig->params [argnum] = &mono_defaults.int_class->byval_arg;
2620                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2621
2622                         mono_mb_emit_ldarg (mb, argnum);
2623                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2624                         mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2625                         if (klass->element_class == mono_defaults.string_class) 
2626                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STRARRAY_STRLPARRAY);
2627                         else
2628                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_ARRAY_LPARRAY);
2629                         mono_mb_emit_stloc (mb, tmp_locals [i]);
2630                         break;
2631                 }
2632         }
2633
2634         /* push all arguments */
2635
2636         if (sig->hasthis)
2637                 mono_mb_emit_byte (mb, CEE_LDARG_0);
2638
2639         for (i = 0; i < sig->param_count; i++) {
2640                 MonoType *t = sig->params [i];
2641                 
2642                 argnum = i + sig->hasthis;
2643
2644                 switch (t->type) {
2645                 case MONO_TYPE_BOOLEAN:
2646                         if (t->byref)
2647                                 g_warning ("byref boolean marshalling not inplemented");
2648                         mono_mb_emit_ldarg (mb, argnum);
2649                         break;
2650                 case MONO_TYPE_I1:
2651                 case MONO_TYPE_U1:
2652                 case MONO_TYPE_I2:
2653                 case MONO_TYPE_U2:
2654                 case MONO_TYPE_I4:
2655                 case MONO_TYPE_U4:
2656                 case MONO_TYPE_I:
2657                 case MONO_TYPE_U:
2658                 case MONO_TYPE_PTR:
2659                 case MONO_TYPE_R4:
2660                 case MONO_TYPE_R8:
2661                 case MONO_TYPE_I8:
2662                 case MONO_TYPE_U8:
2663                         mono_mb_emit_ldarg (mb, argnum);
2664                         break;
2665                 case MONO_TYPE_VALUETYPE:
2666                         klass = sig->params [i]->data.klass;
2667                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2668                             klass->blittable || klass->enumtype) {
2669                                 mono_mb_emit_ldarg (mb, argnum);
2670                                 break;
2671                         }                       
2672                         g_assert (tmp_locals [i]);
2673                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
2674                         if (!t->byref) {
2675                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2676                                 mono_mb_emit_byte (mb, CEE_MONO_LDNATIVEOBJ);
2677                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2678                         }
2679                         break;
2680                 case MONO_TYPE_STRING:
2681                         if (t->byref) {
2682                                 mono_mb_emit_ldarg (mb, argnum);
2683                         } else {
2684                                 g_assert (tmp_locals [i]);
2685                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2686                         }
2687                         break;
2688                 case MONO_TYPE_CLASS:
2689                 case MONO_TYPE_OBJECT:
2690                         if (t->byref) {
2691                                 mono_mb_emit_ldarg (mb, argnum);
2692                         } else {
2693                                 g_assert (tmp_locals [i]);
2694                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2695                         }
2696                         break;
2697                 case MONO_TYPE_CHAR:
2698                         /* fixme: dont know how to marshal that. We cant simply
2699                          * convert it to a one byte UTF8 character, because an
2700                          * unicode character may need more that one byte in UTF8 */
2701                         mono_mb_emit_ldarg (mb, argnum);
2702                         break;
2703                 case MONO_TYPE_ARRAY:
2704                 case MONO_TYPE_SZARRAY:
2705                         if (t->byref) {
2706                                 mono_mb_emit_ldarg (mb, argnum);
2707                         } else {
2708                                 g_assert (tmp_locals [i]);
2709                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2710                         }
2711                         break;
2712                 case MONO_TYPE_TYPEDBYREF:
2713                 case MONO_TYPE_FNPTR:
2714                 default:
2715                         g_warning ("type 0x%02x unknown", t->type);     
2716                         g_assert_not_reached ();
2717                 }
2718         }                       
2719
2720         /* call the native method */
2721         mono_mb_emit_native_call (mb, csig, method->addr);
2722
2723         /* return the result */
2724
2725         /* we need to convert byref arguments back and free string arrays */
2726         for (i = 0; i < sig->param_count; i++) {
2727                 MonoType *t = sig->params [i];
2728                 
2729                 argnum = i + sig->hasthis;
2730
2731                 switch (t->type) {
2732                 case MONO_TYPE_CLASS:
2733                 case MONO_TYPE_OBJECT:                  
2734                         if (t->byref)
2735                                 continue;
2736      
2737                         if (t->data.klass == mono_defaults.stringbuilder_class) {
2738                                 mono_mb_emit_ldarg (mb, argnum);
2739                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2740                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2741                                 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
2742                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_SB);
2743                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2744                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2745                                 mono_mb_emit_byte (mb, CEE_MONO_FREE);
2746                         }
2747                         break;
2748                 case MONO_TYPE_VALUETYPE:
2749                         if (!t->byref)
2750                                 continue;
2751         
2752                         klass = t->data.klass;
2753                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2754                             klass->blittable || klass->enumtype)
2755                                 break;
2756
2757                         /* dst = argument */
2758                         mono_mb_emit_ldarg (mb, argnum);
2759                         mono_mb_emit_byte (mb, CEE_STLOC_1);
2760
2761                         mono_mb_emit_byte (mb, CEE_LDLOC_1);
2762                         mono_mb_emit_byte (mb, CEE_BRFALSE);
2763                         pos = mb->pos;
2764                         mono_mb_emit_i4 (mb, 0);
2765
2766                         /* src = tmp_locals [i] */
2767                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
2768                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2769
2770                         /* emit valuetype conversion code */
2771                         emit_struct_conv (mb, klass, TRUE);
2772                         
2773                         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2774                         break;
2775                 case MONO_TYPE_SZARRAY:
2776                         if (t->byref)
2777                                 continue;
2778  
2779                         klass = mono_class_from_mono_type (t);
2780                         
2781                         if (klass->element_class == mono_defaults.string_class) {
2782                                 g_assert (tmp_locals [i]);
2783
2784                                 mono_mb_emit_ldarg (mb, argnum);
2785                                 mono_mb_emit_byte (mb, CEE_BRFALSE);
2786                                 pos = mb->pos;
2787                                 mono_mb_emit_i4 (mb, 0);
2788
2789                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2790                                 mono_mb_emit_ldarg (mb, argnum);
2791                                 mono_mb_emit_byte (mb, CEE_LDLEN);                              
2792                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2793                                 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
2794                                 mono_mb_emit_byte (mb, MONO_MARSHAL_FREE_ARRAY);
2795
2796                                 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2797                         }
2798
2799                         break;
2800                 }
2801         }
2802
2803         if (!sig->ret->byref) {
2804                 MonoMarshalSpec *spec = mspecs [0];
2805                 type = sig->ret->type;
2806
2807         handle_enum:
2808                 switch (type) {
2809                 case MONO_TYPE_VOID:
2810                 case MONO_TYPE_I1:
2811                 case MONO_TYPE_U1:
2812                 case MONO_TYPE_I2:
2813                 case MONO_TYPE_U2:
2814                 case MONO_TYPE_I4:
2815                 case MONO_TYPE_U4:
2816                 case MONO_TYPE_I:
2817                 case MONO_TYPE_U:
2818                 case MONO_TYPE_PTR:
2819                 case MONO_TYPE_R4:
2820                 case MONO_TYPE_R8:
2821                 case MONO_TYPE_I8:
2822                 case MONO_TYPE_U8:
2823                 /* no conversions necessary */
2824                         break;
2825                 case MONO_TYPE_BOOLEAN:
2826                         /* maybe we need to make sure that it fits within 8 bits */
2827                         break;
2828                 case MONO_TYPE_VALUETYPE: {
2829                         int tmp;
2830
2831                         klass = sig->ret->data.klass;
2832                         if (klass->enumtype) {
2833                                 type = sig->ret->data.klass->enum_basetype->type;
2834                                 goto handle_enum;
2835                         }
2836
2837                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2838                             klass->blittable)
2839                                 break;
2840
2841                         tmp = mono_mb_add_local (mb, sig->ret);
2842                         g_assert (tmp);
2843                         /* load pointer to returned value type */
2844                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2845                         mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
2846                         /* store the address of the source into local variable 0 */
2847                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2848                         /* set dst_ptr */
2849                         mono_mb_emit_ldloc_addr (mb, tmp);
2850                         mono_mb_emit_byte (mb, CEE_STLOC_1);
2851
2852                         /* emit valuetype conversion code */
2853                         emit_struct_conv (mb, sig->ret->data.klass, TRUE);
2854
2855                         mono_mb_emit_ldloc (mb, tmp);
2856                         break;
2857                 }
2858                 case MONO_TYPE_STRING:
2859                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2860                         mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2861                         if (spec) {
2862                                 switch (spec->native) {
2863                                 case MONO_NATIVE_LPWSTR:
2864                                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPWSTR_STR);
2865                                         break;
2866                                 default:
2867                                         g_warning ("marshalling conversion not implemented");
2868                                         g_assert_not_reached ();
2869                                 }
2870                         } else {
2871                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
2872                         }
2873                         break;
2874                 case MONO_TYPE_ARRAY:
2875                 case MONO_TYPE_SZARRAY:
2876                 case MONO_TYPE_CLASS:
2877                 case MONO_TYPE_OBJECT:
2878                         /* fixme: we need conversions here */
2879                         break;
2880                 case MONO_TYPE_CHAR:
2881                         /* fixme: we need conversions here */
2882                         break;
2883                 case MONO_TYPE_TYPEDBYREF:
2884                 case MONO_TYPE_FNPTR:
2885                 default:
2886                         g_warning ("return type 0x%02x unknown", sig->ret->type);       
2887                         g_assert_not_reached ();
2888                 }
2889         }
2890
2891         mono_mb_emit_byte (mb, CEE_RET);
2892
2893         csig = g_memdup (sig, sigsize);
2894         csig->pinvoke = 0;
2895         res = mono_mb_create_method (mb, csig, csig->param_count + 16);
2896         mono_mb_free (mb);
2897
2898         g_hash_table_insert (cache, method, res);
2899
2900         for (i = sig->param_count; i >= 0; i--)
2901                 g_free (mspecs [i]);
2902         g_free (mspecs);
2903
2904         return res;
2905 }
2906
2907 /*
2908  * generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld)
2909  */
2910 MonoMethod *
2911 mono_marshal_get_struct_to_ptr (MonoClass *klass)
2912 {
2913         MonoMethodBuilder *mb;
2914         static MonoMethod *stoptr = NULL;
2915         MonoMethod *res;
2916
2917         g_assert (klass != NULL);
2918
2919         if (klass->str_to_ptr)
2920                 return klass->str_to_ptr;
2921
2922         if (!stoptr) 
2923                 stoptr = mono_find_method_by_name (mono_defaults.marshal_class, "StructureToPtr", 3);
2924         g_assert (stoptr);
2925
2926         mb = mono_mb_new (klass, stoptr->name, MONO_WRAPPER_UNKNOWN);
2927
2928         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable) {
2929                 mono_mb_emit_byte (mb, CEE_LDARG_1);
2930                 mono_mb_emit_byte (mb, CEE_LDARG_0);
2931                 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
2932                 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
2933                 mono_mb_emit_byte (mb, CEE_PREFIX1);
2934                 mono_mb_emit_byte (mb, CEE_CPBLK);
2935         } else {
2936
2937                 /* allocate local 0 (pointer) src_ptr */
2938                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2939                 /* allocate local 1 (pointer) dst_ptr */
2940                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2941                 /* allocate local 2 (boolean) delete_old */
2942                 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2943                 mono_mb_emit_byte (mb, CEE_LDARG_2);
2944                 mono_mb_emit_byte (mb, CEE_STLOC_2);
2945
2946                 /* initialize src_ptr to point to the start of object data */
2947                 mono_mb_emit_byte (mb, CEE_LDARG_0);
2948                 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
2949                 mono_mb_emit_byte (mb, CEE_STLOC_0);
2950
2951                 /* initialize dst_ptr */
2952                 mono_mb_emit_byte (mb, CEE_LDARG_1);
2953                 mono_mb_emit_byte (mb, CEE_STLOC_1);
2954
2955                 emit_struct_conv (mb, klass, FALSE);
2956         }
2957
2958         mono_mb_emit_byte (mb, CEE_RET);
2959
2960         res = mono_mb_create_method (mb, stoptr->signature, 0);
2961         mono_mb_free (mb);
2962
2963         klass->str_to_ptr = res;
2964         return res;
2965 }
2966
2967 /*
2968  * generates IL code for PtrToStructure (IntPtr src, object structure)
2969  */
2970 MonoMethod *
2971 mono_marshal_get_ptr_to_struct (MonoClass *klass)
2972 {
2973         MonoMethodBuilder *mb;
2974         static MonoMethod *ptostr = NULL;
2975         MonoMethod *res;
2976
2977         g_assert (klass != NULL);
2978
2979         if (klass->ptr_to_str)
2980                 return klass->ptr_to_str;
2981
2982         if (!ptostr) 
2983                 ptostr = mono_find_method_by_name (mono_defaults.marshal_class, "PtrToStructure", 2);
2984         g_assert (ptostr);
2985
2986         mb = mono_mb_new (klass, ptostr->name, MONO_WRAPPER_UNKNOWN);
2987
2988         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable) {
2989                 mono_mb_emit_byte (mb, CEE_LDARG_1);
2990                 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
2991                 mono_mb_emit_byte (mb, CEE_LDARG_0);
2992                 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
2993                 mono_mb_emit_byte (mb, CEE_PREFIX1);
2994                 mono_mb_emit_byte (mb, CEE_CPBLK);
2995         } else {
2996
2997                 /* allocate local 0 (pointer) src_ptr */
2998                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2999                 /* allocate local 1 (pointer) dst_ptr */
3000                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3001                 
3002                 /* initialize src_ptr to point to the start of object data */
3003                 mono_mb_emit_byte (mb, CEE_LDARG_0);
3004                 mono_mb_emit_byte (mb, CEE_STLOC_0);
3005
3006                 /* initialize dst_ptr */
3007                 mono_mb_emit_byte (mb, CEE_LDARG_1);
3008                 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3009                 mono_mb_emit_byte (mb, CEE_STLOC_1);
3010
3011                 emit_struct_conv (mb, klass, TRUE);
3012         }
3013
3014         mono_mb_emit_byte (mb, CEE_RET);
3015
3016         res = mono_mb_create_method (mb, ptostr->signature, 0);
3017         mono_mb_free (mb);
3018
3019         klass->ptr_to_str = res;
3020         return res;
3021 }
3022
3023 /* FIXME: on win32 we should probably use GlobalAlloc(). */
3024 void*
3025 mono_marshal_alloc (gpointer size) 
3026 {
3027         MONO_ARCH_SAVE_REGS;
3028
3029         return g_try_malloc ((gulong)size);
3030 }
3031
3032 void
3033 mono_marshal_free (gpointer ptr) 
3034 {
3035         MONO_ARCH_SAVE_REGS;
3036
3037         g_free (ptr);
3038 }
3039
3040 void
3041 mono_marshal_free_array (gpointer *ptr, int size) 
3042 {
3043         int i;
3044
3045         printf ("TESTFREE %p\n", ptr);
3046         if (!ptr)
3047                 return;
3048
3049         for (i = 0; i < size; i++)
3050                 if (ptr [i])
3051                         g_free (ptr [i]);
3052 }
3053
3054 void *
3055 mono_marshal_realloc (gpointer ptr, gpointer size) 
3056 {
3057         MONO_ARCH_SAVE_REGS;
3058
3059         return g_try_realloc (ptr, (gulong)size);
3060 }
3061
3062 void *
3063 mono_marshal_string_array (MonoArray *array)
3064 {
3065         char **result;
3066         int i, len;
3067
3068         if (!array)
3069                 return NULL;
3070
3071         len = mono_array_length (array);
3072
3073         result = g_malloc (sizeof (char *) * (len + 1));
3074         for (i = 0; i < len; ++i) {
3075                 MonoString *s = (MonoString *)mono_array_get (array, gpointer, i);
3076                 result [i] = s ? mono_string_to_utf8 (s): NULL;
3077         }
3078         /* null terminate the array */
3079         result [i] = NULL;
3080
3081         return result;
3082 }
3083
3084 void
3085 ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArray *src, gint32 start_index,
3086                                                                     gpointer dest, gint32 length)
3087 {
3088         int element_size;
3089         void *source_addr;
3090
3091         MONO_ARCH_SAVE_REGS;
3092
3093         MONO_CHECK_ARG_NULL (src);
3094         MONO_CHECK_ARG_NULL (dest);
3095
3096         g_assert (src->obj.vtable->klass->rank == 1);
3097         g_assert (start_index >= 0);
3098         g_assert (length >= 0);
3099         g_assert (start_index + length <= mono_array_length (src));
3100
3101         element_size = mono_array_element_size (src->obj.vtable->klass);
3102           
3103         source_addr = mono_array_addr_with_size (src, element_size, start_index);
3104
3105         memcpy (dest, source_addr, length * element_size);
3106 }
3107
3108 void
3109 ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer src, gint32 start_index,
3110                                                                       MonoArray *dest, gint32 length)
3111 {
3112         int element_size;
3113         void *dest_addr;
3114
3115         MONO_ARCH_SAVE_REGS;
3116
3117         MONO_CHECK_ARG_NULL (src);
3118         MONO_CHECK_ARG_NULL (dest);
3119
3120         g_assert (dest->obj.vtable->klass->rank == 1);
3121         g_assert (start_index >= 0);
3122         g_assert (length >= 0);
3123         g_assert (start_index + length <= mono_array_length (dest));
3124
3125         element_size = mono_array_element_size (dest->obj.vtable->klass);
3126           
3127         dest_addr = mono_array_addr_with_size (dest, element_size, start_index);
3128
3129         memcpy (dest_addr, src, length * element_size);
3130 }
3131
3132 gpointer
3133 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr, gint32 offset)
3134 {
3135         char *p = ptr;
3136
3137         MONO_ARCH_SAVE_REGS;
3138
3139         return *(gpointer*)(p + offset);
3140 }
3141
3142 unsigned char
3143 ves_icall_System_Runtime_InteropServices_Marshal_ReadByte (gpointer ptr, gint32 offset)
3144 {
3145         char *p = ptr;
3146
3147         MONO_ARCH_SAVE_REGS;
3148
3149         return *(unsigned char*)(p + offset);
3150 }
3151
3152 gint16
3153 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt16 (gpointer ptr, gint32 offset)
3154 {
3155         char *p = ptr;
3156
3157         MONO_ARCH_SAVE_REGS;
3158
3159         return *(gint16*)(p + offset);
3160 }
3161
3162 gint32
3163 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt32 (gpointer ptr, gint32 offset)
3164 {
3165         char *p = ptr;
3166
3167         MONO_ARCH_SAVE_REGS;
3168
3169         return *(gint32*)(p + offset);
3170 }
3171
3172 gint64
3173 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt64 (gpointer ptr, gint32 offset)
3174 {
3175         char *p = ptr;
3176
3177         MONO_ARCH_SAVE_REGS;
3178
3179         return *(gint64*)(p + offset);
3180 }
3181
3182 void
3183 ves_icall_System_Runtime_InteropServices_Marshal_WriteByte (gpointer ptr, gint32 offset, unsigned char val)
3184 {
3185         char *p = ptr;
3186
3187         MONO_ARCH_SAVE_REGS;
3188
3189         *(unsigned char*)(p + offset) = val;
3190 }
3191
3192 void
3193 ves_icall_System_Runtime_InteropServices_Marshal_WriteIntPtr (gpointer ptr, gint32 offset, gpointer val)
3194 {
3195         char *p = ptr;
3196
3197         MONO_ARCH_SAVE_REGS;
3198
3199         *(gpointer*)(p + offset) = val;
3200 }
3201
3202 void
3203 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt16 (gpointer ptr, gint32 offset, gint16 val)
3204 {
3205         char *p = ptr;
3206
3207         MONO_ARCH_SAVE_REGS;
3208
3209         *(gint16*)(p + offset) = val;
3210 }
3211
3212 void
3213 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt32 (gpointer ptr, gint32 offset, gint32 val)
3214 {
3215         char *p = ptr;
3216
3217         MONO_ARCH_SAVE_REGS;
3218
3219         *(gint32*)(p + offset) = val;
3220 }
3221
3222 void
3223 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt64 (gpointer ptr, gint32 offset, gint64 val)
3224 {
3225         char *p = ptr;
3226
3227         MONO_ARCH_SAVE_REGS;
3228
3229         *(gint64*)(p + offset) = val;
3230 }
3231
3232 MonoString *
3233 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (char *ptr)
3234 {
3235         MONO_ARCH_SAVE_REGS;
3236
3237         return mono_string_new (mono_domain_get (), ptr);
3238 }
3239
3240 MonoString *
3241 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len (char *ptr, gint32 len)
3242 {
3243         MONO_ARCH_SAVE_REGS;
3244
3245         return mono_string_new_len (mono_domain_get (), ptr, len);
3246 }
3247
3248 MonoString *
3249 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni (guint16 *ptr)
3250 {
3251         MonoDomain *domain = mono_domain_get (); 
3252         int len = 0;
3253         guint16 *t = ptr;
3254
3255         MONO_ARCH_SAVE_REGS;
3256
3257         while (*t++)
3258                 len++;
3259
3260         return mono_string_new_utf16 (domain, ptr, len);
3261 }
3262
3263 MonoString *
3264 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len (guint16 *ptr, gint32 len)
3265 {
3266         MonoDomain *domain = mono_domain_get (); 
3267
3268         MONO_ARCH_SAVE_REGS;
3269
3270         return mono_string_new_utf16 (domain, ptr, len);
3271 }
3272
3273 MonoString *
3274 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR (gpointer ptr)
3275 {
3276         MONO_ARCH_SAVE_REGS;
3277
3278         g_warning ("PtrToStringBSTR not implemented");
3279         g_assert_not_reached ();
3280
3281         return NULL;
3282 }
3283
3284 guint32 
3285 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
3286 {
3287         MONO_ARCH_SAVE_REGS;
3288
3289         return (GetLastError ());
3290 }
3291
3292 guint32 
3293 ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype)
3294 {
3295         MonoClass *klass;
3296
3297         MONO_ARCH_SAVE_REGS;
3298
3299         MONO_CHECK_ARG_NULL (rtype);
3300
3301         klass = mono_class_from_mono_type (rtype->type);
3302
3303         return mono_class_native_size (klass, NULL);
3304 }
3305
3306 void
3307 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old)
3308 {
3309         MonoMethod *method;
3310         gpointer pa [3];
3311
3312         MONO_ARCH_SAVE_REGS;
3313
3314         MONO_CHECK_ARG_NULL (obj);
3315         MONO_CHECK_ARG_NULL (dst);
3316
3317         method = mono_marshal_get_struct_to_ptr (obj->vtable->klass);
3318
3319         pa [0] = obj;
3320         pa [1] = &dst;
3321         pa [2] = &delete_old;
3322
3323         mono_runtime_invoke (method, NULL, pa, NULL);
3324 }
3325
3326 void
3327 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, MonoObject *dst)
3328 {
3329         MonoMethod *method;
3330         gpointer pa [2];
3331
3332         MONO_ARCH_SAVE_REGS;
3333
3334         MONO_CHECK_ARG_NULL (src);
3335         MONO_CHECK_ARG_NULL (dst);
3336
3337         method = mono_marshal_get_ptr_to_struct (dst->vtable->klass);
3338
3339         pa [0] = &src;
3340         pa [1] = dst;
3341
3342         mono_runtime_invoke (method, NULL, pa, NULL);
3343 }
3344
3345 MonoObject *
3346 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer src, MonoReflectionType *type)
3347 {
3348         MonoDomain *domain = mono_domain_get (); 
3349         MonoObject *res;
3350
3351         MONO_ARCH_SAVE_REGS;
3352
3353         MONO_CHECK_ARG_NULL (src);
3354         MONO_CHECK_ARG_NULL (type);
3355
3356         res = mono_object_new (domain, mono_class_from_mono_type (type->type));
3357
3358         ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (src, res);
3359
3360         return res;
3361 }
3362
3363 int
3364 ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *type, MonoString *field_name)
3365 {
3366         MonoMarshalType *info;
3367         MonoClass *klass;
3368         char *fname;
3369         int i;
3370
3371         MONO_ARCH_SAVE_REGS;
3372
3373         MONO_CHECK_ARG_NULL (type);
3374         MONO_CHECK_ARG_NULL (field_name);
3375
3376         fname = mono_string_to_utf8 (field_name);
3377         klass = mono_class_from_mono_type (type->type);
3378
3379         info = mono_marshal_load_type_info (klass);     
3380         
3381         for (i = 0; i < klass->field.count; ++i) {
3382                 if (*fname == *klass->fields [i].name && 
3383                     strcmp (fname, klass->fields [i].name) == 0)
3384                         break;
3385         }
3386         g_free (fname);
3387
3388         mono_assert (i < klass->field.count);
3389
3390         return info->fields [i].offset;
3391 }
3392
3393 gpointer
3394 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString *string)
3395 {
3396         MONO_ARCH_SAVE_REGS;
3397
3398         return mono_string_to_utf8 (string);
3399 }
3400
3401 gpointer
3402 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni (MonoString *string)
3403 {
3404         MONO_ARCH_SAVE_REGS;
3405
3406         return g_memdup (mono_string_chars (string), mono_string_length (string)*2);
3407 }
3408
3409 static void
3410 mono_struct_delete_old (MonoClass *klass, char *ptr)
3411 {
3412         MonoMarshalType *info;
3413         int i;
3414
3415         info = mono_marshal_load_type_info (klass);
3416
3417         for (i = 0; i < info->num_fields; i++) {
3418                 MonoMarshalNative ntype;
3419                 MonoMarshalConv conv;
3420                 MonoType *ftype = info->fields [i].field->type;
3421                 char *cpos;
3422
3423                 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
3424                         continue;
3425
3426                 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, 
3427                                                 klass->unicode, &conv);
3428                         
3429                 cpos = ptr + info->fields [i].offset;
3430
3431                 switch (conv) {
3432                 case MONO_MARSHAL_CONV_NONE:
3433                         if (MONO_TYPE_ISSTRUCT (ftype)) {
3434                                 mono_struct_delete_old (ftype->data.klass, cpos);
3435                                 continue;
3436                         }
3437                         break;
3438                 case MONO_MARSHAL_CONV_STR_LPWSTR:
3439                 case MONO_MARSHAL_CONV_STR_LPSTR:
3440                 case MONO_MARSHAL_CONV_STR_LPTSTR:
3441                 case MONO_MARSHAL_CONV_STR_BSTR:
3442                 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
3443                 case MONO_MARSHAL_CONV_STR_TBSTR:
3444                         g_free (*(gpointer *)cpos);
3445                         break;
3446                 default:
3447                         continue;
3448                 }
3449         }
3450 }
3451
3452 void
3453 ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure (gpointer src, MonoReflectionType *type)
3454 {
3455         MonoClass *klass;
3456
3457         MONO_ARCH_SAVE_REGS;
3458
3459         MONO_CHECK_ARG_NULL (src);
3460         MONO_CHECK_ARG_NULL (type);
3461
3462         klass = mono_class_from_mono_type (type->type);
3463
3464         mono_struct_delete_old (klass, (char *)src);
3465 }
3466