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