2003-05-08 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 (!MONO_TYPE_IS_VOID(sig->ret)) {
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         /* convert and the result */
2764         if (!sig->ret->byref) {
2765                 MonoMarshalSpec *spec = mspecs [0];
2766                 type = sig->ret->type;
2767
2768         handle_enum:
2769                 switch (type) {
2770                 case MONO_TYPE_VOID:
2771                         break;
2772                 case MONO_TYPE_I1:
2773                 case MONO_TYPE_U1:
2774                 case MONO_TYPE_I2:
2775                 case MONO_TYPE_U2:
2776                 case MONO_TYPE_I4:
2777                 case MONO_TYPE_U4:
2778                 case MONO_TYPE_I:
2779                 case MONO_TYPE_U:
2780                 case MONO_TYPE_PTR:
2781                 case MONO_TYPE_R4:
2782                 case MONO_TYPE_R8:
2783                 case MONO_TYPE_I8:
2784                 case MONO_TYPE_U8:
2785                         /* no conversions necessary */
2786                         mono_mb_emit_byte (mb, CEE_STLOC_3);
2787                         break;
2788                 case MONO_TYPE_BOOLEAN:
2789                         /* maybe we need to make sure that it fits within 8 bits */
2790                         mono_mb_emit_byte (mb, CEE_STLOC_3);
2791                         break;
2792                 case MONO_TYPE_VALUETYPE:
2793                         klass = sig->ret->data.klass;
2794                         if (klass->enumtype) {
2795                                 type = sig->ret->data.klass->enum_basetype->type;
2796                                 goto handle_enum;
2797                         }
2798
2799                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2800                             klass->blittable) {
2801                                 mono_mb_emit_byte (mb, CEE_STLOC_3);
2802                                 break;
2803                         }
2804                         /* load pointer to returned value type */
2805                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2806                         mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
2807                         /* store the address of the source into local variable 0 */
2808                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2809                         /* set dst_ptr */
2810                         mono_mb_emit_ldloc_addr (mb, 3);
2811                         mono_mb_emit_byte (mb, CEE_STLOC_1);
2812
2813                         /* emit valuetype conversion code */
2814                         emit_struct_conv (mb, sig->ret->data.klass, TRUE);
2815                         break;
2816                 case MONO_TYPE_STRING:
2817                         /* maybe we should free strings here */
2818                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2819                         mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2820                         if (spec) {
2821                                 switch (spec->native) {
2822                                 case MONO_NATIVE_LPWSTR:
2823                                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPWSTR_STR);
2824                                         break;
2825                                 default:
2826                                         g_warning ("marshalling conversion not implemented");
2827                                         g_assert_not_reached ();
2828                                 }
2829                         } else {
2830                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
2831                         }
2832                         mono_mb_emit_byte (mb, CEE_STLOC_3);
2833                         break;
2834                 case MONO_TYPE_ARRAY:
2835                 case MONO_TYPE_SZARRAY:
2836                 case MONO_TYPE_CLASS:
2837                 case MONO_TYPE_OBJECT:
2838                         /* fixme: we need conversions here */
2839                         mono_mb_emit_byte (mb, CEE_STLOC_3);
2840                         break;
2841                 case MONO_TYPE_CHAR:
2842                         /* fixme: we need conversions here */
2843                         mono_mb_emit_byte (mb, CEE_STLOC_3);
2844                         break;
2845                 case MONO_TYPE_TYPEDBYREF:
2846                 case MONO_TYPE_FNPTR:
2847                 default:
2848                         g_warning ("return type 0x%02x unknown", sig->ret->type);       
2849                         g_assert_not_reached ();
2850                 }
2851         } else {
2852                 mono_mb_emit_byte (mb, CEE_STLOC_3);
2853         }
2854
2855         /* we need to convert byref arguments back and free string arrays */
2856         for (i = 0; i < sig->param_count; i++) {
2857                 MonoType *t = sig->params [i];
2858                 
2859                 argnum = i + sig->hasthis;
2860
2861                 switch (t->type) {
2862                 case MONO_TYPE_STRING:
2863                         if (t->byref)
2864                                 continue;
2865
2866                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
2867                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2868                         mono_mb_emit_byte (mb, CEE_MONO_FREE);
2869
2870                         break;
2871                 case MONO_TYPE_CLASS:
2872                 case MONO_TYPE_OBJECT:                  
2873                         if (t->byref)
2874                                 continue;
2875      
2876                         if (t->data.klass == mono_defaults.stringbuilder_class) {
2877                                 mono_mb_emit_ldarg (mb, argnum);
2878                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2879                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2880                                 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
2881                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_SB);
2882                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2883                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2884                                 mono_mb_emit_byte (mb, CEE_MONO_FREE);
2885                         }
2886                         break;
2887                 case MONO_TYPE_VALUETYPE:
2888                         if (!t->byref)
2889                                 continue;
2890         
2891                         klass = t->data.klass;
2892                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2893                             klass->blittable || klass->enumtype)
2894                                 break;
2895
2896                         /* dst = argument */
2897                         mono_mb_emit_ldarg (mb, argnum);
2898                         mono_mb_emit_byte (mb, CEE_STLOC_1);
2899
2900                         mono_mb_emit_byte (mb, CEE_LDLOC_1);
2901                         mono_mb_emit_byte (mb, CEE_BRFALSE);
2902                         pos = mb->pos;
2903                         mono_mb_emit_i4 (mb, 0);
2904
2905                         /* src = tmp_locals [i] */
2906                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
2907                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2908
2909                         /* emit valuetype conversion code */
2910                         emit_struct_conv (mb, klass, TRUE);
2911                         
2912                         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2913                         break;
2914                 case MONO_TYPE_SZARRAY:
2915                         if (t->byref)
2916                                 continue;
2917  
2918                         klass = mono_class_from_mono_type (t);
2919                         
2920                         if (klass->element_class == mono_defaults.string_class) {
2921                                 g_assert (tmp_locals [i]);
2922
2923                                 mono_mb_emit_ldarg (mb, argnum);
2924                                 mono_mb_emit_byte (mb, CEE_BRFALSE);
2925                                 pos = mb->pos;
2926                                 mono_mb_emit_i4 (mb, 0);
2927
2928                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2929                                 mono_mb_emit_ldarg (mb, argnum);
2930                                 mono_mb_emit_byte (mb, CEE_LDLEN);                              
2931                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2932                                 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
2933                                 mono_mb_emit_byte (mb, MONO_MARSHAL_FREE_ARRAY);
2934
2935                                 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2936                         }
2937
2938                         break;
2939                 }
2940         }
2941
2942
2943         if (!MONO_TYPE_IS_VOID(sig->ret))
2944                 mono_mb_emit_byte (mb, CEE_LDLOC_3);
2945
2946         mono_mb_emit_byte (mb, CEE_RET);
2947
2948         csig = g_memdup (sig, sigsize);
2949         csig->pinvoke = 0;
2950         res = mono_mb_create_method (mb, csig, csig->param_count + 16);
2951         mono_mb_free (mb);
2952
2953         g_hash_table_insert (cache, method, res);
2954
2955         for (i = sig->param_count; i >= 0; i--)
2956                 g_free (mspecs [i]);
2957         g_free (mspecs);
2958
2959         return res;
2960 }
2961
2962 /*
2963  * generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld)
2964  */
2965 MonoMethod *
2966 mono_marshal_get_struct_to_ptr (MonoClass *klass)
2967 {
2968         MonoMethodBuilder *mb;
2969         static MonoMethod *stoptr = NULL;
2970         MonoMethod *res;
2971
2972         g_assert (klass != NULL);
2973
2974         if (klass->str_to_ptr)
2975                 return klass->str_to_ptr;
2976
2977         if (!stoptr) 
2978                 stoptr = mono_find_method_by_name (mono_defaults.marshal_class, "StructureToPtr", 3);
2979         g_assert (stoptr);
2980
2981         mb = mono_mb_new (klass, stoptr->name, MONO_WRAPPER_UNKNOWN);
2982
2983         if (klass->blittable) {
2984                 mono_mb_emit_byte (mb, CEE_LDARG_1);
2985                 mono_mb_emit_byte (mb, CEE_LDARG_0);
2986                 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
2987                 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
2988                 mono_mb_emit_byte (mb, CEE_PREFIX1);
2989                 mono_mb_emit_byte (mb, CEE_CPBLK);
2990         } else {
2991
2992                 /* allocate local 0 (pointer) src_ptr */
2993                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2994                 /* allocate local 1 (pointer) dst_ptr */
2995                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2996                 /* allocate local 2 (boolean) delete_old */
2997                 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2998                 mono_mb_emit_byte (mb, CEE_LDARG_2);
2999                 mono_mb_emit_byte (mb, CEE_STLOC_2);
3000
3001                 /* initialize src_ptr to point to the start of object data */
3002                 mono_mb_emit_byte (mb, CEE_LDARG_0);
3003                 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3004                 mono_mb_emit_byte (mb, CEE_STLOC_0);
3005
3006                 /* initialize dst_ptr */
3007                 mono_mb_emit_byte (mb, CEE_LDARG_1);
3008                 mono_mb_emit_byte (mb, CEE_STLOC_1);
3009
3010                 emit_struct_conv (mb, klass, FALSE);
3011         }
3012
3013         mono_mb_emit_byte (mb, CEE_RET);
3014
3015         res = mono_mb_create_method (mb, stoptr->signature, 0);
3016         mono_mb_free (mb);
3017
3018         klass->str_to_ptr = res;
3019         return res;
3020 }
3021
3022 /*
3023  * generates IL code for PtrToStructure (IntPtr src, object structure)
3024  */
3025 MonoMethod *
3026 mono_marshal_get_ptr_to_struct (MonoClass *klass)
3027 {
3028         MonoMethodBuilder *mb;
3029         static MonoMethod *ptostr = NULL;
3030         MonoMethod *res;
3031
3032         g_assert (klass != NULL);
3033
3034         if (klass->ptr_to_str)
3035                 return klass->ptr_to_str;
3036
3037         if (!ptostr) 
3038                 ptostr = mono_find_method_by_name (mono_defaults.marshal_class, "PtrToStructure", 2);
3039         g_assert (ptostr);
3040
3041         mb = mono_mb_new (klass, ptostr->name, MONO_WRAPPER_UNKNOWN);
3042
3043         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable) {
3044                 mono_mb_emit_byte (mb, CEE_LDARG_1);
3045                 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3046                 mono_mb_emit_byte (mb, CEE_LDARG_0);
3047                 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
3048                 mono_mb_emit_byte (mb, CEE_PREFIX1);
3049                 mono_mb_emit_byte (mb, CEE_CPBLK);
3050         } else {
3051
3052                 /* allocate local 0 (pointer) src_ptr */
3053                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3054                 /* allocate local 1 (pointer) dst_ptr */
3055                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3056                 
3057                 /* initialize src_ptr to point to the start of object data */
3058                 mono_mb_emit_byte (mb, CEE_LDARG_0);
3059                 mono_mb_emit_byte (mb, CEE_STLOC_0);
3060
3061                 /* initialize dst_ptr */
3062                 mono_mb_emit_byte (mb, CEE_LDARG_1);
3063                 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3064                 mono_mb_emit_byte (mb, CEE_STLOC_1);
3065
3066                 emit_struct_conv (mb, klass, TRUE);
3067         }
3068
3069         mono_mb_emit_byte (mb, CEE_RET);
3070
3071         res = mono_mb_create_method (mb, ptostr->signature, 0);
3072         mono_mb_free (mb);
3073
3074         klass->ptr_to_str = res;
3075         return res;
3076 }
3077
3078 static MonoReflectionType *
3079 type_from_handle (MonoType *handle)
3080 {
3081         MonoDomain *domain = mono_domain_get (); 
3082         MonoClass *klass = mono_class_from_mono_type (handle);
3083
3084         MONO_ARCH_SAVE_REGS;
3085
3086         mono_class_init (klass);
3087         return mono_type_get_object (domain, handle);
3088 }
3089
3090 /*
3091  * generates IL code for the synchronized wrapper: the generated method
3092  * calls METHOD while locking 'this' or the parent type.
3093  */
3094 MonoMethod *
3095 mono_marshal_get_synchronized_wrapper (MonoMethod *method)
3096 {
3097         static MonoMethodSignature *from_handle_sig = NULL;
3098         static MonoMethod *enter_method, *exit_method;
3099         MonoMethodSignature *sig;
3100         MonoExceptionClause *clause;
3101         MonoMethodHeader *header;
3102         MonoMethodBuilder *mb;
3103         MonoMethod *res;
3104         GHashTable *cache;
3105         int i, pos, this_local, ret_local;
3106
3107         g_assert (method);
3108
3109         if (method->wrapper_type == MONO_WRAPPER_SYNCHRONIZED)
3110                 return method;
3111
3112         cache = method->klass->image->synchronized_cache;
3113         if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
3114                 return res;
3115
3116         sig = method->signature;
3117
3118         mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_SYNCHRONIZED);
3119
3120         /* result */
3121         if (!MONO_TYPE_IS_VOID (sig->ret))
3122                 ret_local = mono_mb_add_local (mb, sig->ret);
3123
3124         /* this */
3125         this_local = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
3126
3127         clause = g_new0 (MonoExceptionClause, 1);
3128         clause->flags = MONO_EXCEPTION_CLAUSE_FINALLY;
3129
3130         if (!enter_method) {
3131                 MonoMethodDesc *desc;
3132
3133                 desc = mono_method_desc_new ("Monitor:Enter", FALSE);
3134                 enter_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
3135                 g_assert (enter_method);
3136                 mono_method_desc_free (desc);
3137                 desc = mono_method_desc_new ("Monitor:Exit", FALSE);
3138                 exit_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
3139                 g_assert (exit_method);
3140                 mono_method_desc_free (desc);
3141
3142                 /*
3143                  * GetTypeFromHandle isn't called as a managed method because it has
3144                  * a funky calling sequence, e.g. ldtoken+GetTypeFromHandle gets
3145                  * transformed into something else by the JIT.
3146                  */
3147                 from_handle_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
3148                 from_handle_sig->params [0] = &mono_defaults.object_class->byval_arg;
3149                 from_handle_sig->ret = &mono_defaults.object_class->byval_arg;
3150         }
3151
3152         /* Push this or the type object */
3153         if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3154                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3155                 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
3156                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, &method->klass->byval_arg));
3157                 mono_mb_emit_native_call (mb, from_handle_sig, type_from_handle);
3158         }
3159         else
3160                 mono_mb_emit_ldarg (mb, 0);
3161         mono_mb_emit_stloc (mb, this_local);
3162
3163         /* Call Monitor::Enter() */
3164         mono_mb_emit_ldloc (mb, this_local);
3165         mono_mb_emit_managed_call (mb, enter_method, NULL);
3166
3167         clause->try_offset = mb->pos;
3168
3169         /* Call the method */
3170         if (sig->hasthis)
3171                 mono_mb_emit_ldarg (mb, 0);
3172         for (i = 0; i < sig->param_count; i++)
3173                 mono_mb_emit_ldarg (mb, i + (sig->hasthis == TRUE));
3174         mono_mb_emit_managed_call (mb, method, method->signature);
3175         if (!MONO_TYPE_IS_VOID (sig->ret))
3176                 mono_mb_emit_stloc (mb, ret_local);
3177
3178         mono_mb_emit_byte (mb, CEE_LEAVE);
3179         pos = mb->pos;
3180         mono_mb_emit_i4 (mb, 0);
3181
3182         clause->try_len = mb->pos - clause->try_offset;
3183         clause->handler_offset = mb->pos;
3184
3185         /* Call Monitor::Exit() */
3186         mono_mb_emit_ldloc (mb, this_local);
3187 //      mono_mb_emit_native_call (mb, exit_sig, mono_monitor_exit);
3188         mono_mb_emit_managed_call (mb, exit_method, NULL);
3189         mono_mb_emit_byte (mb, CEE_ENDFINALLY);
3190
3191         clause->handler_len = mb->pos - clause->handler_offset;
3192
3193         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3194         if (!MONO_TYPE_IS_VOID (sig->ret))
3195                 mono_mb_emit_ldloc (mb, ret_local);
3196         mono_mb_emit_byte (mb, CEE_RET);
3197
3198         res = mono_mb_create_method (mb, sig, sig->param_count + 16);
3199         mono_mb_free (mb);
3200
3201         header = ((MonoMethodNormal *)res)->header;
3202         header->num_clauses = 1;
3203         header->clauses = clause;
3204
3205         g_hash_table_insert (cache, method, res);
3206
3207         return res;     
3208 }
3209
3210 /* FIXME: on win32 we should probably use GlobalAlloc(). */
3211 void*
3212 mono_marshal_alloc (gpointer size) 
3213 {
3214         MONO_ARCH_SAVE_REGS;
3215
3216         return g_try_malloc ((gulong)size);
3217 }
3218
3219 void
3220 mono_marshal_free (gpointer ptr) 
3221 {
3222         MONO_ARCH_SAVE_REGS;
3223
3224         g_free (ptr);
3225 }
3226
3227 void
3228 mono_marshal_free_array (gpointer *ptr, int size) 
3229 {
3230         int i;
3231
3232         if (!ptr)
3233                 return;
3234
3235         for (i = 0; i < size; i++)
3236                 if (ptr [i])
3237                         g_free (ptr [i]);
3238 }
3239
3240 void *
3241 mono_marshal_realloc (gpointer ptr, gpointer size) 
3242 {
3243         MONO_ARCH_SAVE_REGS;
3244
3245         return g_try_realloc (ptr, (gulong)size);
3246 }
3247
3248 void *
3249 mono_marshal_string_array (MonoArray *array)
3250 {
3251         char **result;
3252         int i, len;
3253
3254         if (!array)
3255                 return NULL;
3256
3257         len = mono_array_length (array);
3258
3259         result = g_malloc (sizeof (char *) * (len + 1));
3260         for (i = 0; i < len; ++i) {
3261                 MonoString *s = (MonoString *)mono_array_get (array, gpointer, i);
3262                 result [i] = s ? mono_string_to_utf8 (s): NULL;
3263         }
3264         /* null terminate the array */
3265         result [i] = NULL;
3266
3267         return result;
3268 }
3269
3270 void
3271 ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArray *src, gint32 start_index,
3272                                                                     gpointer dest, gint32 length)
3273 {
3274         int element_size;
3275         void *source_addr;
3276
3277         MONO_ARCH_SAVE_REGS;
3278
3279         MONO_CHECK_ARG_NULL (src);
3280         MONO_CHECK_ARG_NULL (dest);
3281
3282         g_assert (src->obj.vtable->klass->rank == 1);
3283         g_assert (start_index >= 0);
3284         g_assert (length >= 0);
3285         g_assert (start_index + length <= mono_array_length (src));
3286
3287         element_size = mono_array_element_size (src->obj.vtable->klass);
3288           
3289         source_addr = mono_array_addr_with_size (src, element_size, start_index);
3290
3291         memcpy (dest, source_addr, length * element_size);
3292 }
3293
3294 void
3295 ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer src, gint32 start_index,
3296                                                                       MonoArray *dest, gint32 length)
3297 {
3298         int element_size;
3299         void *dest_addr;
3300
3301         MONO_ARCH_SAVE_REGS;
3302
3303         MONO_CHECK_ARG_NULL (src);
3304         MONO_CHECK_ARG_NULL (dest);
3305
3306         g_assert (dest->obj.vtable->klass->rank == 1);
3307         g_assert (start_index >= 0);
3308         g_assert (length >= 0);
3309         g_assert (start_index + length <= mono_array_length (dest));
3310
3311         element_size = mono_array_element_size (dest->obj.vtable->klass);
3312           
3313         dest_addr = mono_array_addr_with_size (dest, element_size, start_index);
3314
3315         memcpy (dest_addr, src, length * element_size);
3316 }
3317
3318 gpointer
3319 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr, gint32 offset)
3320 {
3321         char *p = ptr;
3322
3323         MONO_ARCH_SAVE_REGS;
3324
3325         return *(gpointer*)(p + offset);
3326 }
3327
3328 unsigned char
3329 ves_icall_System_Runtime_InteropServices_Marshal_ReadByte (gpointer ptr, gint32 offset)
3330 {
3331         char *p = ptr;
3332
3333         MONO_ARCH_SAVE_REGS;
3334
3335         return *(unsigned char*)(p + offset);
3336 }
3337
3338 gint16
3339 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt16 (gpointer ptr, gint32 offset)
3340 {
3341         char *p = ptr;
3342
3343         MONO_ARCH_SAVE_REGS;
3344
3345         return *(gint16*)(p + offset);
3346 }
3347
3348 gint32
3349 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt32 (gpointer ptr, gint32 offset)
3350 {
3351         char *p = ptr;
3352
3353         MONO_ARCH_SAVE_REGS;
3354
3355         return *(gint32*)(p + offset);
3356 }
3357
3358 gint64
3359 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt64 (gpointer ptr, gint32 offset)
3360 {
3361         char *p = ptr;
3362
3363         MONO_ARCH_SAVE_REGS;
3364
3365         return *(gint64*)(p + offset);
3366 }
3367
3368 void
3369 ves_icall_System_Runtime_InteropServices_Marshal_WriteByte (gpointer ptr, gint32 offset, unsigned char val)
3370 {
3371         char *p = ptr;
3372
3373         MONO_ARCH_SAVE_REGS;
3374
3375         *(unsigned char*)(p + offset) = val;
3376 }
3377
3378 void
3379 ves_icall_System_Runtime_InteropServices_Marshal_WriteIntPtr (gpointer ptr, gint32 offset, gpointer val)
3380 {
3381         char *p = ptr;
3382
3383         MONO_ARCH_SAVE_REGS;
3384
3385         *(gpointer*)(p + offset) = val;
3386 }
3387
3388 void
3389 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt16 (gpointer ptr, gint32 offset, gint16 val)
3390 {
3391         char *p = ptr;
3392
3393         MONO_ARCH_SAVE_REGS;
3394
3395         *(gint16*)(p + offset) = val;
3396 }
3397
3398 void
3399 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt32 (gpointer ptr, gint32 offset, gint32 val)
3400 {
3401         char *p = ptr;
3402
3403         MONO_ARCH_SAVE_REGS;
3404
3405         *(gint32*)(p + offset) = val;
3406 }
3407
3408 void
3409 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt64 (gpointer ptr, gint32 offset, gint64 val)
3410 {
3411         char *p = ptr;
3412
3413         MONO_ARCH_SAVE_REGS;
3414
3415         *(gint64*)(p + offset) = val;
3416 }
3417
3418 MonoString *
3419 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (char *ptr)
3420 {
3421         MONO_ARCH_SAVE_REGS;
3422
3423         return mono_string_new (mono_domain_get (), ptr);
3424 }
3425
3426 MonoString *
3427 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len (char *ptr, gint32 len)
3428 {
3429         MONO_ARCH_SAVE_REGS;
3430
3431         return mono_string_new_len (mono_domain_get (), ptr, len);
3432 }
3433
3434 MonoString *
3435 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni (guint16 *ptr)
3436 {
3437         MonoDomain *domain = mono_domain_get (); 
3438         int len = 0;
3439         guint16 *t = ptr;
3440
3441         MONO_ARCH_SAVE_REGS;
3442
3443         while (*t++)
3444                 len++;
3445
3446         return mono_string_new_utf16 (domain, ptr, len);
3447 }
3448
3449 MonoString *
3450 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len (guint16 *ptr, gint32 len)
3451 {
3452         MonoDomain *domain = mono_domain_get (); 
3453
3454         MONO_ARCH_SAVE_REGS;
3455
3456         return mono_string_new_utf16 (domain, ptr, len);
3457 }
3458
3459 MonoString *
3460 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR (gpointer ptr)
3461 {
3462         MONO_ARCH_SAVE_REGS;
3463
3464         g_warning ("PtrToStringBSTR not implemented");
3465         g_assert_not_reached ();
3466
3467         return NULL;
3468 }
3469
3470 guint32 
3471 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
3472 {
3473         MONO_ARCH_SAVE_REGS;
3474
3475         return (GetLastError ());
3476 }
3477
3478 guint32 
3479 ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype)
3480 {
3481         MonoClass *klass;
3482
3483         MONO_ARCH_SAVE_REGS;
3484
3485         MONO_CHECK_ARG_NULL (rtype);
3486
3487         klass = mono_class_from_mono_type (rtype->type);
3488
3489         return mono_class_native_size (klass, NULL);
3490 }
3491
3492 void
3493 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old)
3494 {
3495         MonoMethod *method;
3496         gpointer pa [3];
3497
3498         MONO_ARCH_SAVE_REGS;
3499
3500         MONO_CHECK_ARG_NULL (obj);
3501         MONO_CHECK_ARG_NULL (dst);
3502
3503         method = mono_marshal_get_struct_to_ptr (obj->vtable->klass);
3504
3505         pa [0] = obj;
3506         pa [1] = &dst;
3507         pa [2] = &delete_old;
3508
3509         mono_runtime_invoke (method, NULL, pa, NULL);
3510 }
3511
3512 void
3513 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, MonoObject *dst)
3514 {
3515         MonoMethod *method;
3516         gpointer pa [2];
3517
3518         MONO_ARCH_SAVE_REGS;
3519
3520         MONO_CHECK_ARG_NULL (src);
3521         MONO_CHECK_ARG_NULL (dst);
3522
3523         method = mono_marshal_get_ptr_to_struct (dst->vtable->klass);
3524
3525         pa [0] = &src;
3526         pa [1] = dst;
3527
3528         mono_runtime_invoke (method, NULL, pa, NULL);
3529 }
3530
3531 MonoObject *
3532 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer src, MonoReflectionType *type)
3533 {
3534         MonoDomain *domain = mono_domain_get (); 
3535         MonoObject *res;
3536
3537         MONO_ARCH_SAVE_REGS;
3538
3539         MONO_CHECK_ARG_NULL (src);
3540         MONO_CHECK_ARG_NULL (type);
3541
3542         res = mono_object_new (domain, mono_class_from_mono_type (type->type));
3543
3544         ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (src, res);
3545
3546         return res;
3547 }
3548
3549 int
3550 ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *type, MonoString *field_name)
3551 {
3552         MonoMarshalType *info;
3553         MonoClass *klass;
3554         char *fname;
3555         int i, match_index = -1;
3556         
3557         MONO_ARCH_SAVE_REGS;
3558
3559         MONO_CHECK_ARG_NULL (type);
3560         MONO_CHECK_ARG_NULL (field_name);
3561
3562         fname = mono_string_to_utf8 (field_name);
3563         klass = mono_class_from_mono_type (type->type);
3564
3565         while(klass && match_index == -1) {
3566                 for (i = 0; i < klass->field.count; ++i) {
3567                         if (*fname == *klass->fields [i].name && strcmp (fname, klass->fields [i].name) == 0) {
3568                                 match_index = i;
3569                                 break;
3570                         }
3571                 }
3572
3573                 if(match_index == -1)
3574                         klass = klass->parent;
3575         }
3576
3577         g_free (fname);
3578
3579         if(match_index == -1) {
3580                MonoException* exc;
3581                gchar *tmp;
3582
3583                /* Get back original class instance */
3584                klass = mono_class_from_mono_type (type->type);
3585
3586                tmp = g_strdup_printf ("Field passed in is not a marshaled member of the type %s", klass->name);
3587                exc = mono_get_exception_argument ("fieldName", tmp);
3588                g_free (tmp);
3589  
3590                mono_raise_exception ((MonoException*)exc);
3591        }
3592
3593        info = mono_marshal_load_type_info (klass);     
3594        return info->fields [match_index].offset;
3595 }
3596
3597 gpointer
3598 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString *string)
3599 {
3600         MONO_ARCH_SAVE_REGS;
3601
3602         return mono_string_to_utf8 (string);
3603 }
3604
3605 gpointer
3606 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni (MonoString *string)
3607 {
3608         MONO_ARCH_SAVE_REGS;
3609
3610         return g_memdup (mono_string_chars (string), mono_string_length (string)*2);
3611 }
3612
3613 static void
3614 mono_struct_delete_old (MonoClass *klass, char *ptr)
3615 {
3616         MonoMarshalType *info;
3617         int i;
3618
3619         info = mono_marshal_load_type_info (klass);
3620
3621         for (i = 0; i < info->num_fields; i++) {
3622                 MonoMarshalNative ntype;
3623                 MonoMarshalConv conv;
3624                 MonoType *ftype = info->fields [i].field->type;
3625                 char *cpos;
3626
3627                 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
3628                         continue;
3629
3630                 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, 
3631                                                 klass->unicode, &conv);
3632                         
3633                 cpos = ptr + info->fields [i].offset;
3634
3635                 switch (conv) {
3636                 case MONO_MARSHAL_CONV_NONE:
3637                         if (MONO_TYPE_ISSTRUCT (ftype)) {
3638                                 mono_struct_delete_old (ftype->data.klass, cpos);
3639                                 continue;
3640                         }
3641                         break;
3642                 case MONO_MARSHAL_CONV_STR_LPWSTR:
3643                 case MONO_MARSHAL_CONV_STR_LPSTR:
3644                 case MONO_MARSHAL_CONV_STR_LPTSTR:
3645                 case MONO_MARSHAL_CONV_STR_BSTR:
3646                 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
3647                 case MONO_MARSHAL_CONV_STR_TBSTR:
3648                         g_free (*(gpointer *)cpos);
3649                         break;
3650                 default:
3651                         continue;
3652                 }
3653         }
3654 }
3655
3656 void
3657 ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure (gpointer src, MonoReflectionType *type)
3658 {
3659         MonoClass *klass;
3660
3661         MONO_ARCH_SAVE_REGS;
3662
3663         MONO_CHECK_ARG_NULL (src);
3664         MONO_CHECK_ARG_NULL (type);
3665
3666         klass = mono_class_from_mono_type (type->type);
3667
3668         mono_struct_delete_old (klass, (char *)src);
3669 }
3670