* icall.c: Added ves_icall_type_IsInstanceOf internal call.
[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 #include <errno.h>
23
24 //#define DEBUG_RUNTIME_CODE
25
26 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
27         a = i,
28
29 enum {
30 #include "mono/cil/opcode.def"
31         LAST = 0xff
32 };
33 #undef OPDEF
34
35 struct _MonoMethodBuilder {
36         MonoMethod *method;
37         GList *locals_list;
38         int locals;
39         guint32 code_size, pos;
40         unsigned char *code;
41 };
42
43 static void
44 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object);
45
46 static MonoMethod *
47 mono_find_method_by_name (MonoClass *klass, const char *name, int param_count)
48 {
49         MonoMethod *res = NULL;
50         int i;
51
52         for (i = 0; i < klass->method.count; ++i) {
53                 if (klass->methods [i]->name[0] == name [0] && 
54                     !strcmp (name, klass->methods [i]->name) &&
55                     klass->methods [i]->signature->param_count == param_count) {
56                         res = klass->methods [i];
57                         break;
58                 }
59         }
60         return res;
61 }
62
63 #ifdef DEBUG_RUNTIME_CODE
64 static char*
65 indenter (MonoDisHelper *dh, MonoMethod *method, guint32 ip_offset)
66 {
67         return g_strdup (" ");
68 }
69
70 static MonoDisHelper marshal_dh = {
71         "\n",
72         "IL_%04x: ",
73         "IL_%04x",
74         indenter, 
75         NULL,
76         NULL
77 };
78 #endif 
79
80 /* This mutex protects the various marshalling related caches in MonoImage */
81 static CRITICAL_SECTION marshal_mutex;
82
83 /* Maps wrapper methods to the methods they wrap */
84 static MonoGHashTable *wrapper_hash;
85
86 static guint32 last_error_tls_id;
87
88 void
89 mono_marshal_init (void)
90 {
91         static gboolean module_initialized = FALSE;
92
93         if (!module_initialized) {
94                 module_initialized = TRUE;
95                 InitializeCriticalSection (&marshal_mutex);
96                 wrapper_hash = mono_g_hash_table_new (NULL, NULL);
97                 last_error_tls_id = TlsAlloc ();
98         }
99 }
100
101 gpointer
102 mono_delegate_to_ftnptr (MonoDelegate *delegate)
103 {
104         MonoMethod *method, *wrapper, *invoke;
105         MonoMarshalSpec **mspecs;
106         MonoClass *klass;
107         int i;
108
109         if (!delegate)
110                 return NULL;
111
112         if (delegate->delegate_trampoline)
113                 return delegate->delegate_trampoline;
114
115         klass = ((MonoObject *)delegate)->vtable->klass;
116         g_assert (klass->delegate);
117
118
119         method = delegate->method_info->method;
120         invoke = mono_find_method_by_name (klass, "Invoke", method->signature->param_count);
121
122         mspecs = g_new (MonoMarshalSpec*, invoke->signature->param_count + 1);
123         mono_method_get_marshal_info (invoke, mspecs);
124
125         wrapper = mono_marshal_get_managed_wrapper (method, delegate->target, mspecs);
126
127         for (i = invoke->signature->param_count; i >= 0; i--)
128                 g_free (mspecs [i]);
129         g_free (mspecs);
130
131         delegate->delegate_trampoline =  mono_compile_method (wrapper);
132
133         return delegate->delegate_trampoline;
134 }
135
136 gpointer
137 mono_array_to_savearray (MonoArray *array)
138 {
139         if (!array)
140                 return NULL;
141
142         g_assert_not_reached ();
143         return NULL;
144 }
145
146 gpointer
147 mono_array_to_lparray (MonoArray *array)
148 {
149         if (!array)
150                 return NULL;
151
152         /* fixme: maybe we need to make a copy */
153         return array->vector;
154 }
155
156 void
157 mono_string_utf8_to_builder (MonoStringBuilder *sb, char *text)
158 {
159         GError *error = NULL;
160         guint16 *ut;
161         glong items_written;
162         int l;
163
164         if (!sb || !text)
165                 return;
166
167         l = strlen (text);
168
169         ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
170         
171         if (items_written > mono_stringbuilder_capacity (sb))
172                 items_written = mono_stringbuilder_capacity (sb);
173         
174         if (!error) {
175                 memcpy (mono_string_chars (sb->str), ut, items_written * 2);
176                 sb->length = items_written;
177         } else 
178                 g_error_free (error);
179
180         g_free (ut);
181 }
182
183 gpointer
184 mono_string_builder_to_utf8 (MonoStringBuilder *sb)
185 {
186         GError *error = NULL;
187         glong *res;
188
189         if (!sb)
190                 return NULL;
191
192         res = g_malloc0 (mono_stringbuilder_capacity (sb) + 1);
193
194         g_utf16_to_utf8 (mono_string_chars (sb->str), sb->length, NULL, res, &error);
195         if (error) {
196                 g_error_free (error);
197                 mono_raise_exception (mono_get_exception_execution_engine ("Failed to convert StringBuilder from utf16 to utf8"));
198         }
199
200         return res;
201 }
202
203 gpointer
204 mono_string_to_ansibstr (MonoString *string_obj)
205 {
206         g_error ("implement me");
207         return NULL;
208 }
209
210 gpointer
211 mono_string_to_bstr (MonoString *string_obj)
212 {
213         g_error ("implement me");
214         return NULL;
215 }
216
217 void
218 mono_string_to_byvalstr (gpointer dst, MonoString *src, int size)
219 {
220         char *s;
221         int len;
222
223         g_assert (dst != NULL);
224         g_assert (size > 0);
225
226         memset (dst, 0, size);
227         
228         if (!src)
229                 return;
230
231         s = mono_string_to_utf8 (src);
232         len = MIN (size, strlen (s));
233         memcpy (dst, s, len);
234         g_free (s);
235
236         *((char *)dst + size - 1) = 0;
237 }
238
239 void
240 mono_string_to_byvalwstr (gpointer dst, MonoString *src, int size)
241 {
242         int len;
243
244         g_assert (dst != NULL);
245         g_assert (size > 1);
246
247         if (!src) {
248                 memset (dst, 0, size);
249                 return;
250         }
251
252         len = MIN (size, (mono_string_length (src) * 2));
253         memcpy (dst, mono_string_chars (src), len);
254
255         *((char *)dst + size - 1) = 0;
256         *((char *)dst + size - 2) = 0;
257 }
258
259 void
260 mono_mb_free (MonoMethodBuilder *mb)
261 {
262         g_list_free (mb->locals_list);
263         g_free (mb);
264 }
265
266 MonoMethodBuilder *
267 mono_mb_new (MonoClass *klass, const char *name, MonoWrapperType type)
268 {
269         MonoMethodBuilder *mb;
270         MonoMethod *m;
271
272         g_assert (klass != NULL);
273         g_assert (name != NULL);
274
275         mb = g_new0 (MonoMethodBuilder, 1);
276
277         mb->method = m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
278
279         m->klass = klass;
280         m->name = g_strdup (name);
281         m->inline_info = 1;
282         m->inline_count = -1;
283         m->wrapper_type = type;
284
285         mb->code_size = 256;
286         mb->code = g_malloc (mb->code_size);
287         
288         return mb;
289 }
290
291 int
292 mono_mb_add_local (MonoMethodBuilder *mb, MonoType *type)
293 {
294         int res = mb->locals;
295
296         g_assert (mb != NULL);
297         g_assert (type != NULL);
298
299         mb->locals_list = g_list_append (mb->locals_list, type);
300         mb->locals++;
301
302         return res;
303 }
304
305 MonoMethod *
306 mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack)
307 {
308         MonoMethodHeader *header;
309         GList *l;
310         int i;
311
312         g_assert (mb != NULL);
313
314         ((MonoMethodNormal *)mb->method)->header = header = (MonoMethodHeader *) 
315                 g_malloc0 (sizeof (MonoMethodHeader) + mb->locals * sizeof (MonoType *));
316
317         if (max_stack < 8)
318                 max_stack = 8;
319
320         header->max_stack = max_stack;
321
322         for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
323                 header->locals [i] = (MonoType *)l->data;
324         }
325
326         mb->method->signature = signature;
327         header->code = mb->code;
328         header->code_size = mb->pos;
329         header->num_locals = mb->locals;
330
331 #ifdef DEBUG_RUNTIME_CODE
332         printf ("RUNTIME CODE FOR %s\n", mono_method_full_name (mb->method, TRUE));
333         printf ("%s\n", mono_disasm_code (&marshal_dh, mb->method, mb->code, mb->code + mb->pos));
334 #endif
335
336         return mb->method;
337 }
338
339 guint32
340 mono_mb_add_data (MonoMethodBuilder *mb, gpointer data)
341 {
342         MonoMethodWrapper *mw;
343
344         g_assert (mb != NULL);
345
346         mw = (MonoMethodWrapper *)mb->method;
347
348         mw->data = g_list_append (mw->data, data);
349
350         return g_list_length (mw->data);
351 }
352
353 void
354 mono_mb_patch_addr (MonoMethodBuilder *mb, int pos, int value)
355 {
356         mb->code [pos] = value & 0xff;
357         mb->code [pos + 1] = (value >> 8) & 0xff;
358         mb->code [pos + 2] = (value >> 16) & 0xff;
359         mb->code [pos + 3] = (value >> 24) & 0xff;
360 }
361
362 void
363 mono_mb_patch_addr_s (MonoMethodBuilder *mb, int pos, gint8 value)
364 {
365         *((gint8 *)(&mb->code [pos])) = value;
366 }
367
368 void
369 mono_mb_emit_byte (MonoMethodBuilder *mb, guint8 op)
370 {
371         if (mb->pos >= mb->code_size) {
372                 mb->code_size += 64;
373                 mb->code = g_realloc (mb->code, mb->code_size);
374         }
375
376         mb->code [mb->pos++] = op;
377 }
378
379 void
380 mono_mb_emit_ldflda (MonoMethodBuilder *mb, gint32 offset)
381 {
382         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
383         mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
384
385         if (offset) {
386                 mono_mb_emit_icon (mb, offset);
387                 mono_mb_emit_byte (mb, CEE_ADD);
388         }
389 }
390
391 static int
392 mono_mb_emit_proxy_check (MonoMethodBuilder *mb, int branch_code)
393 {
394         int pos;
395         mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoObject, vtable));
396         mono_mb_emit_byte (mb, CEE_LDIND_I);
397         mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoVTable, klass));
398         mono_mb_emit_byte (mb, CEE_ADD);
399         mono_mb_emit_byte (mb, CEE_LDIND_I);
400         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
401         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
402         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_defaults.transparent_proxy_class));
403         mono_mb_emit_byte (mb, branch_code);
404         pos = mb->pos;
405         mono_mb_emit_i4 (mb, 0);
406         return pos;
407 }
408
409 void
410 mono_mb_emit_i4 (MonoMethodBuilder *mb, gint32 data)
411 {
412         if ((mb->pos + 4) >= mb->code_size) {
413                 mb->code_size += 64;
414                 mb->code = g_realloc (mb->code, mb->code_size);
415         }
416
417         mono_mb_patch_addr (mb, mb->pos, data);
418         mb->pos += 4;
419 }
420
421 void
422 mono_mb_emit_i2 (MonoMethodBuilder *mb, gint16 data)
423 {
424         if ((mb->pos + 2) >= mb->code_size) {
425                 mb->code_size += 64;
426                 mb->code = g_realloc (mb->code, mb->code_size);
427         }
428
429         mb->code [mb->pos] = data & 0xff;
430         mb->code [mb->pos + 1] = (data >> 8) & 0xff;
431         mb->pos += 2;
432 }
433
434 void
435 mono_mb_emit_ldstr (MonoMethodBuilder *mb, char *str)
436 {
437         mono_mb_emit_byte (mb, CEE_LDSTR);
438         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, str));
439 }
440
441
442 void
443 mono_mb_emit_ldarg (MonoMethodBuilder *mb, guint argnum)
444 {
445         if (argnum < 4) {
446                 mono_mb_emit_byte (mb, CEE_LDARG_0 + argnum);
447         } else if (argnum < 256) {
448                 mono_mb_emit_byte (mb, CEE_LDARG_S);
449                 mono_mb_emit_byte (mb, argnum);
450         } else {
451                 mono_mb_emit_byte (mb, CEE_PREFIX1);
452                 mono_mb_emit_byte (mb, CEE_LDARG);
453                 mono_mb_emit_i2 (mb, argnum);
454         }
455 }
456
457 void
458 mono_mb_emit_ldarg_addr (MonoMethodBuilder *mb, guint argnum)
459 {
460         if (argnum < 256) {
461                 mono_mb_emit_byte (mb, CEE_LDARGA_S);
462                 mono_mb_emit_byte (mb, argnum);
463         } else {
464                 mono_mb_emit_byte (mb, CEE_PREFIX1);
465                 mono_mb_emit_byte (mb, CEE_LDARGA);
466                 mono_mb_emit_i2 (mb, argnum);
467         }
468 }
469
470 void
471 mono_mb_emit_ldloc_addr (MonoMethodBuilder *mb, guint locnum)
472 {
473         if (locnum < 256) {
474                 mono_mb_emit_byte (mb, CEE_LDLOCA_S);
475                 mono_mb_emit_byte (mb, locnum);
476         } else {
477                 mono_mb_emit_byte (mb, CEE_PREFIX1);
478                 mono_mb_emit_byte (mb, CEE_LDLOCA);
479                 mono_mb_emit_i2 (mb, locnum);
480         }
481 }
482
483 void
484 mono_mb_emit_ldloc (MonoMethodBuilder *mb, guint num)
485 {
486         if (num < 4) {
487                 mono_mb_emit_byte (mb, CEE_LDLOC_0 + num);
488         } else if (num < 256) {
489                 mono_mb_emit_byte (mb, CEE_LDLOC_S);
490                 mono_mb_emit_byte (mb, num);
491         } else {
492                 mono_mb_emit_byte (mb, CEE_PREFIX1);
493                 mono_mb_emit_byte (mb, CEE_LDLOC);
494                 mono_mb_emit_i2 (mb, num);
495         }
496 }
497
498 void
499 mono_mb_emit_stloc (MonoMethodBuilder *mb, guint num)
500 {
501         if (num < 4) {
502                 mono_mb_emit_byte (mb, CEE_STLOC_0 + num);
503         } else if (num < 256) {
504                 mono_mb_emit_byte (mb, CEE_STLOC_S);
505                 mono_mb_emit_byte (mb, num);
506         } else {
507                 mono_mb_emit_byte (mb, CEE_PREFIX1);
508                 mono_mb_emit_byte (mb, CEE_STLOC);
509                 mono_mb_emit_i2 (mb, num);
510         }
511 }
512
513 void
514 mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value)
515 {
516         if (value >= -1 && value < 8) {
517                 mono_mb_emit_byte (mb, CEE_LDC_I4_0 + value);
518         } else if (value >= -128 && value <= 127) {
519                 mono_mb_emit_byte (mb, CEE_LDC_I4_S);
520                 mono_mb_emit_byte (mb, value);
521         } else {
522                 mono_mb_emit_byte (mb, CEE_LDC_I4);
523                 mono_mb_emit_i4 (mb, value);
524         }
525 }
526
527 guint32
528 mono_mb_emit_branch (MonoMethodBuilder *mb, guint8 op)
529 {
530         guint32 res;
531         mono_mb_emit_byte (mb, op);
532         res = mb->pos;
533         mono_mb_emit_i4 (mb, 0);
534         return res;
535 }
536
537 void
538 mono_mb_emit_managed_call (MonoMethodBuilder *mb, MonoMethod *method, MonoMethodSignature *opt_sig)
539 {
540         if (!opt_sig)
541                 opt_sig = method->signature;
542         mono_mb_emit_byte (mb, CEE_PREFIX1);
543         mono_mb_emit_byte (mb, CEE_LDFTN);
544         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
545         mono_mb_emit_byte (mb, CEE_CALLI);
546         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, opt_sig));
547 }
548
549 void
550 mono_mb_emit_native_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, gpointer func)
551 {
552         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
553         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
554         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, func));
555         mono_mb_emit_byte (mb, CEE_CALLI);
556         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
557 }
558
559 void
560 mono_mb_emit_exception (MonoMethodBuilder *mb, const char *exc_name, const char *msg)
561 {
562         /* fixme: we need a better way to throw exception,
563          * supporting several exception types and messages */
564         MonoMethod *ctor = NULL;
565
566         MonoClass *mme = mono_class_from_name (mono_defaults.corlib, "System", exc_name);
567         int i;
568         mono_class_init (mme);
569         for (i = 0; i < mme->method.count; ++i) {
570                 if (strcmp (mme->methods [i]->name, ".ctor") == 0 && mme->methods [i]->signature->param_count == 0) {
571                         ctor = mme->methods [i];
572                         break;
573                 }
574         }
575         g_assert (ctor);
576         mono_mb_emit_byte (mb, CEE_NEWOBJ);
577         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, ctor));
578         if (msg != NULL) {
579                 mono_mb_emit_byte (mb, CEE_DUP);
580                 mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoException, message));
581                 mono_mb_emit_ldstr (mb, msg);
582                 mono_mb_emit_byte (mb, CEE_STIND_I);
583         }
584         mono_mb_emit_byte (mb, CEE_THROW);
585 }
586
587 void
588 mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint16 local, gint32 incr)
589 {
590         mono_mb_emit_ldloc (mb, local); 
591         mono_mb_emit_icon (mb, incr);
592         mono_mb_emit_byte (mb, CEE_ADD);
593         mono_mb_emit_stloc (mb, local); 
594 }
595
596 static void
597 emit_ptr_to_str_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, 
598                       int usize, int msize, MonoMarshalSpec *mspec)
599 {
600         switch (conv) {
601         case MONO_MARSHAL_CONV_BOOL_I4:
602                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
603                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
604                 mono_mb_emit_byte (mb, CEE_LDIND_I4);
605                 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
606                 mono_mb_emit_byte (mb, 3);
607                 mono_mb_emit_byte (mb, CEE_LDC_I4_1);
608                 mono_mb_emit_byte (mb, CEE_BR_S);
609                 mono_mb_emit_byte (mb, 1);
610                 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
611                 mono_mb_emit_byte (mb, CEE_STIND_I1);
612                 break;
613         case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
614                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
615                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
616                 mono_mb_emit_byte (mb, CEE_LDIND_I2);
617                 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
618                 mono_mb_emit_byte (mb, 3);
619                 mono_mb_emit_byte (mb, CEE_LDC_I4_1);
620                 mono_mb_emit_byte (mb, CEE_BR_S);
621                 mono_mb_emit_byte (mb, 1);
622                 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
623                 mono_mb_emit_byte (mb, CEE_STIND_I1);
624                 break;
625         case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
626                 MonoClass *eclass;
627                 int esize;
628
629                 if (type->type == MONO_TYPE_SZARRAY) {
630                         eclass = type->data.klass;
631                 } else {
632                         g_assert_not_reached ();
633                 }
634
635                 if (eclass->valuetype)
636                         esize = mono_class_instance_size (eclass) - sizeof (MonoObject);
637                 else
638                         esize = sizeof (gpointer);
639
640                 /* create a new array */
641                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
642                 mono_mb_emit_icon (mb, mspec->data.array_data.num_elem);
643                 mono_mb_emit_byte (mb, CEE_NEWARR);     
644                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eclass));
645                 mono_mb_emit_byte (mb, CEE_STIND_I);
646
647                 /* copy the elements */
648                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
649                 mono_mb_emit_byte (mb, CEE_LDIND_I);
650                 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
651                 mono_mb_emit_byte (mb, CEE_ADD);
652                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
653                 mono_mb_emit_icon (mb, mspec->data.array_data.num_elem * esize);
654                 mono_mb_emit_byte (mb, CEE_PREFIX1);
655                 mono_mb_emit_byte (mb, CEE_CPBLK);                      
656
657                 break;
658         }
659         case MONO_MARSHAL_CONV_STR_BYVALSTR: 
660                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
661                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
662                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
663                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
664                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
665                 mono_mb_emit_byte (mb, CEE_STIND_I);            
666                 break;
667         case MONO_MARSHAL_CONV_STR_LPTSTR:
668         case MONO_MARSHAL_CONV_STR_LPSTR:
669                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
670                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
671                 mono_mb_emit_byte (mb, CEE_LDIND_I);
672                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
673                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
674                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
675                 mono_mb_emit_byte (mb, CEE_STIND_I);            
676                 break;
677         case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
678                 MonoClass *klass = mono_class_from_mono_type (type);
679                 int src_var, dst_var;
680
681                 src_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
682                 dst_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
683                 
684                 /* *dst = new object */
685                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
686                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
687                 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);        
688                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
689                 mono_mb_emit_byte (mb, CEE_STIND_I);
690         
691                 /* save the old src pointer */
692                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
693                 mono_mb_emit_stloc (mb, src_var);
694                 /* save the old dst pointer */
695                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
696                 mono_mb_emit_stloc (mb, dst_var);
697
698                 /* dst = pointer to newly created object data */
699                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
700                 mono_mb_emit_byte (mb, CEE_LDIND_I);
701                 mono_mb_emit_icon (mb, sizeof (MonoObject));
702                 mono_mb_emit_byte (mb, CEE_ADD);
703                 mono_mb_emit_byte (mb, CEE_STLOC_1); 
704
705                 emit_struct_conv (mb, klass, TRUE);
706                 
707                 /* restore the old src pointer */
708                 mono_mb_emit_ldloc (mb, src_var);
709                 mono_mb_emit_byte (mb, CEE_STLOC_0);
710                 /* restore the old dst pointer */
711                 mono_mb_emit_ldloc (mb, dst_var);
712                 mono_mb_emit_byte (mb, CEE_STLOC_1);
713                 break;
714         }
715         case MONO_MARSHAL_CONV_DEL_FTN: {
716                 // fixme: we never convert functions back to delegates, dont 
717                 // know if thats the correct behaviour
718                 break;
719         }
720         case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
721                 g_error ("Structure field of type %s can't be marshalled as LPArray", mono_class_from_mono_type (type)->name);
722                 break;
723         case MONO_MARSHAL_CONV_STR_LPWSTR:
724         case MONO_MARSHAL_CONV_STR_BSTR:
725         case MONO_MARSHAL_CONV_STR_ANSIBSTR:
726         case MONO_MARSHAL_CONV_STR_TBSTR:
727         case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
728         case MONO_MARSHAL_CONV_STR_BYVALWSTR: 
729         default:
730                 g_warning ("marshaling conversion %d not implemented", conv);
731                 g_assert_not_reached ();
732         }
733 }
734
735 static void
736 emit_str_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, int usize, int msize,
737                       MonoMarshalSpec *mspec)
738 {
739         int pos;
740
741         switch (conv) {
742         case MONO_MARSHAL_CONV_BOOL_I4:
743                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
744                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
745                 mono_mb_emit_byte (mb, CEE_LDIND_U1);
746                 mono_mb_emit_byte (mb, CEE_STIND_I4);
747                 break;
748         case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
749                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
750                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
751                 mono_mb_emit_byte (mb, CEE_LDIND_U1);
752                 mono_mb_emit_byte (mb, CEE_NEG);
753                 mono_mb_emit_byte (mb, CEE_STIND_I2);
754                 break;
755         case MONO_MARSHAL_CONV_STR_LPWSTR:
756         case MONO_MARSHAL_CONV_STR_LPSTR:
757         case MONO_MARSHAL_CONV_STR_LPTSTR:
758         case MONO_MARSHAL_CONV_STR_BSTR:
759         case MONO_MARSHAL_CONV_STR_ANSIBSTR:
760         case MONO_MARSHAL_CONV_STR_TBSTR:
761                 /* free space if free == true */
762                 mono_mb_emit_byte (mb, CEE_LDLOC_2);
763                 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
764                 mono_mb_emit_byte (mb, 4);
765                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
766                 mono_mb_emit_byte (mb, CEE_LDIND_I);
767                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
768                 mono_mb_emit_byte (mb, CEE_MONO_FREE);
769
770                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
771                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
772                 mono_mb_emit_byte (mb, CEE_LDIND_I);
773                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
774                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
775                 mono_mb_emit_byte (mb, conv);
776                 mono_mb_emit_byte (mb, CEE_STIND_I);    
777                 break;
778         case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
779         case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
780         case MONO_MARSHAL_CONV_DEL_FTN:
781                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
782                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
783                 mono_mb_emit_byte (mb, CEE_LDIND_I);
784                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
785                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
786                 mono_mb_emit_byte (mb, conv);
787                 mono_mb_emit_byte (mb, CEE_STIND_I);    
788                 break;
789         case MONO_MARSHAL_CONV_STR_BYVALSTR: 
790         case MONO_MARSHAL_CONV_STR_BYVALWSTR: {
791                 if (!usize)
792                         break;
793
794                 mono_mb_emit_byte (mb, CEE_LDLOC_1); /* dst */
795                 mono_mb_emit_byte (mb, CEE_LDLOC_0);    
796                 mono_mb_emit_byte (mb, CEE_LDIND_I); /* src String */
797                 mono_mb_emit_icon (mb, usize);
798                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
799                 mono_mb_emit_byte (mb, CEE_MONO_PROC3);
800                 mono_mb_emit_byte (mb, conv);
801                 break;
802         }
803         case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
804                 MonoClass *eclass;
805                 int esize;
806
807                 if (type->type == MONO_TYPE_SZARRAY) {
808                         eclass = type->data.klass;
809                 } else {
810                         g_assert_not_reached ();
811                 }
812
813                 if (eclass->valuetype)
814                         esize = mono_class_native_size (eclass, NULL);
815                 else
816                         esize = sizeof (gpointer);
817
818                 if (!usize) 
819                         break;
820
821                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
822                 mono_mb_emit_byte (mb, CEE_LDIND_I);            
823                 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
824                 pos = mb->pos;
825                 mono_mb_emit_byte (mb, 0);
826
827                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
828                 mono_mb_emit_byte (mb, CEE_LDLOC_0);    
829                 mono_mb_emit_byte (mb, CEE_LDIND_I);    
830                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
831                 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
832                 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
833                 mono_mb_emit_byte (mb, CEE_ADD);
834                 mono_mb_emit_icon (mb, mspec->data.array_data.num_elem * esize);
835                 mono_mb_emit_byte (mb, CEE_PREFIX1);
836                 mono_mb_emit_byte (mb, CEE_CPBLK);                      
837                 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
838                 break;
839         }
840         case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
841                 int src_var, dst_var;
842
843                 src_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
844                 dst_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
845                 
846                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
847                 mono_mb_emit_byte (mb, CEE_LDIND_I);            
848                 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
849                 pos = mb->pos;
850                 mono_mb_emit_byte (mb, 0);
851                 
852                 /* save the old src pointer */
853                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
854                 mono_mb_emit_stloc (mb, src_var);
855                 /* save the old dst pointer */
856                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
857                 mono_mb_emit_stloc (mb, dst_var);
858
859                 /* src = pointer to object data */
860                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
861                 mono_mb_emit_byte (mb, CEE_LDIND_I);            
862                 mono_mb_emit_icon (mb, sizeof (MonoObject));
863                 mono_mb_emit_byte (mb, CEE_ADD);
864                 mono_mb_emit_byte (mb, CEE_STLOC_0); 
865
866                 emit_struct_conv (mb, mono_class_from_mono_type (type), FALSE);
867                 
868                 /* restore the old src pointer */
869                 mono_mb_emit_ldloc (mb, src_var);
870                 mono_mb_emit_byte (mb, CEE_STLOC_0);
871                 /* restore the old dst pointer */
872                 mono_mb_emit_ldloc (mb, dst_var);
873                 mono_mb_emit_byte (mb, CEE_STLOC_1);
874
875                 mono_mb_patch_addr_s (mb, pos, mb->pos - pos - 1);
876                 break;
877         }
878         default: {
879                 char *msg = g_strdup_printf ("marshalling conversion %d not implemented", conv);
880                 MonoException *exc = mono_get_exception_not_implemented (msg);
881                 g_warning (msg);
882                 g_free (msg);
883                 mono_raise_exception (exc);
884         }
885         }
886 }
887
888 static void
889 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
890 {
891         MonoMarshalType *info;
892         int i;
893
894         if (klass->parent)
895                 emit_struct_conv(mb, klass->parent, to_object);
896
897         info = mono_marshal_load_type_info (klass);
898
899         if (info->native_size == 0)
900                 return;
901
902         if (klass->blittable) {
903                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
904                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
905                 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
906                 mono_mb_emit_byte (mb, CEE_PREFIX1);
907                 mono_mb_emit_byte (mb, CEE_CPBLK);
908                 return;
909         }
910
911         for (i = 0; i < info->num_fields; i++) {
912                 MonoMarshalNative ntype;
913                 MonoMarshalConv conv;
914                 MonoType *ftype = info->fields [i].field->type;
915                 int msize = 0;
916                 int usize = 0;
917                 gboolean last_field = i < (info->num_fields -1) ? 0 : 1;
918
919                 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
920                         continue;
921
922                 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, klass->unicode, &conv);
923                         
924                 if (last_field) {
925                         msize = klass->instance_size - info->fields [i].field->offset;
926                         usize = info->native_size - info->fields [i].offset;
927                 } else {
928                         msize = info->fields [i + 1].field->offset - info->fields [i].field->offset;
929                         usize = info->fields [i + 1].offset - info->fields [i].offset;
930                 }
931                 g_assert ((msize >= 0) && (usize >= 0));
932
933                 switch (conv) {
934                 case MONO_MARSHAL_CONV_NONE: {
935                         int t;
936
937                         if (ftype->byref || ftype->type == MONO_TYPE_I ||
938                             ftype->type == MONO_TYPE_U) {
939                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
940                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
941                                 mono_mb_emit_byte (mb, CEE_LDIND_I);
942                                 mono_mb_emit_byte (mb, CEE_STIND_I);
943                                 break;
944                         }
945
946                         t = ftype->type;
947                 handle_enum:
948                         switch (t) {
949                         case MONO_TYPE_I4:
950                         case MONO_TYPE_U4:
951 #if SIZEOF_VOID_P == 4
952                         case MONO_TYPE_PTR:
953 #endif
954                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
955                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
956                                 mono_mb_emit_byte (mb, CEE_LDIND_I4);
957                                 mono_mb_emit_byte (mb, CEE_STIND_I4);
958                                 break;
959                         case MONO_TYPE_I1:
960                         case MONO_TYPE_U1:
961                         case MONO_TYPE_BOOLEAN:
962                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
963                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
964                                 mono_mb_emit_byte (mb, CEE_LDIND_I1);
965                                 mono_mb_emit_byte (mb, CEE_STIND_I1);
966                                 break;
967                         case MONO_TYPE_I2:
968                         case MONO_TYPE_U2:
969                         case MONO_TYPE_CHAR:
970                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
971                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
972                                 mono_mb_emit_byte (mb, CEE_LDIND_I2);
973                                 mono_mb_emit_byte (mb, CEE_STIND_I2);
974                                 break;
975                         case MONO_TYPE_I8:
976                         case MONO_TYPE_U8:
977 #if SIZEOF_VOID_P == 8
978                         case MONO_TYPE_PTR:
979 #endif
980                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
981                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
982                                 mono_mb_emit_byte (mb, CEE_LDIND_I8);
983                                 mono_mb_emit_byte (mb, CEE_STIND_I8);
984                                 break;
985                         case MONO_TYPE_R4:
986                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
987                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
988                                 mono_mb_emit_byte (mb, CEE_LDIND_R4);
989                                 mono_mb_emit_byte (mb, CEE_STIND_R4);
990                                 break;
991                         case MONO_TYPE_R8:
992                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
993                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
994                                 mono_mb_emit_byte (mb, CEE_LDIND_R8);
995                                 mono_mb_emit_byte (mb, CEE_STIND_R8);
996                                 break;
997                         case MONO_TYPE_VALUETYPE:
998                                 if (ftype->data.klass->enumtype) {
999                                         t = ftype->data.klass->enum_basetype->type;
1000                                         goto handle_enum;
1001                                 }
1002                                 emit_struct_conv (mb, ftype->data.klass, to_object);
1003                                 continue;
1004                         default:
1005                                 g_warning ("marshaling type %02x not implemented", ftype->type);
1006                                 g_assert_not_reached ();
1007                         }
1008                         break;
1009                 }
1010                 default:
1011                         if (to_object) 
1012                                 emit_ptr_to_str_conv (mb, ftype, conv, usize, msize, info->fields [i].mspec);
1013                         else
1014                                 emit_str_to_ptr_conv (mb, ftype, conv, usize, msize, info->fields [i].mspec);   
1015                 }
1016                 
1017                 if (to_object) {
1018                         mono_mb_emit_add_to_local (mb, 0, usize);
1019                         mono_mb_emit_add_to_local (mb, 1, msize);
1020                 } else {
1021                         mono_mb_emit_add_to_local (mb, 0, msize);
1022                         mono_mb_emit_add_to_local (mb, 1, usize);
1023                 }                               
1024         }
1025 }
1026
1027 static MonoAsyncResult *
1028 mono_delegate_begin_invoke (MonoDelegate *delegate, gpointer *params)
1029 {
1030         MonoMethodMessage *msg;
1031         MonoDelegate *async_callback;
1032         MonoObject *state;
1033         MonoMethod *im;
1034         MonoClass *klass;
1035         MonoMethod *method = NULL;
1036         int i;
1037
1038         g_assert (delegate);
1039
1040         if (delegate->target && mono_object_class (delegate->target) == mono_defaults.transparent_proxy_class) {
1041
1042                 MonoTransparentProxy* tp = (MonoTransparentProxy *)delegate->target;
1043                 if (!tp->klass->contextbound || tp->rp->context != (MonoObject *) mono_context_get ()) {
1044
1045                         // If the target is a proxy, make a direct call. Is proxy's work
1046                         // to make the call asynchronous.
1047
1048                         MonoAsyncResult *ares;
1049                         MonoObject *exc;
1050                         MonoArray *out_args;
1051                         HANDLE handle;
1052                         method = delegate->method_info->method;
1053
1054                         msg = mono_method_call_message_new (method, params, NULL, &async_callback, &state);
1055                         handle = CreateEvent (NULL, TRUE, FALSE, NULL);
1056                         ares = mono_async_result_new (mono_domain_get (), handle, state, handle);
1057                         ares->async_delegate = (MonoObject *)delegate;
1058                         ares->async_callback = (MonoObject *)async_callback;
1059                         msg->async_result = ares;
1060                         msg->call_type = CallType_BeginInvoke;
1061
1062                         mono_remoting_invoke ((MonoObject *)tp->rp, msg, &exc, &out_args);
1063                         return ares;
1064                 }
1065         }
1066
1067         klass = delegate->object.vtable->klass;
1068
1069         method = mono_get_delegate_invoke (klass);
1070         for (i = 0; i < klass->method.count; ++i) {
1071                 if (klass->methods [i]->name[0] == 'B' && 
1072                     !strcmp ("BeginInvoke", klass->methods [i]->name)) {
1073                         method = klass->methods [i];
1074                         break;
1075                 }
1076         }
1077
1078         g_assert (method != NULL);
1079
1080         im = mono_get_delegate_invoke (method->klass);
1081         msg = mono_method_call_message_new (method, params, im, &async_callback, &state);
1082
1083         return mono_thread_pool_add ((MonoObject *)delegate, msg, async_callback, state);
1084 }
1085
1086 static int
1087 mono_mb_emit_save_args (MonoMethodBuilder *mb, MonoMethodSignature *sig, gboolean save_this)
1088 {
1089         int i, params_var, tmp_var;
1090
1091         /* allocate local (pointer) *params[] */
1092         params_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1093         /* allocate local (pointer) tmp */
1094         tmp_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1095
1096         /* alloate space on stack to store an array of pointers to the arguments */
1097         mono_mb_emit_icon (mb, sizeof (gpointer) * (sig->param_count + 1));
1098         mono_mb_emit_byte (mb, CEE_PREFIX1);
1099         mono_mb_emit_byte (mb, CEE_LOCALLOC);
1100         mono_mb_emit_stloc (mb, params_var);
1101
1102         /* tmp = params */
1103         mono_mb_emit_ldloc (mb, params_var);
1104         mono_mb_emit_stloc (mb, tmp_var);
1105
1106         if (save_this && sig->hasthis) {
1107                 mono_mb_emit_ldloc (mb, tmp_var);
1108                 mono_mb_emit_ldarg_addr (mb, 0);
1109                 mono_mb_emit_byte (mb, CEE_STIND_I);
1110                 /* tmp = tmp + sizeof (gpointer) */
1111                 if (sig->param_count)
1112                         mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
1113
1114         }
1115
1116         for (i = 0; i < sig->param_count; i++) {
1117                 mono_mb_emit_ldloc (mb, tmp_var);
1118                 mono_mb_emit_ldarg_addr (mb, i + sig->hasthis);
1119                 mono_mb_emit_byte (mb, CEE_STIND_I);
1120                 /* tmp = tmp + sizeof (gpointer) */
1121                 if (i < (sig->param_count - 1))
1122                         mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
1123         }
1124
1125         return params_var;
1126 }
1127
1128 static char*
1129 mono_signature_to_name (MonoMethodSignature *sig, const char *prefix)
1130 {
1131         int i;
1132         char *result;
1133         GString *res = g_string_new ("");
1134
1135         if (prefix) {
1136                 g_string_append (res, prefix);
1137                 g_string_append_c (res, '_');
1138         }
1139
1140         mono_type_get_desc (res, sig->ret, FALSE);
1141
1142         for (i = 0; i < sig->param_count; ++i) {
1143                 g_string_append_c (res, '_');
1144                 mono_type_get_desc (res, sig->params [i], FALSE);
1145         }
1146         result = res->str;
1147         g_string_free (res, FALSE);
1148         return result;
1149 }
1150
1151 static inline MonoMethod*
1152 mono_marshal_find_in_cache (GHashTable *cache, gpointer key)
1153 {
1154         MonoMethod *res;
1155
1156         EnterCriticalSection (&marshal_mutex);
1157         res = g_hash_table_lookup (cache, key);
1158         LeaveCriticalSection (&marshal_mutex);
1159         return res;
1160 }
1161
1162 /* Create the method from the builder and place it in the cache */
1163 static inline MonoMethod*
1164 mono_mb_create_and_cache (GHashTable *cache, gpointer key,
1165                                                            MonoMethodBuilder *mb, MonoMethodSignature *sig,
1166                                                            int max_stack)
1167 {
1168         MonoMethod *res;
1169
1170         EnterCriticalSection (&marshal_mutex);
1171         res = g_hash_table_lookup (cache, key);
1172         if (!res) {
1173                 /* This does not acquire any locks */
1174                 res = mono_mb_create_method (mb, sig, max_stack);
1175                 g_hash_table_insert (cache, key, res);
1176                 mono_g_hash_table_insert (wrapper_hash, res, key);
1177         }
1178         else
1179                 /* Somebody created it before us */
1180                 ;
1181         LeaveCriticalSection (&marshal_mutex);
1182
1183         return res;
1184 }               
1185
1186 MonoMethod *
1187 mono_marshal_method_from_wrapper (MonoMethod *wrapper)
1188 {
1189         MonoMethod *res;
1190
1191         if (wrapper->wrapper_type == MONO_WRAPPER_NONE)
1192                 return wrapper;
1193
1194         EnterCriticalSection (&marshal_mutex);
1195         res = mono_g_hash_table_lookup (wrapper_hash, wrapper);
1196         LeaveCriticalSection (&marshal_mutex);
1197
1198         if (res && wrapper->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)
1199                 /* See mono_marshal_get_remoting_invoke_with_check */
1200                 return (MonoMethod*)((char*)res - 1);
1201         else
1202                 return res;
1203 }
1204
1205 MonoMethod *
1206 mono_marshal_get_delegate_begin_invoke (MonoMethod *method)
1207 {
1208         MonoMethodSignature *sig;
1209         static MonoMethodSignature *csig = NULL;
1210         MonoMethodBuilder *mb;
1211         MonoMethod *res;
1212         GHashTable *cache;
1213         int params_var;
1214         char *name;
1215
1216         g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1217                   !strcmp (method->name, "BeginInvoke"));
1218
1219         sig = method->signature;
1220
1221         cache = method->klass->image->delegate_begin_invoke_cache;
1222         if ((res = mono_marshal_find_in_cache (cache, sig)))
1223                 return res;
1224
1225         g_assert (sig->hasthis);
1226
1227         if (!csig) {
1228                 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1229                 csig = g_malloc0 (sigsize);
1230
1231                 /* MonoAsyncResult * begin_invoke (MonoDelegate *delegate, gpointer params[]) */
1232                 csig->param_count = 2;
1233                 csig->ret = &mono_defaults.object_class->byval_arg;
1234                 csig->params [0] = &mono_defaults.object_class->byval_arg;
1235                 csig->params [1] = &mono_defaults.int_class->byval_arg;
1236         }
1237
1238         name = mono_signature_to_name (sig, "begin_invoke");
1239         mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_BEGIN_INVOKE);
1240         g_free (name);
1241
1242         mb->method->save_lmf = 1;
1243
1244         params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1245
1246         mono_mb_emit_ldarg (mb, 0);
1247         mono_mb_emit_ldloc (mb, params_var);
1248         mono_mb_emit_native_call (mb, csig, mono_delegate_begin_invoke);
1249         mono_mb_emit_byte (mb, CEE_RET);
1250
1251         res = mono_mb_create_and_cache (cache, sig, mb, sig, sig->param_count + 16);
1252         mono_mb_free (mb);
1253         return res;
1254 }
1255
1256 static MonoObject *
1257 mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params)
1258 {
1259         MonoDomain *domain = mono_domain_get ();
1260         MonoAsyncResult *ares;
1261         MonoMethod *method = NULL;
1262         MonoMethodSignature *sig;
1263         MonoMethodMessage *msg;
1264         MonoObject *res, *exc;
1265         MonoArray *out_args;
1266         MonoClass *klass;
1267         int i;
1268
1269         g_assert (delegate);
1270
1271         if (!delegate->method_info || !delegate->method_info->method)
1272                 g_assert_not_reached ();
1273
1274         klass = delegate->object.vtable->klass;
1275
1276         for (i = 0; i < klass->method.count; ++i) {
1277                 if (klass->methods [i]->name[0] == 'E' && 
1278                     !strcmp ("EndInvoke", klass->methods [i]->name)) {
1279                         method = klass->methods [i];
1280                         break;
1281                 }
1282         }
1283
1284         g_assert (method != NULL);
1285
1286         sig = method->signature;
1287
1288         msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1289
1290         ares = mono_array_get (msg->args, gpointer, sig->param_count - 1);
1291         g_assert (ares);
1292
1293         if (delegate->target && mono_object_class (delegate->target) == mono_defaults.transparent_proxy_class) {
1294                 MonoTransparentProxy* tp = (MonoTransparentProxy *)delegate->target;
1295                 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
1296                 mono_message_init (domain, msg, delegate->method_info, NULL);
1297                 msg->call_type = CallType_EndInvoke;
1298                 msg->async_result = ares;
1299                 res = mono_remoting_invoke ((MonoObject *)tp->rp, msg, &exc, &out_args);
1300         }
1301         else
1302                 res = mono_thread_pool_finish (ares, &out_args, &exc);
1303
1304         if (exc) {
1305                 char *strace = mono_string_to_utf8 (((MonoException*)exc)->stack_trace);
1306                 char  *tmp;
1307                 tmp = g_strdup_printf ("%s\nException Rethrown at:\n", strace);
1308                 g_free (strace);        
1309                 ((MonoException*)exc)->stack_trace = mono_string_new (domain, tmp);
1310                 g_free (tmp);
1311                 mono_raise_exception ((MonoException*)exc);
1312         }
1313
1314         mono_method_return_message_restore (method, params, out_args);
1315         return res;
1316 }
1317
1318 static void
1319 mono_mb_emit_restore_result (MonoMethodBuilder *mb, MonoType *return_type)
1320 {
1321         if (return_type->byref)
1322                 return_type = &mono_defaults.int_class->byval_arg;
1323         else if (return_type->type == MONO_TYPE_VALUETYPE && return_type->data.klass->enumtype)
1324                 return_type = return_type->data.klass->enum_basetype;
1325
1326         switch (return_type->type) {
1327         case MONO_TYPE_VOID:
1328                 g_assert_not_reached ();
1329                 break;
1330         case MONO_TYPE_PTR:
1331         case MONO_TYPE_STRING:
1332         case MONO_TYPE_CLASS: 
1333         case MONO_TYPE_OBJECT: 
1334         case MONO_TYPE_ARRAY: 
1335         case MONO_TYPE_SZARRAY: 
1336                 /* nothing to do */
1337                 break;
1338         case MONO_TYPE_U1:
1339         case MONO_TYPE_BOOLEAN:
1340                 mono_mb_emit_byte (mb, CEE_UNBOX);
1341                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1342                 mono_mb_emit_byte (mb, CEE_LDIND_U1);
1343                 break;
1344         case MONO_TYPE_I1:
1345                 mono_mb_emit_byte (mb, CEE_UNBOX);
1346                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1347                 mono_mb_emit_byte (mb, CEE_LDIND_I1);
1348                 break;
1349         case MONO_TYPE_U2:
1350         case MONO_TYPE_CHAR:
1351                 mono_mb_emit_byte (mb, CEE_UNBOX);
1352                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1353                 mono_mb_emit_byte (mb, CEE_LDIND_U2);
1354                 break;
1355         case MONO_TYPE_I2:
1356                 mono_mb_emit_byte (mb, CEE_UNBOX);
1357                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1358                 mono_mb_emit_byte (mb, CEE_LDIND_I2);
1359                 break;
1360         case MONO_TYPE_I:
1361         case MONO_TYPE_U:
1362                 mono_mb_emit_byte (mb, CEE_UNBOX);
1363                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1364                 mono_mb_emit_byte (mb, CEE_LDIND_I);
1365                 break;
1366         case MONO_TYPE_I4:
1367                 mono_mb_emit_byte (mb, CEE_UNBOX);
1368                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1369                 mono_mb_emit_byte (mb, CEE_LDIND_I4);
1370                 break;
1371         case MONO_TYPE_U4:
1372                 mono_mb_emit_byte (mb, CEE_UNBOX);
1373                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1374                 mono_mb_emit_byte (mb, CEE_LDIND_U4);
1375                 break;
1376         case MONO_TYPE_U8:
1377         case MONO_TYPE_I8:
1378                 mono_mb_emit_byte (mb, CEE_UNBOX);
1379                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1380                 mono_mb_emit_byte (mb, CEE_LDIND_I8);
1381                 break;
1382         case MONO_TYPE_R4:
1383                 mono_mb_emit_byte (mb, CEE_UNBOX);
1384                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1385                 mono_mb_emit_byte (mb, CEE_LDIND_R4);
1386                 break;
1387         case MONO_TYPE_R8:
1388                 mono_mb_emit_byte (mb, CEE_UNBOX);
1389                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
1390                 mono_mb_emit_byte (mb, CEE_LDIND_R8);
1391                 break;
1392         case MONO_TYPE_VALUETYPE: {
1393                 int class;
1394                 mono_mb_emit_byte (mb, CEE_UNBOX);
1395                 class = mono_mb_add_data (mb, mono_class_from_mono_type (return_type));
1396                 mono_mb_emit_i4 (mb, class);
1397                 mono_mb_emit_byte (mb, CEE_LDOBJ);
1398                 mono_mb_emit_i4 (mb, class);
1399                 break;
1400         }
1401         default:
1402                 g_warning ("type 0x%x not handled", return_type->type);
1403                 g_assert_not_reached ();
1404         }
1405
1406         mono_mb_emit_byte (mb, CEE_RET);
1407 }
1408
1409 MonoMethod *
1410 mono_marshal_get_delegate_end_invoke (MonoMethod *method)
1411 {
1412         MonoMethodSignature *sig;
1413         static MonoMethodSignature *csig = NULL;
1414         MonoMethodBuilder *mb;
1415         MonoMethod *res;
1416         GHashTable *cache;
1417         int params_var;
1418         char *name;
1419
1420         g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1421                   !strcmp (method->name, "EndInvoke"));
1422
1423         sig = method->signature;
1424
1425         cache = method->klass->image->delegate_end_invoke_cache;
1426         if ((res = mono_marshal_find_in_cache (cache, sig)))
1427                 return res;
1428
1429         g_assert (sig->hasthis);
1430
1431         if (!csig) {
1432                 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
1433                 csig = g_malloc0 (sigsize);
1434
1435                 /* MonoObject *end_invoke (MonoDelegate *delegate, gpointer params[]) */
1436                 csig->param_count = 2;
1437                 csig->ret = &mono_defaults.object_class->byval_arg;
1438                 csig->params [0] = &mono_defaults.object_class->byval_arg;
1439                 csig->params [1] = &mono_defaults.int_class->byval_arg;
1440         }
1441
1442         name = mono_signature_to_name (sig, "end_invoke");
1443         mb = mono_mb_new (mono_defaults.multicastdelegate_class, name, MONO_WRAPPER_DELEGATE_END_INVOKE);
1444         g_free (name);
1445
1446         mb->method->save_lmf = 1;
1447
1448         params_var = mono_mb_emit_save_args (mb, sig, FALSE);
1449
1450         mono_mb_emit_ldarg (mb, 0);
1451         mono_mb_emit_ldloc (mb, params_var);
1452         mono_mb_emit_native_call (mb, csig, mono_delegate_end_invoke);
1453
1454         if (sig->ret->type == MONO_TYPE_VOID) {
1455                 mono_mb_emit_byte (mb, CEE_POP);
1456                 mono_mb_emit_byte (mb, CEE_RET);
1457         } else
1458                 mono_mb_emit_restore_result (mb, sig->ret);
1459
1460         res = mono_mb_create_and_cache (cache, sig,
1461                                                                                  mb, sig, sig->param_count + 16);
1462         mono_mb_free (mb);
1463
1464         return res;
1465 }
1466
1467 static MonoObject *
1468 mono_remoting_wrapper (MonoMethod *method, gpointer *params)
1469 {
1470         MonoMethodMessage *msg;
1471         MonoTransparentProxy *this;
1472         MonoObject *res, *exc;
1473         MonoArray *out_args;
1474
1475         this = *((MonoTransparentProxy **)params [0]);
1476
1477         g_assert (this);
1478         g_assert (((MonoObject *)this)->vtable->klass == mono_defaults.transparent_proxy_class);
1479         
1480         /* skip the this pointer */
1481         params++;
1482
1483         if (this->klass->contextbound && this->rp->context == (MonoObject *) mono_context_get ())
1484         {
1485                 int i;
1486                 MonoMethodSignature *sig = method->signature;
1487                 int count = sig->param_count;
1488                 gpointer* mparams = (gpointer*) alloca(count*sizeof(gpointer));
1489
1490                 for (i=0; i<count; i++) {
1491                         MonoClass *class = mono_class_from_mono_type (sig->params [i]);
1492                         if (class->valuetype) {
1493                                 if (sig->params [i]->byref)
1494                                         mparams[i] = *((gpointer *)params [i]);
1495                                 else 
1496                                         mparams[i] = params [i];
1497                         } else {
1498                                 mparams[i] = *((gpointer**)params [i]);
1499                         }
1500                 }
1501
1502                 return mono_runtime_invoke (method, this, mparams, NULL);
1503         }
1504
1505         msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
1506
1507         res = mono_remoting_invoke ((MonoObject *)this->rp, msg, &exc, &out_args);
1508
1509         if (exc)
1510                 mono_raise_exception ((MonoException *)exc);
1511
1512         mono_method_return_message_restore (method, params, out_args);
1513
1514         return res;
1515
1516
1517 MonoMethod *
1518 mono_marshal_get_remoting_invoke (MonoMethod *method)
1519 {
1520         MonoMethodSignature *sig;
1521         static MonoMethodSignature *csig = NULL;
1522         MonoMethodBuilder *mb;
1523         MonoMethod *res;
1524         GHashTable *cache;
1525         int params_var;
1526
1527         g_assert (method);
1528
1529         if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE)
1530                 return method;
1531
1532         sig = method->signature;
1533
1534         /* we cant remote methods without this pointer */
1535         if (!sig->hasthis)
1536                 return method;
1537
1538         cache = method->klass->image->remoting_invoke_cache;
1539         if ((res = mono_marshal_find_in_cache (cache, method)))
1540                 return res;
1541
1542         if (!csig) {
1543                 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
1544                 csig->params [0] = &mono_defaults.int_class->byval_arg;
1545                 csig->params [1] = &mono_defaults.int_class->byval_arg;
1546                 csig->ret = &mono_defaults.object_class->byval_arg;
1547                 csig->pinvoke = 1;
1548         }
1549
1550         mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE);
1551         mb->method->save_lmf = 1;
1552
1553         params_var = mono_mb_emit_save_args (mb, sig, TRUE);
1554
1555         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1556         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1557         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
1558         mono_mb_emit_ldloc (mb, params_var);
1559         mono_mb_emit_native_call (mb, csig, mono_remoting_wrapper);
1560
1561         if (sig->ret->type == MONO_TYPE_VOID) {
1562                 mono_mb_emit_byte (mb, CEE_POP);
1563                 mono_mb_emit_byte (mb, CEE_RET);
1564         } else {
1565                  mono_mb_emit_restore_result (mb, sig->ret);
1566         }
1567
1568         res = mono_mb_create_and_cache (cache, method, mb, sig, sig->param_count + 16);
1569         mono_mb_free (mb);
1570
1571         return res;
1572 }
1573
1574 MonoMethod *
1575 mono_marshal_get_remoting_invoke_with_check (MonoMethod *method)
1576 {
1577         MonoMethodSignature *sig;
1578         MonoMethodBuilder *mb;
1579         MonoMethod *res, *native;
1580         GHashTable *cache;
1581         int i, pos;
1582
1583         g_assert (method);
1584
1585         if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)
1586                 return method;
1587
1588         sig = method->signature;
1589
1590         /* we cant remote methods without this pointer */
1591         g_assert (sig->hasthis);
1592
1593         cache = method->klass->image->remoting_invoke_cache;
1594         if ((res = mono_marshal_find_in_cache (cache, (char *)method + 1)))
1595                 return res;
1596
1597         mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK);
1598
1599         mono_mb_emit_ldarg (mb, 0);
1600         pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
1601
1602         native = mono_marshal_get_remoting_invoke (method);
1603
1604         for (i = 0; i <= sig->param_count; i++)
1605                 mono_mb_emit_ldarg (mb, i);
1606         
1607         mono_mb_emit_managed_call (mb, native, native->signature);
1608         mono_mb_emit_byte (mb, CEE_RET);
1609
1610         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1611
1612         for (i = 0; i <= sig->param_count; i++)
1613                 mono_mb_emit_ldarg (mb, i);
1614                 
1615         mono_mb_emit_managed_call (mb, method, method->signature);
1616         mono_mb_emit_byte (mb, CEE_RET);
1617
1618         res = mono_mb_create_and_cache (cache, (char*)method + 1,
1619                                                                                  mb, sig, sig->param_count + 16);
1620         mono_mb_free (mb);
1621
1622         return res;
1623 }
1624
1625 /*
1626  * the returned method invokes all methods in a multicast delegate 
1627  */
1628 MonoMethod *
1629 mono_marshal_get_delegate_invoke (MonoMethod *method)
1630 {
1631         MonoMethodSignature *sig, *static_sig;
1632         int i, sigsize;
1633         MonoMethodBuilder *mb;
1634         MonoMethod *res;
1635         GHashTable *cache;
1636         int pos0, pos1;
1637         char *name;
1638
1639         g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1640                   !strcmp (method->name, "Invoke"));
1641                 
1642         sig = method->signature;
1643
1644         cache = method->klass->image->delegate_invoke_cache;
1645         if ((res = mono_marshal_find_in_cache (cache, sig)))
1646                 return res;
1647
1648         sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1649         static_sig = g_memdup (sig, sigsize);
1650         static_sig->hasthis = 0;
1651
1652         name = mono_signature_to_name (sig, "invoke");
1653         mb = mono_mb_new (mono_defaults.multicastdelegate_class, name,  MONO_WRAPPER_DELEGATE_INVOKE);
1654         g_free (name);
1655
1656         /* allocate local 0 (object) */
1657         mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1658
1659         g_assert (sig->hasthis);
1660         
1661         /*
1662          * if (prev != null)
1663          *      prev.Invoke( args .. );
1664          * return this.<target>( args .. );
1665          */
1666
1667         /* get this->prev */
1668         mono_mb_emit_ldarg (mb, 0);
1669         mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoMulticastDelegate, prev));
1670         mono_mb_emit_byte (mb, CEE_LDIND_I );
1671         mono_mb_emit_stloc (mb, 0);
1672
1673         /* if prev != null */
1674         mono_mb_emit_ldloc (mb, 0);
1675         mono_mb_emit_byte (mb, CEE_BRFALSE);
1676
1677         pos0 = mb->pos;
1678         mono_mb_emit_i4 (mb, 0);
1679
1680         /* then recurse */
1681         mono_mb_emit_ldloc (mb, 0);
1682         for (i = 0; i < sig->param_count; i++)
1683                 mono_mb_emit_ldarg (mb, i + 1);
1684         mono_mb_emit_managed_call (mb, method, method->signature);
1685         if (sig->ret->type != MONO_TYPE_VOID)
1686                 mono_mb_emit_byte (mb, CEE_POP);
1687
1688         /* continued or prev == null */
1689         mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1690
1691         /* get this->target */
1692         mono_mb_emit_ldarg (mb, 0);
1693         mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, target));
1694         mono_mb_emit_byte (mb, CEE_LDIND_I );
1695         mono_mb_emit_stloc (mb, 0);
1696
1697         /* if target != null */
1698         mono_mb_emit_ldloc (mb, 0);
1699         mono_mb_emit_byte (mb, CEE_BRFALSE);
1700         pos0 = mb->pos;
1701         mono_mb_emit_i4 (mb, 0);
1702         
1703         /* then call this->method_ptr nonstatic */
1704         mono_mb_emit_ldloc (mb, 0); 
1705         for (i = 0; i < sig->param_count; ++i)
1706                 mono_mb_emit_ldarg (mb, i + 1);
1707         mono_mb_emit_ldarg (mb, 0);
1708         mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1709         mono_mb_emit_byte (mb, CEE_LDIND_I );
1710         mono_mb_emit_byte (mb, CEE_CALLI);
1711         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
1712
1713         mono_mb_emit_byte (mb, CEE_BR);
1714         pos1 = mb->pos;
1715         mono_mb_emit_i4 (mb, 0);
1716
1717         /* else [target == null] call this->method_ptr static */
1718         mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
1719
1720         for (i = 0; i < sig->param_count; ++i)
1721                 mono_mb_emit_ldarg (mb, i + 1);
1722         mono_mb_emit_ldarg (mb, 0);
1723         mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1724         mono_mb_emit_byte (mb, CEE_LDIND_I );
1725         mono_mb_emit_byte (mb, CEE_CALLI);
1726         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, static_sig));
1727
1728         /* return */
1729         mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
1730         mono_mb_emit_byte (mb, CEE_RET);
1731
1732         res = mono_mb_create_and_cache (cache, sig,
1733                                                                                  mb, sig, sig->param_count + 16);
1734         mono_mb_free (mb);
1735
1736         return res;     
1737 }
1738
1739 /*
1740  * generates IL code for the runtime invoke function 
1741  * MonoObject *runtime_invoke (MonoObject *this, void **params, MonoObject **exc)
1742  *
1743  * we also catch exceptions if exc != null
1744  */
1745 MonoMethod *
1746 mono_marshal_get_runtime_invoke (MonoMethod *method)
1747 {
1748         MonoMethodSignature *sig, *csig;
1749         MonoExceptionClause *clause;
1750         MonoMethodHeader *header;
1751         MonoMethodBuilder *mb;
1752         MonoMethod *res;
1753         GHashTable *cache;
1754         static MonoString *string_dummy = NULL;
1755         int i, pos, sigsize;
1756
1757         g_assert (method);
1758
1759         cache = method->klass->image->runtime_invoke_cache;
1760         if ((res = mono_marshal_find_in_cache (cache, method)))
1761                 return res;
1762         
1763         /* to make it work with our special string constructors */
1764         if (!string_dummy)
1765                 string_dummy = mono_string_new_wrapper ("dummy");
1766
1767         sig = method->signature;
1768
1769         sigsize = sizeof (MonoMethodSignature) + 3 * sizeof (MonoType *);
1770         csig = g_malloc0 (sigsize);
1771
1772         csig->param_count = 3;
1773         csig->ret = &mono_defaults.object_class->byval_arg;
1774         csig->params [0] = &mono_defaults.object_class->byval_arg;
1775         csig->params [1] = &mono_defaults.int_class->byval_arg;
1776         csig->params [2] = &mono_defaults.int_class->byval_arg;
1777
1778         mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_RUNTIME_INVOKE);
1779
1780         /* allocate local 0 (object) tmp */
1781         mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1782         /* allocate local 1 (object) exc */
1783         mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1784
1785         /* cond set *exc to null */
1786         mono_mb_emit_byte (mb, CEE_LDARG_2);
1787         mono_mb_emit_byte (mb, CEE_BRFALSE_S);
1788         mono_mb_emit_byte (mb, 3);      
1789         mono_mb_emit_byte (mb, CEE_LDARG_2);
1790         mono_mb_emit_byte (mb, CEE_LDNULL);
1791         mono_mb_emit_byte (mb, CEE_STIND_I);
1792
1793         if (sig->hasthis) {
1794                 if (method->string_ctor) {
1795                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1796                         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1797                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, string_dummy));
1798                 } else {
1799                         mono_mb_emit_ldarg (mb, 0);
1800                         if (method->klass->valuetype) {
1801                                 mono_mb_emit_byte (mb, CEE_UNBOX);
1802                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method->klass));
1803                         } 
1804                 }
1805         }
1806
1807         for (i = 0; i < sig->param_count; i++) {
1808                 MonoType *t = sig->params [i];
1809                 int type;
1810
1811                 mono_mb_emit_ldarg (mb, 1);
1812                 if (i) {
1813                         mono_mb_emit_icon (mb, sizeof (gpointer) * i);
1814                         mono_mb_emit_byte (mb, CEE_ADD);
1815                 }
1816                 mono_mb_emit_byte (mb, CEE_LDIND_I);
1817
1818                 if (t->byref)
1819                         continue;
1820
1821                 type = sig->params [i]->type;
1822 handle_enum:
1823                 switch (type) {
1824                 case MONO_TYPE_I1:
1825                         mono_mb_emit_byte (mb, CEE_LDIND_I1);
1826                         break;
1827                 case MONO_TYPE_BOOLEAN:
1828                 case MONO_TYPE_U1:
1829                         mono_mb_emit_byte (mb, CEE_LDIND_U1);
1830                         break;
1831                 case MONO_TYPE_I2:
1832                         mono_mb_emit_byte (mb, CEE_LDIND_I2);
1833                         break;
1834                 case MONO_TYPE_U2:
1835                 case MONO_TYPE_CHAR:
1836                         mono_mb_emit_byte (mb, CEE_LDIND_U2);
1837                         break;
1838                 case MONO_TYPE_I:
1839                 case MONO_TYPE_U:
1840                         mono_mb_emit_byte (mb, CEE_LDIND_I);
1841                         break;
1842                 case MONO_TYPE_I4:
1843                         mono_mb_emit_byte (mb, CEE_LDIND_I4);
1844                         break;
1845                 case MONO_TYPE_U4:
1846                         mono_mb_emit_byte (mb, CEE_LDIND_U4);
1847                         break;
1848                 case MONO_TYPE_R4:
1849                         mono_mb_emit_byte (mb, CEE_LDIND_R4);
1850                         break;
1851                 case MONO_TYPE_R8:
1852                         mono_mb_emit_byte (mb, CEE_LDIND_R8);
1853                         break;
1854                 case MONO_TYPE_I8:
1855                 case MONO_TYPE_U8:
1856                         mono_mb_emit_byte (mb, CEE_LDIND_I8);
1857                         break;
1858                 case MONO_TYPE_STRING:
1859                 case MONO_TYPE_CLASS:  
1860                 case MONO_TYPE_ARRAY:
1861                 case MONO_TYPE_PTR:
1862                 case MONO_TYPE_SZARRAY:
1863                 case MONO_TYPE_OBJECT:
1864                         /* do nothing */
1865                         break;
1866                 case MONO_TYPE_VALUETYPE:
1867                         if (t->data.klass->enumtype) {
1868                                 type = t->data.klass->enum_basetype->type;
1869                                 goto handle_enum;
1870                         }
1871                         mono_mb_emit_byte (mb, CEE_LDOBJ);
1872                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, t->data.klass));
1873                         break;
1874                 default:
1875                         g_assert_not_reached ();
1876                 }               
1877         }
1878
1879         if (method->string_ctor) {
1880                 MonoMethodSignature *strsig;
1881
1882                 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1883                 strsig = g_memdup (sig, sigsize);
1884                 strsig->ret = &mono_defaults.string_class->byval_arg;
1885
1886                 mono_mb_emit_managed_call (mb, method, strsig);         
1887         } else 
1888                 mono_mb_emit_managed_call (mb, method, NULL);
1889
1890         if (sig->ret->byref) {
1891                 /* fixme: */
1892                 g_assert_not_reached ();
1893         }
1894
1895
1896         switch (sig->ret->type) {
1897         case MONO_TYPE_VOID:
1898                 if (!method->string_ctor)
1899                         mono_mb_emit_byte (mb, CEE_LDNULL);
1900                 break;
1901         case MONO_TYPE_BOOLEAN:
1902         case MONO_TYPE_CHAR:
1903         case MONO_TYPE_I1:
1904         case MONO_TYPE_U1:
1905         case MONO_TYPE_I2:
1906         case MONO_TYPE_U2:
1907         case MONO_TYPE_I4:
1908         case MONO_TYPE_U4:
1909         case MONO_TYPE_I:
1910         case MONO_TYPE_U:
1911         case MONO_TYPE_R4:
1912         case MONO_TYPE_R8:
1913         case MONO_TYPE_I8:
1914         case MONO_TYPE_U8:
1915         case MONO_TYPE_VALUETYPE:
1916                 /* box value types */
1917                 mono_mb_emit_byte (mb, CEE_BOX);
1918                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (sig->ret)));
1919                 break;
1920         case MONO_TYPE_STRING:
1921         case MONO_TYPE_CLASS:  
1922         case MONO_TYPE_ARRAY:
1923         case MONO_TYPE_SZARRAY:
1924         case MONO_TYPE_OBJECT:
1925                 /* nothing to do */
1926                 break;
1927         case MONO_TYPE_PTR:
1928         default:
1929                 g_assert_not_reached ();
1930         }
1931
1932         mono_mb_emit_stloc (mb, 0);
1933                 
1934         mono_mb_emit_byte (mb, CEE_LEAVE);
1935         pos = mb->pos;
1936         mono_mb_emit_i4 (mb, 0);
1937
1938         clause = g_new0 (MonoExceptionClause, 1);
1939         clause->flags = MONO_EXCEPTION_CLAUSE_FILTER;
1940         clause->try_len = mb->pos;
1941
1942         /* filter code */
1943         clause->token_or_filter = mb->pos;
1944         
1945         mono_mb_emit_byte (mb, CEE_POP);
1946         mono_mb_emit_byte (mb, CEE_LDARG_2);
1947         mono_mb_emit_byte (mb, CEE_LDC_I4_0);
1948         mono_mb_emit_byte (mb, CEE_PREFIX1);
1949         mono_mb_emit_byte (mb, CEE_CGT_UN);
1950         mono_mb_emit_byte (mb, CEE_PREFIX1);
1951         mono_mb_emit_byte (mb, CEE_ENDFILTER);
1952
1953         clause->handler_offset = mb->pos;
1954
1955         /* handler code */
1956         /* store exception */
1957         mono_mb_emit_stloc (mb, 1);
1958         
1959         mono_mb_emit_byte (mb, CEE_LDARG_2);
1960         mono_mb_emit_ldloc (mb, 1);
1961         mono_mb_emit_byte (mb, CEE_STIND_I);
1962
1963         mono_mb_emit_byte (mb, CEE_LEAVE);
1964         mono_mb_emit_i4 (mb, 0);
1965
1966         clause->handler_len = mb->pos - clause->handler_offset;
1967
1968         /* return result */
1969         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1970         mono_mb_emit_ldloc (mb, 0);
1971         mono_mb_emit_byte (mb, CEE_RET);
1972         
1973         res = mono_mb_create_and_cache (cache, method,
1974                                                                                  mb, csig, sig->param_count + 16);
1975         mono_mb_free (mb);
1976
1977         header = ((MonoMethodNormal *)res)->header;
1978         header->num_clauses = 1;
1979         header->clauses = clause;
1980
1981         return res;     
1982 }
1983
1984 /*
1985  * generates IL code to call managed methods from unmanaged code 
1986  */
1987 MonoMethod *
1988 mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this, MonoMarshalSpec **mspecs)
1989 {
1990         MonoMethodSignature *sig, *csig;
1991         MonoMethodBuilder *mb;
1992         MonoClass *klass;
1993         MonoMethod *res;
1994         GHashTable *cache;
1995         int i, pos, sigsize, *tmp_locals;
1996         static MonoMethodSignature *alloc_sig = NULL;
1997         int retobj_var = 0;
1998
1999         g_assert (method != NULL);
2000         g_assert (!method->signature->pinvoke);
2001
2002         cache = method->klass->image->managed_wrapper_cache;
2003         if (!this && (res = mono_marshal_find_in_cache (cache, method)))
2004                 return res;
2005
2006         /* Under MS, the allocation should be done using CoTaskMemAlloc */
2007         if (!alloc_sig) {
2008                 alloc_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
2009                 alloc_sig->params [0] = &mono_defaults.int_class->byval_arg;
2010                 alloc_sig->ret = &mono_defaults.int_class->byval_arg;
2011                 alloc_sig->pinvoke = 1;
2012         }
2013
2014         if (this) {
2015                 /* fime: howto free that memory ? */
2016         }
2017
2018         sig = method->signature;
2019
2020         mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_NATIVE_TO_MANAGED);
2021
2022         /* allocate local 0 (pointer) src_ptr */
2023         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2024         /* allocate local 1 (pointer) dst_ptr */
2025         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2026         /* allocate local 2 (boolean) delete_old */
2027         mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2028
2029         if (!MONO_TYPE_IS_VOID(sig->ret)) {
2030                 /* allocate local 3 to store the return value */
2031                 mono_mb_add_local (mb, sig->ret);
2032         }
2033
2034         mono_mb_emit_byte (mb, CEE_LDNULL);
2035         mono_mb_emit_byte (mb, CEE_STLOC_2);
2036
2037         /* we copy the signature, so that we can modify it */
2038         sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
2039         csig = g_memdup (sig, sigsize);
2040         csig->hasthis = 0;
2041         csig->pinvoke = 1;
2042
2043 #ifdef PLATFORM_WIN32
2044         /* 
2045          * Under windows, delegates passed to native code must use the STDCALL
2046          * calling convention.
2047          */
2048         csig->call_convention = MONO_CALL_STDCALL;
2049 #endif
2050
2051         /* fixme: howto handle this ? */
2052         if (sig->hasthis) {
2053
2054                 if (this) {
2055                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2056                         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
2057                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, this));
2058
2059
2060                 } else {
2061                         /* fixme: */
2062                         g_assert_not_reached ();
2063                 }
2064         } 
2065
2066
2067         /* we first do all conversions */
2068         tmp_locals = alloca (sizeof (int) * sig->param_count);
2069         for (i = 0; i < sig->param_count; i ++) {
2070                 MonoType *t = sig->params [i];
2071                 MonoMarshalSpec *spec = mspecs [i + 1];
2072
2073                 tmp_locals [i] = 0;
2074                 
2075                 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
2076                         MonoType *mtype;
2077                         MonoClass *mklass;
2078                         MonoMethod *marshal_native_to_managed;
2079                         MonoMethod *get_instance;
2080
2081                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
2082                         g_assert (mtype != NULL);
2083                         mklass = mono_class_from_mono_type (mtype);
2084                         g_assert (mklass != NULL);
2085
2086                         marshal_native_to_managed = mono_find_method_by_name (mklass, "MarshalNativeToManaged", 1);
2087                         g_assert (marshal_native_to_managed);
2088                         get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
2089                         g_assert (get_instance);
2090                         
2091                         switch (t->type) {
2092                         case MONO_TYPE_CLASS:
2093                         case MONO_TYPE_OBJECT:
2094                         case MONO_TYPE_STRING:
2095                         case MONO_TYPE_ARRAY:
2096                         case MONO_TYPE_SZARRAY:
2097                                 if (t->byref)
2098                                         break;
2099
2100                                 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2101
2102                                 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
2103
2104                                 mono_mb_emit_byte (mb, CEE_CALL);
2105                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
2106                                 
2107                                 mono_mb_emit_ldarg (mb, i);
2108                                 
2109                                 mono_mb_emit_byte (mb, CEE_CALLVIRT);
2110                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_native_to_managed));
2111                                 
2112                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
2113                                 break;
2114                         default:
2115                                 g_warning ("custom marshalling of type %x is currently not supported", t->type);
2116                                 g_assert_not_reached ();
2117                                 break;
2118                         }
2119                         continue;
2120                 }
2121
2122                 switch (t->type) {
2123                 case MONO_TYPE_CLASS: {
2124                         klass = t->data.klass;
2125
2126                         /* FIXME: Raise a MarshalDirectiveException here */
2127                         g_assert ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT);
2128
2129                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2130
2131                         if (t->attrs & PARAM_ATTRIBUTE_OUT) {
2132                                 mono_mb_emit_byte (mb, CEE_LDNULL);
2133                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
2134                                 break;
2135                         }
2136
2137                         /* Set src */
2138                         mono_mb_emit_ldarg (mb, i);
2139                         if (t->byref) {
2140                                 int pos2;
2141
2142                                 /* Check for NULL and raise an exception */
2143                                 mono_mb_emit_byte (mb, CEE_BRTRUE);
2144                                 pos2 = mb->pos;
2145                                 mono_mb_emit_i4 (mb, 0);
2146
2147                                 mono_mb_emit_exception (mb, "ArgumentNullException", NULL);
2148
2149                                 mono_mb_patch_addr (mb, pos2, mb->pos - (pos2 + 4));
2150                                 mono_mb_emit_ldarg (mb, i);
2151                                 mono_mb_emit_byte (mb, CEE_LDIND_I);
2152                         }                               
2153
2154                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2155
2156                         mono_mb_emit_byte (mb, CEE_LDC_I4_0);
2157                         mono_mb_emit_stloc (mb, tmp_locals [i]);
2158
2159                         mono_mb_emit_byte (mb, CEE_LDLOC_0);
2160                         mono_mb_emit_byte (mb, CEE_BRFALSE);
2161                         pos = mb->pos;
2162                         mono_mb_emit_i4 (mb, 0);
2163
2164                         /* Create and set dst */
2165                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2166                         mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);        
2167                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2168                         mono_mb_emit_stloc (mb, tmp_locals [i]);
2169                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
2170                         mono_mb_emit_icon (mb, sizeof (MonoObject));
2171                         mono_mb_emit_byte (mb, CEE_ADD);
2172                         mono_mb_emit_byte (mb, CEE_STLOC_1); 
2173
2174                         /* emit valuetype conversion code */
2175                         emit_struct_conv (mb, klass, TRUE);
2176
2177                         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2178                         break;
2179                 }
2180                 case MONO_TYPE_VALUETYPE:
2181                         
2182                         klass = sig->params [i]->data.klass;
2183                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2184                             klass->blittable || klass->enumtype)
2185                                 break;
2186
2187                         tmp_locals [i] = mono_mb_add_local (mb, &klass->byval_arg);
2188
2189                         if (t->byref) 
2190                                 mono_mb_emit_ldarg (mb, i);
2191                         else
2192                                 mono_mb_emit_ldarg_addr (mb, i);
2193                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2194
2195                         if (t->byref) {
2196                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
2197                                 mono_mb_emit_byte (mb, CEE_BRFALSE);
2198                                 pos = mb->pos;
2199                                 mono_mb_emit_i4 (mb, 0);
2200                         }                       
2201
2202                         mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2203                         mono_mb_emit_byte (mb, CEE_STLOC_1);
2204
2205                         /* emit valuetype convnversion code code */
2206                         emit_struct_conv (mb, klass, TRUE);
2207
2208                         if (t->byref)
2209                                 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2210                         break;
2211                 case MONO_TYPE_STRING:
2212                         if (t->byref)
2213                                 continue;
2214
2215                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2216                         csig->params [i] = &mono_defaults.int_class->byval_arg;
2217
2218                         mono_mb_emit_ldarg (mb, i);
2219                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2220                         mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2221                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
2222                         mono_mb_emit_stloc (mb, tmp_locals [i]);
2223                         break;  
2224                 case MONO_TYPE_ARRAY:
2225                 case MONO_TYPE_SZARRAY:
2226                         if (t->byref)
2227                                 continue;
2228
2229                         klass = mono_class_from_mono_type (t);
2230
2231                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
2232                         csig->params [i] = &mono_defaults.int_class->byval_arg;
2233
2234                         g_warning ("array marshaling not implemented");
2235                         g_assert_not_reached ();
2236                         break;
2237                 }
2238         }
2239
2240         for (i = 0; i < sig->param_count; i++) {
2241                 MonoType *t = sig->params [i];
2242
2243                 switch (t->type) {
2244                 case MONO_TYPE_BOOLEAN:
2245                 case MONO_TYPE_I1:
2246                 case MONO_TYPE_U1:
2247                 case MONO_TYPE_I2:
2248                 case MONO_TYPE_U2:
2249                 case MONO_TYPE_I4:
2250                 case MONO_TYPE_U4:
2251                 case MONO_TYPE_I:
2252                 case MONO_TYPE_U:
2253                 case MONO_TYPE_PTR:
2254                 case MONO_TYPE_R4:
2255                 case MONO_TYPE_R8:
2256                 case MONO_TYPE_I8:
2257                 case MONO_TYPE_U8:
2258                         mono_mb_emit_ldarg (mb, i);
2259                         break;
2260                 case MONO_TYPE_STRING:
2261                         if (t->byref) {
2262                                 mono_mb_emit_ldarg (mb, i);
2263                         } else {
2264                                 g_assert (tmp_locals [i]);
2265                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2266                         }
2267                         break;  
2268                 case MONO_TYPE_CLASS:  
2269                         if (t->byref)
2270                                 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2271                         else
2272                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2273                         break;
2274                 case MONO_TYPE_ARRAY:
2275                 case MONO_TYPE_SZARRAY:
2276                 case MONO_TYPE_OBJECT:
2277                         if (tmp_locals [i])
2278                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2279                         else
2280                                 mono_mb_emit_ldarg (mb, i);
2281                         break;
2282                 case MONO_TYPE_VALUETYPE:
2283                         klass = sig->params [i]->data.klass;
2284                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2285                             klass->blittable || klass->enumtype) {
2286                                 mono_mb_emit_ldarg (mb, i);
2287                                 break;
2288                         }
2289
2290                         g_assert (tmp_locals [i]);
2291                         if (t->byref)
2292                                 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
2293                         else
2294                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
2295                         break;
2296                 default:
2297                         g_warning ("type 0x%02x unknown", t->type);     
2298                         g_assert_not_reached ();
2299                 }
2300         }
2301
2302         mono_mb_emit_managed_call (mb, method, NULL);
2303
2304         if (!sig->ret->byref) { 
2305                 switch (sig->ret->type) {
2306                 case MONO_TYPE_VOID:
2307                         break;
2308                 case MONO_TYPE_BOOLEAN:
2309                 case MONO_TYPE_I1:
2310                 case MONO_TYPE_U1:
2311                 case MONO_TYPE_I2:
2312                 case MONO_TYPE_U2:
2313                 case MONO_TYPE_I4:
2314                 case MONO_TYPE_U4:
2315                 case MONO_TYPE_I:
2316                 case MONO_TYPE_U:
2317                 case MONO_TYPE_PTR:
2318                 case MONO_TYPE_R4:
2319                 case MONO_TYPE_R8:
2320                 case MONO_TYPE_I8:
2321                 case MONO_TYPE_U8:
2322                 case MONO_TYPE_OBJECT:
2323                         mono_mb_emit_byte (mb, CEE_STLOC_3);
2324                         break;
2325                 case MONO_TYPE_STRING:          
2326                         csig->ret = &mono_defaults.int_class->byval_arg;
2327
2328                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2329                         mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
2330                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
2331                         mono_mb_emit_byte (mb, CEE_STLOC_3);
2332                         break;
2333                 case MONO_TYPE_VALUETYPE:
2334                         klass = sig->ret->data.klass;
2335                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
2336                             klass->blittable || klass->enumtype)
2337                                 break;
2338                         
2339                         /* load pointer to returned value type */
2340                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2341                         mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
2342                         
2343                         /* store the address of the source into local variable 0 */
2344                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2345                         /* allocate space for the native struct and
2346                          * store the address into dst_ptr */
2347                         retobj_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2348                         g_assert (retobj_var);
2349                         mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2350                         mono_mb_emit_native_call (mb, alloc_sig, mono_marshal_alloc);
2351                         mono_mb_emit_byte (mb, CEE_STLOC_1);
2352                         mono_mb_emit_byte (mb, CEE_LDLOC_1);
2353                         mono_mb_emit_stloc (mb, retobj_var);
2354
2355                         /* emit valuetype conversion code */
2356                         emit_struct_conv (mb, klass, FALSE);
2357                         break;
2358                 case MONO_TYPE_CLASS: {
2359                         int pos2;
2360
2361                         klass = sig->ret->data.klass;
2362
2363                         /* FIXME: Raise a MarshalDirectiveException here */
2364                         g_assert ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT);
2365
2366                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2367                         /* Check for null */
2368                         mono_mb_emit_byte (mb, CEE_LDLOC_0);
2369                         pos = mono_mb_emit_branch (mb, CEE_BRTRUE);
2370                         mono_mb_emit_byte (mb, CEE_LDNULL);
2371                         mono_mb_emit_byte (mb, CEE_STLOC_3);
2372                         pos2 = mono_mb_emit_branch (mb, CEE_BR);
2373
2374                         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2375
2376                         /* Set src */
2377                         mono_mb_emit_byte (mb, CEE_LDLOC_0);
2378                         mono_mb_emit_icon (mb, sizeof (MonoObject));
2379                         mono_mb_emit_byte (mb, CEE_ADD);
2380                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2381
2382                         /* Allocate and set dest */
2383                         mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2384                         mono_mb_emit_native_call (mb, alloc_sig, mono_marshal_alloc);
2385                         mono_mb_emit_byte (mb, CEE_DUP);
2386                         mono_mb_emit_byte (mb, CEE_STLOC_1);
2387                         mono_mb_emit_byte (mb, CEE_STLOC_3);
2388
2389                         emit_struct_conv (mb, klass, FALSE);
2390
2391                         mono_mb_patch_addr (mb, pos2, mb->pos - (pos2 + 4));
2392                         break;
2393                 }
2394                 default:
2395                         g_warning ("return type 0x%02x unknown", sig->ret->type);       
2396                         g_assert_not_reached ();
2397                 }
2398         } else {
2399                 mono_mb_emit_byte (mb, CEE_STLOC_3);
2400         }
2401
2402         /* Convert byref arguments back */
2403         for (i = 0; i < sig->param_count; i ++) {
2404                 MonoType *t = sig->params [i];
2405
2406                 if (!t->byref)
2407                         break;
2408
2409                 switch (t->type) {
2410                 case MONO_TYPE_CLASS: {
2411                         int pos2;
2412
2413                         klass = t->data.klass;
2414
2415                         /* Check for null */
2416                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
2417                         pos = mono_mb_emit_branch (mb, CEE_BRTRUE);
2418                         mono_mb_emit_ldarg (mb, i);
2419                         mono_mb_emit_byte (mb, CEE_LDC_I4_0);
2420                         mono_mb_emit_byte (mb, CEE_STIND_I);
2421                         pos2 = mono_mb_emit_branch (mb, CEE_BR);
2422                         
2423                         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));                      
2424                         
2425                         /* Set src */
2426                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
2427                         mono_mb_emit_icon (mb, sizeof (MonoObject));
2428                         mono_mb_emit_byte (mb, CEE_ADD);
2429                         mono_mb_emit_byte (mb, CEE_STLOC_0);
2430
2431                         /* Allocate and set dest */
2432                         mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
2433                         mono_mb_emit_native_call (mb, alloc_sig, mono_marshal_alloc);
2434                         mono_mb_emit_byte (mb, CEE_STLOC_1);
2435
2436                         /* Update argument pointer */
2437                         mono_mb_emit_ldarg (mb, i);
2438                         mono_mb_emit_byte (mb, CEE_LDLOC_1);
2439                         mono_mb_emit_byte (mb, CEE_STIND_I);
2440
2441                         /* emit valuetype conversion code */
2442                         emit_struct_conv (mb, klass, FALSE);
2443
2444                         mono_mb_patch_addr (mb, pos2, mb->pos - (pos2 + 4));
2445                         break;
2446                 }
2447                 }
2448         }
2449
2450         if (retobj_var) {
2451                 mono_mb_emit_ldloc (mb, retobj_var);
2452                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2453                 mono_mb_emit_byte (mb, CEE_MONO_RETOBJ);
2454                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2455         }
2456         else {
2457                 if (!MONO_TYPE_IS_VOID(sig->ret))
2458                         mono_mb_emit_byte (mb, CEE_LDLOC_3);
2459                 mono_mb_emit_byte (mb, CEE_RET);
2460         }
2461
2462         if (!this)
2463                 res = mono_mb_create_and_cache (cache, method,
2464                                                                                          mb, csig, sig->param_count + 16);
2465         else
2466                 res = mono_mb_create_method (mb, csig, sig->param_count + 16);
2467         mono_mb_free (mb);
2468
2469         //printf ("CODE FOR %s: \n%s.\n", mono_method_full_name (res, TRUE), mono_disasm_code (0, res, ((MonoMethodNormal*)res)->header->code, ((MonoMethodNormal*)res)->header->code + ((MonoMethodNormal*)res)->header->code_size));
2470
2471         return res;
2472 }
2473
2474 /*
2475  * mono_marshal_get_ldfld_wrapper:
2476  * @type: the type of the field
2477  *
2478  * This method generates a function which can be use to load a field with type
2479  * @type from an object. The generated function has the following signature:
2480  * <@type> ldfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset)
2481  */
2482 MonoMethod *
2483 mono_marshal_get_ldfld_wrapper (MonoType *type)
2484 {
2485         MonoMethodSignature *sig, *csig;
2486         MonoMethodBuilder *mb;
2487         MonoMethod *res;
2488         MonoClass *klass;
2489         static GHashTable *ldfld_hash = NULL; 
2490         char *name;
2491         int t, pos0, pos1;
2492
2493         t = type->type;
2494
2495         if (!type->byref) {
2496                 if (type->type == MONO_TYPE_SZARRAY) {
2497                         klass = mono_defaults.array_class;
2498                 } else if (type->type == MONO_TYPE_VALUETYPE) {
2499                         klass = type->data.klass;
2500                         if (klass->enumtype) {
2501                                 t = klass->enum_basetype->type;
2502                                 klass = mono_class_from_mono_type (klass->enum_basetype);
2503                         }
2504                 } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
2505                            t == MONO_TYPE_CLASS) { 
2506                         klass = mono_defaults.object_class;
2507                 } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
2508                         klass = mono_defaults.int_class;
2509                 } else {
2510                         klass = mono_class_from_mono_type (type);                       
2511                 }
2512         } else {
2513                 klass = mono_defaults.int_class;
2514         }
2515
2516         EnterCriticalSection (&marshal_mutex);
2517         if (!ldfld_hash) 
2518                 ldfld_hash = g_hash_table_new (NULL, NULL);
2519         res = g_hash_table_lookup (ldfld_hash, klass);
2520         LeaveCriticalSection (&marshal_mutex);
2521         if (res)
2522                 return res;
2523
2524         name = g_strdup_printf ("__ldfld_wrapper_%s.%s", klass->name_space, klass->name); 
2525         mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_LDFLD);
2526         g_free (name);
2527
2528         mb->method->save_lmf = 1;
2529
2530         sig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
2531         sig->params [0] = &mono_defaults.object_class->byval_arg;
2532         sig->params [1] = &mono_defaults.int_class->byval_arg;
2533         sig->params [2] = &mono_defaults.int_class->byval_arg;
2534         sig->params [3] = &mono_defaults.int_class->byval_arg;
2535         sig->ret = &klass->byval_arg;
2536
2537         mono_mb_emit_ldarg (mb, 0);
2538         pos0 = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
2539
2540         mono_mb_emit_ldarg (mb, 0);
2541         mono_mb_emit_ldarg (mb, 1);
2542         mono_mb_emit_ldarg (mb, 2);
2543
2544         csig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
2545         csig->params [0] = &mono_defaults.object_class->byval_arg;
2546         csig->params [1] = &mono_defaults.int_class->byval_arg;
2547         csig->params [2] = &mono_defaults.int_class->byval_arg;
2548         csig->ret = &klass->this_arg;
2549         csig->pinvoke = 1;
2550
2551         mono_mb_emit_native_call (mb, csig, mono_load_remote_field_new);
2552
2553         if (klass->valuetype) {
2554                 mono_mb_emit_byte (mb, CEE_UNBOX);
2555                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));             
2556                 mono_mb_emit_byte (mb, CEE_BR);
2557                 pos1 = mb->pos;
2558                 mono_mb_emit_i4 (mb, 0);
2559         } else {
2560                 mono_mb_emit_byte (mb, CEE_RET);
2561         }
2562
2563
2564         mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
2565
2566         mono_mb_emit_ldarg (mb, 0);
2567         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2568         mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2569         mono_mb_emit_ldarg (mb, 3);
2570         mono_mb_emit_byte (mb, CEE_ADD);
2571
2572         if (klass->valuetype)
2573                 mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
2574
2575         switch (t) {
2576         case MONO_TYPE_I1:
2577         case MONO_TYPE_U1:
2578         case MONO_TYPE_BOOLEAN:
2579                 mono_mb_emit_byte (mb, CEE_LDIND_I1);
2580                 break;
2581         case MONO_TYPE_CHAR:
2582         case MONO_TYPE_I2:
2583         case MONO_TYPE_U2:
2584                 mono_mb_emit_byte (mb, CEE_LDIND_I2);
2585                 break;
2586         case MONO_TYPE_I4:
2587         case MONO_TYPE_U4:
2588                 mono_mb_emit_byte (mb, CEE_LDIND_I4);
2589                 break;
2590         case MONO_TYPE_I8:
2591         case MONO_TYPE_U8:
2592                 mono_mb_emit_byte (mb, CEE_LDIND_I8);
2593                 break;
2594         case MONO_TYPE_R4:
2595                 mono_mb_emit_byte (mb, CEE_LDIND_R4);
2596                 break;
2597         case MONO_TYPE_R8:
2598                 mono_mb_emit_byte (mb, CEE_LDIND_R8);
2599                 break;
2600         case MONO_TYPE_ARRAY:
2601         case MONO_TYPE_PTR:
2602         case MONO_TYPE_FNPTR:
2603         case MONO_TYPE_SZARRAY:
2604         case MONO_TYPE_OBJECT:
2605         case MONO_TYPE_CLASS:
2606         case MONO_TYPE_STRING:
2607         case MONO_TYPE_I:
2608         case MONO_TYPE_U:
2609                 mono_mb_emit_byte (mb, CEE_LDIND_I);
2610                 break;
2611         case MONO_TYPE_VALUETYPE:
2612                 g_assert (!klass->enumtype);
2613                 mono_mb_emit_byte (mb, CEE_LDOBJ);
2614                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2615                 break;
2616         default:
2617                 g_warning ("type %x not implemented", type->type);
2618                 g_assert_not_reached ();
2619         }
2620
2621         mono_mb_emit_byte (mb, CEE_RET);
2622        
2623         res = mono_mb_create_and_cache (ldfld_hash, klass,
2624                                                                                  mb, sig, sig->param_count + 16);
2625         mono_mb_free (mb);
2626         
2627         return res;
2628 }
2629
2630 /*
2631  * mono_marshal_get_stfld_wrapper:
2632  * @type: the type of the field
2633  *
2634  * This method generates a function which can be use to store a field with type
2635  * @type. The generated function has the following signature:
2636  * void stfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset, <@type> val)
2637  */
2638 MonoMethod *
2639 mono_marshal_get_stfld_wrapper (MonoType *type)
2640 {
2641         MonoMethodSignature *sig, *csig;
2642         MonoMethodBuilder *mb;
2643         MonoMethod *res;
2644         MonoClass *klass;
2645         static GHashTable *stfld_hash = NULL; 
2646         char *name;
2647         int t, pos;
2648
2649         t = type->type;
2650
2651         if (!type->byref) {
2652                 if (type->type == MONO_TYPE_SZARRAY) {
2653                         klass = mono_defaults.array_class;
2654                 } else if (type->type == MONO_TYPE_VALUETYPE) {
2655                         klass = type->data.klass;
2656                         if (klass->enumtype) {
2657                                 t = klass->enum_basetype->type;
2658                                 klass = mono_class_from_mono_type (klass->enum_basetype);
2659                         }
2660                 } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
2661                            t == MONO_TYPE_CLASS) { 
2662                         klass = mono_defaults.object_class;
2663                 } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
2664                         klass = mono_defaults.int_class;
2665                 } else {
2666                         klass = mono_class_from_mono_type (type);                       
2667                 }
2668         } else {
2669                 klass = mono_defaults.int_class;
2670         }
2671
2672         EnterCriticalSection (&marshal_mutex);
2673         if (!stfld_hash) 
2674                 stfld_hash = g_hash_table_new (NULL, NULL);
2675         res = g_hash_table_lookup (stfld_hash, klass);
2676         LeaveCriticalSection (&marshal_mutex);
2677         if (res)
2678                 return res;
2679
2680         name = g_strdup_printf ("__stfld_wrapper_%s.%s", klass->name_space, klass->name); 
2681         mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_STFLD);
2682         g_free (name);
2683
2684         mb->method->save_lmf = 1;
2685
2686         sig = mono_metadata_signature_alloc (mono_defaults.corlib, 5);
2687         sig->params [0] = &mono_defaults.object_class->byval_arg;
2688         sig->params [1] = &mono_defaults.int_class->byval_arg;
2689         sig->params [2] = &mono_defaults.int_class->byval_arg;
2690         sig->params [3] = &mono_defaults.int_class->byval_arg;
2691         sig->params [4] = &klass->byval_arg;
2692         sig->ret = &mono_defaults.void_class->byval_arg;
2693
2694         mono_mb_emit_ldarg (mb, 0);
2695         pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
2696
2697         mono_mb_emit_ldarg (mb, 0);
2698         mono_mb_emit_ldarg (mb, 1);
2699         mono_mb_emit_ldarg (mb, 2);
2700         mono_mb_emit_ldarg (mb, 4);
2701
2702         if (klass->valuetype) {
2703                 mono_mb_emit_byte (mb, CEE_BOX);
2704                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));             
2705         }
2706
2707         csig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
2708         csig->params [0] = &mono_defaults.object_class->byval_arg;
2709         csig->params [1] = &mono_defaults.int_class->byval_arg;
2710         csig->params [2] = &mono_defaults.int_class->byval_arg;
2711         csig->params [3] = &klass->this_arg;
2712         csig->ret = &mono_defaults.void_class->byval_arg;
2713         csig->pinvoke = 1;
2714
2715         mono_mb_emit_native_call (mb, csig, mono_store_remote_field_new);
2716
2717         mono_mb_emit_byte (mb, CEE_RET);
2718
2719         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
2720
2721         mono_mb_emit_ldarg (mb, 0);
2722         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
2723         mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
2724         mono_mb_emit_ldarg (mb, 3);
2725         mono_mb_emit_byte (mb, CEE_ADD);
2726         mono_mb_emit_ldarg (mb, 4);
2727
2728         switch (t) {
2729         case MONO_TYPE_I1:
2730         case MONO_TYPE_U1:
2731         case MONO_TYPE_BOOLEAN:
2732                 mono_mb_emit_byte (mb, CEE_STIND_I1);
2733                 break;
2734         case MONO_TYPE_CHAR:
2735         case MONO_TYPE_I2:
2736         case MONO_TYPE_U2:
2737                 mono_mb_emit_byte (mb, CEE_STIND_I2);
2738                 break;
2739         case MONO_TYPE_I4:
2740         case MONO_TYPE_U4:
2741                 mono_mb_emit_byte (mb, CEE_STIND_I4);
2742                 break;
2743         case MONO_TYPE_I8:
2744         case MONO_TYPE_U8:
2745                 mono_mb_emit_byte (mb, CEE_STIND_I8);
2746                 break;
2747         case MONO_TYPE_R4:
2748                 mono_mb_emit_byte (mb, CEE_STIND_R4);
2749                 break;
2750         case MONO_TYPE_R8:
2751                 mono_mb_emit_byte (mb, CEE_STIND_R8);
2752                 break;
2753         case MONO_TYPE_ARRAY:
2754         case MONO_TYPE_PTR:
2755         case MONO_TYPE_FNPTR:
2756         case MONO_TYPE_SZARRAY:
2757         case MONO_TYPE_OBJECT:
2758         case MONO_TYPE_CLASS:
2759         case MONO_TYPE_STRING:
2760         case MONO_TYPE_I:
2761         case MONO_TYPE_U:
2762                 mono_mb_emit_byte (mb, CEE_STIND_I);
2763                 break;
2764         case MONO_TYPE_VALUETYPE:
2765                 g_assert (!klass->enumtype);
2766                 mono_mb_emit_byte (mb, CEE_STOBJ);
2767                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
2768                 break;
2769         default:
2770                 g_warning ("type %x not implemented", type->type);
2771                 g_assert_not_reached ();
2772         }
2773
2774         mono_mb_emit_byte (mb, CEE_RET);
2775        
2776         res = mono_mb_create_and_cache (stfld_hash, klass,
2777                                                                         mb, sig, sig->param_count + 16);
2778         mono_mb_free (mb);
2779         
2780         return res;
2781 }
2782
2783 /*
2784  * generates IL code for the icall wrapper (the generated method
2785  * calls the unmanaged code in func)
2786  */
2787 MonoMethod *
2788 mono_marshal_get_icall_wrapper (MonoMethodSignature *sig, const char *name, gconstpointer func)
2789 {
2790         MonoMethodSignature *csig;
2791         MonoMethodBuilder *mb;
2792         MonoMethod *res;
2793         int i, sigsize;
2794
2795         g_assert (sig->pinvoke);
2796
2797         mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_MANAGED_TO_NATIVE);
2798
2799         mb->method->save_lmf = 1;
2800
2801         /* we copy the signature, so that we can modify it */
2802         sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
2803
2804         if (sig->hasthis)
2805                 mono_mb_emit_byte (mb, CEE_LDARG_0);
2806
2807         for (i = 0; i < sig->param_count; i++)
2808                 mono_mb_emit_ldarg (mb, i + sig->hasthis);
2809
2810         mono_mb_emit_native_call (mb, sig, (gpointer) func);
2811
2812         mono_mb_emit_byte (mb, CEE_RET);
2813
2814         csig = g_memdup (sig, sigsize);
2815         csig->pinvoke = 0;
2816
2817         res = mono_mb_create_method (mb, csig, csig->param_count + 16);
2818         mono_mb_free (mb);
2819         
2820         return res;
2821 }
2822
2823 /**
2824  * mono_marshal_get_native_wrapper:
2825  * @method: The MonoMethod to wrap.
2826  *
2827  * generates IL code for the pinvoke wrapper (the generated method
2828  * calls the unmanaged code in method->addr)
2829  */
2830 MonoMethod *
2831 mono_marshal_get_native_wrapper (MonoMethod *method)
2832 {
2833         MonoMethodSignature *sig, *csig;
2834         MonoMethodPInvoke *piinfo;
2835         MonoMethodBuilder *mb;
2836         MonoMarshalSpec **mspecs;
2837         MonoMethod *res;
2838         GHashTable *cache;
2839         MonoClass *klass;
2840         gboolean pinvoke = FALSE;
2841         int i, pos, argnum, *tmp_locals;
2842         int type, sigsize;
2843         const char *exc_class = "MissingMethodException";
2844         const char *exc_arg = NULL;
2845
2846         g_assert (method != NULL);
2847         g_assert (method->signature->pinvoke);
2848
2849         cache = method->klass->image->native_wrapper_cache;
2850         if ((res = mono_marshal_find_in_cache (cache, method)))
2851                 return res;
2852
2853         sig = method->signature;
2854         sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
2855
2856         if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
2857             (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2858                 pinvoke = TRUE;
2859
2860         if (!method->addr) {
2861                 if (pinvoke)
2862                         mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
2863                 else
2864                         method->addr = mono_lookup_internal_call (method);
2865         }
2866
2867         mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_MANAGED_TO_NATIVE);
2868
2869         mb->method->save_lmf = 1;
2870
2871         piinfo = (MonoMethodPInvoke *)method;
2872
2873         if (!method->addr) {
2874                 mono_mb_emit_exception (mb, exc_class, exc_arg);
2875                 csig = g_memdup (sig, sigsize);
2876                 csig->pinvoke = 0;
2877                 res = mono_mb_create_and_cache (cache, method,
2878                                                                                 mb, csig, csig->param_count + 16);
2879                 mono_mb_free (mb);
2880                 return res;
2881         }
2882
2883         /* internal calls: we simply push all arguments and call the method (no conversions) */
2884         if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
2885
2886                 /* hack - string constructors returns a value */
2887                 if (method->string_ctor) {
2888                         csig = g_memdup (sig, sigsize);
2889                         csig->ret = &mono_defaults.string_class->byval_arg;
2890                 } else
2891                         csig = sig;
2892
2893                 if (sig->hasthis)
2894                         mono_mb_emit_byte (mb, CEE_LDARG_0);
2895
2896                 for (i = 0; i < sig->param_count; i++)
2897                         mono_mb_emit_ldarg (mb, i + sig->hasthis);
2898
2899                 g_assert (method->addr);
2900                 mono_mb_emit_native_call (mb, csig, method->addr);
2901
2902                 mono_mb_emit_byte (mb, CEE_RET);
2903
2904                 csig = g_memdup (csig, sigsize);
2905                 csig->pinvoke = 0;
2906                 res = mono_mb_create_and_cache (cache, method,
2907                                                                                 mb, csig, csig->param_count + 16);
2908                 mono_mb_free (mb);
2909                 return res;
2910         }
2911
2912         g_assert (pinvoke);
2913
2914         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
2915         mono_method_get_marshal_info (method, mspecs);
2916
2917         /* pinvoke: we need to convert the arguments if necessary */
2918
2919         /* we copy the signature, so that we can set pinvoke to 0 */
2920         csig = g_memdup (sig, sigsize);
2921         csig->pinvoke = 1;
2922
2923         /* we allocate local for use with emit_struct_conv() */
2924         /* allocate local 0 (pointer) src_ptr */
2925         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2926         /* allocate local 1 (pointer) dst_ptr */
2927         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2928         /* allocate local 2 (boolean) delete_old */
2929         mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
2930
2931         /* delete_old = FALSE */
2932         mono_mb_emit_icon (mb, 0);
2933         mono_mb_emit_byte (mb, CEE_STLOC_2);
2934
2935         if (!MONO_TYPE_IS_VOID(sig->ret)) {
2936                 /* allocate local 3 to store the return value */
2937                 mono_mb_add_local (mb, sig->ret);
2938         }
2939
2940         /* we first do all conversions */
2941         tmp_locals = alloca (sizeof (int) * sig->param_count);
2942
2943         for (i = 0; i < sig->param_count; i ++) {
2944                 MonoType *t = sig->params [i];
2945                 MonoMarshalSpec *spec = mspecs [i + 1];
2946
2947                 argnum = i + sig->hasthis;
2948                 tmp_locals [i] = 0;
2949
2950                 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
2951                         MonoType *mtype;
2952                         MonoClass *mklass;
2953                         MonoMethod *marshal_managed_to_native;
2954                         MonoMethod *get_instance;
2955
2956                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
2957                         g_assert (mtype != NULL);
2958                         mklass = mono_class_from_mono_type (mtype);
2959                         g_assert (mklass != NULL);
2960
2961                         marshal_managed_to_native = mono_find_method_by_name (mklass, "MarshalManagedToNative", 1);
2962                         g_assert (marshal_managed_to_native);
2963                         get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
2964                         g_assert (get_instance);
2965                         
2966                         switch (t->type) {
2967                         case MONO_TYPE_CLASS:
2968                         case MONO_TYPE_OBJECT:
2969                         case MONO_TYPE_STRING:
2970                         case MONO_TYPE_ARRAY:
2971                         case MONO_TYPE_SZARRAY:
2972                                 if (t->byref)
2973                                         break;
2974
2975                                 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
2976
2977                                 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
2978
2979                                 mono_mb_emit_byte (mb, CEE_CALL);
2980                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
2981                                 
2982                                 mono_mb_emit_ldarg (mb, argnum);
2983                                 
2984                                 mono_mb_emit_byte (mb, CEE_CALLVIRT);
2985                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_managed_to_native));
2986                                 
2987                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
2988                                 break;
2989                         default:
2990                                 g_warning ("custom marshalling of type %x is currently not supported", t->type);
2991                                 g_assert_not_reached ();
2992                                 break;
2993                         }
2994                         continue;
2995                 }
2996                 
2997
2998                 switch (t->type) {
2999                 case MONO_TYPE_VALUETYPE:                       
3000                         klass = t->data.klass;
3001
3002                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3003                             klass->blittable || klass->enumtype)
3004                                 break;
3005
3006                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3007                         
3008                         /* store the address of the source into local variable 0 */
3009                         if (t->byref)
3010                                 mono_mb_emit_ldarg (mb, argnum);
3011                         else
3012                                 mono_mb_emit_ldarg_addr (mb, argnum);
3013
3014                         mono_mb_emit_byte (mb, CEE_STLOC_0);
3015                         
3016                         /* allocate space for the native struct and
3017                          * store the address into local variable 1 (dest) */
3018                         mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
3019                         mono_mb_emit_byte (mb, CEE_PREFIX1);
3020                         mono_mb_emit_byte (mb, CEE_LOCALLOC);
3021                         mono_mb_emit_stloc (mb, tmp_locals [i]);
3022
3023                         if (t->byref) {
3024                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3025                                 mono_mb_emit_byte (mb, CEE_BRFALSE);
3026                                 pos = mb->pos;
3027                                 mono_mb_emit_i4 (mb, 0);
3028                         }
3029
3030                         /* set dst_ptr */
3031                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
3032                         mono_mb_emit_byte (mb, CEE_STLOC_1);
3033
3034                         /* emit valuetype conversion code */
3035                         emit_struct_conv (mb, klass, FALSE);
3036                         
3037                         if (t->byref)
3038                                 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3039                         break;
3040                 case MONO_TYPE_STRING:
3041                         csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3042                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3043
3044                         if (t->byref) {
3045                                 if (t->attrs & PARAM_ATTRIBUTE_OUT)
3046                                         break;
3047
3048                                 mono_mb_emit_ldarg (mb, argnum);
3049                                 mono_mb_emit_byte (mb, CEE_LDIND_I);                            
3050                         } else {
3051                                 mono_mb_emit_ldarg (mb, argnum);
3052                         }
3053
3054                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3055                         mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3056
3057                         if (spec) {
3058                                 switch (spec->native) {
3059                                 case MONO_NATIVE_LPWSTR:
3060                                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPWSTR);
3061                                         break;
3062                                 case MONO_NATIVE_LPSTR:
3063                                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
3064                                         break;
3065                                 default: {
3066                                         char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", spec->native);
3067                                         MonoException *exc = mono_get_exception_not_implemented (msg);
3068                                         g_warning (msg);
3069                                         g_free (msg);
3070                                         mono_raise_exception (exc);
3071                                 }
3072                                 }
3073                         } else {
3074                                 switch (piinfo->piflags & PINVOKE_ATTRIBUTE_CHAR_SET_MASK) {
3075                                 case PINVOKE_ATTRIBUTE_CHAR_SET_ANSI:
3076                                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
3077                                         break;
3078                                 case PINVOKE_ATTRIBUTE_CHAR_SET_UNICODE:
3079                                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPWSTR);
3080                                         break;
3081                                 case PINVOKE_ATTRIBUTE_CHAR_SET_AUTO:
3082                                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPTSTR);
3083                                         break;
3084                                 default:
3085                                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
3086                                         break;                                  
3087                                 }
3088                         }
3089
3090                         mono_mb_emit_stloc (mb, tmp_locals [i]);
3091                         break;
3092                 case MONO_TYPE_CLASS:
3093                 case MONO_TYPE_OBJECT:
3094                         klass = t->data.klass;
3095
3096                         csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3097                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3098
3099                         if (klass->delegate) {
3100                                 g_assert (!t->byref);
3101                                 mono_mb_emit_ldarg (mb, argnum);
3102                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3103                                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3104                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_DEL_FTN);
3105                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
3106                         } else if (klass == mono_defaults.stringbuilder_class) {
3107                                 g_assert (!t->byref);
3108                                 mono_mb_emit_ldarg (mb, argnum);
3109                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3110                                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3111                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_SB_LPSTR);
3112                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
3113                         } else {
3114                                 mono_mb_emit_byte (mb, CEE_LDNULL);
3115                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
3116
3117                                 if (t->byref) {
3118                                         /* we dont need any conversions for out parameters */
3119                                         if (t->attrs & PARAM_ATTRIBUTE_OUT)
3120                                                 break;
3121
3122                                         mono_mb_emit_ldarg (mb, argnum);                                
3123                                         mono_mb_emit_byte (mb, CEE_LDIND_I);
3124
3125                                 } else {
3126                                         mono_mb_emit_ldarg (mb, argnum);
3127                                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3128                                         mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
3129                                 }
3130                                 
3131                                 /* store the address of the source into local variable 0 */
3132                                 mono_mb_emit_byte (mb, CEE_STLOC_0);
3133                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3134                                 mono_mb_emit_byte (mb, CEE_BRFALSE);
3135                                 pos = mb->pos;
3136                                 mono_mb_emit_i4 (mb, 0);
3137
3138                                 /* allocate space for the native struct and store the address */
3139                                 mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
3140                                 mono_mb_emit_byte (mb, CEE_PREFIX1);
3141                                 mono_mb_emit_byte (mb, CEE_LOCALLOC);
3142                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
3143                                 
3144                                 /* set the src_ptr */
3145                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3146                                 mono_mb_emit_icon (mb, sizeof (MonoObject));
3147                                 mono_mb_emit_byte (mb, CEE_ADD);
3148                                 mono_mb_emit_byte (mb, CEE_STLOC_0);
3149
3150                                 /* set dst_ptr */
3151                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3152                                 mono_mb_emit_byte (mb, CEE_STLOC_1);
3153
3154                                 /* emit valuetype conversion code */
3155                                 emit_struct_conv (mb, klass, FALSE);
3156
3157                                 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3158                         }
3159
3160                         break;
3161                 case MONO_TYPE_ARRAY:
3162                 case MONO_TYPE_SZARRAY:
3163                         if (t->byref)
3164                                 continue;
3165
3166                         klass = mono_class_from_mono_type (t);
3167
3168                         csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3169                         tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3170
3171                         if (klass->element_class == mono_defaults.string_class) {
3172                                 mono_mb_emit_ldarg (mb, argnum);
3173                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3174                                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3175
3176                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STRARRAY_STRLPARRAY);
3177                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
3178                         }
3179                         else if (klass->element_class->blittable) {
3180                                 mono_mb_emit_ldarg (mb, argnum);
3181                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3182                                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3183
3184                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_ARRAY_LPARRAY);
3185                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
3186                         }
3187                         else {
3188                                 MonoClass *eklass;
3189                                 guint32 label1, label2, label3;
3190                                 int index_var, dest_ptr;
3191
3192                                 dest_ptr = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3193
3194                                 /* Check null */
3195                                 mono_mb_emit_ldarg (mb, argnum);
3196                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
3197                                 mono_mb_emit_ldarg (mb, argnum);
3198                                 mono_mb_emit_byte (mb, CEE_BRFALSE);
3199                                 label1 = mb->pos;
3200                                 mono_mb_emit_i4 (mb, 0);
3201
3202                                 /* allocate space for the native struct and store the address */
3203                                 eklass = klass->element_class;
3204                                 mono_mb_emit_icon (mb, mono_class_native_size (eklass, NULL));
3205                                 mono_mb_emit_ldarg (mb, argnum);
3206                                 mono_mb_emit_byte (mb, CEE_LDLEN);
3207                                 mono_mb_emit_byte (mb, CEE_MUL);
3208                                 mono_mb_emit_byte (mb, CEE_PREFIX1);
3209                                 mono_mb_emit_byte (mb, CEE_LOCALLOC);
3210                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
3211
3212                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3213                                 mono_mb_emit_stloc (mb, dest_ptr);
3214
3215                                 /* Emit marshalling loop */
3216                                 index_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);                                
3217                                 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
3218                                 mono_mb_emit_stloc (mb, index_var);
3219                                 label2 = mb->pos;
3220                                 mono_mb_emit_ldloc (mb, index_var);
3221                                 mono_mb_emit_ldarg (mb, argnum);
3222                                 mono_mb_emit_byte (mb, CEE_LDLEN);
3223                                 mono_mb_emit_byte (mb, CEE_BGE);
3224                                 label3 = mb->pos;
3225                                 mono_mb_emit_i4 (mb, 0);
3226
3227                                 /* Emit marshalling code */
3228
3229                                 /* set the src_ptr */
3230                                 mono_mb_emit_ldarg (mb, argnum);
3231                                 mono_mb_emit_ldloc (mb, index_var);
3232                                 mono_mb_emit_byte (mb, CEE_LDELEMA);
3233                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eklass));
3234                                 mono_mb_emit_byte (mb, CEE_STLOC_0);
3235
3236                                 /* set dst_ptr */
3237                                 mono_mb_emit_ldloc (mb, dest_ptr);
3238                                 mono_mb_emit_byte (mb, CEE_STLOC_1);
3239
3240                                 /* emit valuetype conversion code */
3241                                 emit_struct_conv (mb, eklass, FALSE);
3242
3243                                 mono_mb_emit_add_to_local (mb, index_var, 1);
3244                                 mono_mb_emit_add_to_local (mb, dest_ptr, mono_class_native_size (eklass, NULL));
3245
3246                                 mono_mb_emit_byte (mb, CEE_BR);
3247                                 mono_mb_emit_i4 (mb, label2 - (mb->pos + 4));
3248
3249                                 mono_mb_patch_addr (mb, label1, mb->pos - (label1 + 4));
3250                                 mono_mb_patch_addr (mb, label3, mb->pos - (label3 + 4));
3251                         }
3252
3253                         break;
3254                 case MONO_TYPE_BOOLEAN: {
3255                         MonoType *local_type;
3256                         int variant_bool = 0;
3257                         if (!t->byref)
3258                                 continue;
3259                         if (spec == NULL) {
3260                                 local_type = &mono_defaults.int32_class->byval_arg;
3261                         } else {
3262                                 switch (spec->native) {
3263                                 case MONO_NATIVE_I1:
3264                                         local_type = &mono_defaults.byte_class->byval_arg;
3265                                         break;
3266                                 case MONO_NATIVE_VARIANTBOOL:
3267                                         local_type = &mono_defaults.int16_class->byval_arg;
3268                                         variant_bool = 1;
3269                                         break;
3270                                 default:
3271                                         g_warning ("marshalling bool as native type %x is currently not supported", spec->native);
3272                                 break;
3273                                 }
3274                         }
3275                         csig->params [argnum] = &mono_defaults.int_class->byval_arg;
3276                         tmp_locals [i] = mono_mb_add_local (mb, local_type);
3277                         mono_mb_emit_ldarg (mb, argnum);
3278                         mono_mb_emit_byte (mb, CEE_LDIND_I1);
3279                         if (variant_bool)
3280                                 mono_mb_emit_byte (mb, CEE_NEG);
3281                         mono_mb_emit_stloc (mb, tmp_locals [i]);
3282                         break;
3283                 }
3284                 }
3285         }
3286
3287         /* push all arguments */
3288
3289         if (sig->hasthis)
3290                 mono_mb_emit_byte (mb, CEE_LDARG_0);
3291
3292         for (i = 0; i < sig->param_count; i++) {
3293                 MonoType *t = sig->params [i];
3294                 
3295                 argnum = i + sig->hasthis;
3296
3297                 switch (t->type) {
3298                 case MONO_TYPE_BOOLEAN:
3299                         if (t->byref) {
3300                                 g_assert (tmp_locals [i]);
3301                                 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
3302                         } else
3303                                 mono_mb_emit_ldarg (mb, argnum);
3304                         break;
3305                 case MONO_TYPE_I1:
3306                 case MONO_TYPE_U1:
3307                 case MONO_TYPE_I2:
3308                 case MONO_TYPE_U2:
3309                 case MONO_TYPE_I4:
3310                 case MONO_TYPE_U4:
3311                 case MONO_TYPE_I:
3312                 case MONO_TYPE_U:
3313                 case MONO_TYPE_PTR:
3314                 case MONO_TYPE_R4:
3315                 case MONO_TYPE_R8:
3316                 case MONO_TYPE_I8:
3317                 case MONO_TYPE_U8:
3318                         mono_mb_emit_ldarg (mb, argnum);
3319                         break;
3320                 case MONO_TYPE_VALUETYPE:
3321                         klass = sig->params [i]->data.klass;
3322                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3323                             klass->blittable || klass->enumtype) {
3324                                 mono_mb_emit_ldarg (mb, argnum);
3325                                 break;
3326                         }                       
3327                         g_assert (tmp_locals [i]);
3328                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
3329                         if (!t->byref) {
3330                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3331                                 mono_mb_emit_byte (mb, CEE_MONO_LDNATIVEOBJ);
3332                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3333                         }
3334                         break;
3335                 case MONO_TYPE_STRING:
3336                 case MONO_TYPE_CLASS:
3337                 case MONO_TYPE_OBJECT:
3338                         g_assert (tmp_locals [i]);
3339                         if (t->byref) 
3340                                 mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
3341                         else
3342                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3343                         break;
3344                 case MONO_TYPE_CHAR:
3345                         /* fixme: dont know how to marshal that. We cant simply
3346                          * convert it to a one byte UTF8 character, because an
3347                          * unicode character may need more that one byte in UTF8 */
3348                         mono_mb_emit_ldarg (mb, argnum);
3349                         break;
3350                 case MONO_TYPE_ARRAY:
3351                 case MONO_TYPE_SZARRAY:
3352                         if (t->byref) {
3353                                 mono_mb_emit_ldarg (mb, argnum);
3354                         } else {
3355                                 g_assert (tmp_locals [i]);
3356                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3357                         }
3358                         break;
3359                 case MONO_TYPE_TYPEDBYREF:
3360                 case MONO_TYPE_FNPTR:
3361                 default:
3362                         g_warning ("type 0x%02x unknown", t->type);     
3363                         g_assert_not_reached ();
3364                 }
3365         }                       
3366
3367         /* call the native method */
3368         mono_mb_emit_native_call (mb, csig, method->addr);
3369
3370         /* Set LastError if needed */
3371         if (piinfo->piflags & PINVOKE_ATTRIBUTE_SUPPORTS_LAST_ERROR) {
3372                 MonoMethodSignature *lasterr_sig;
3373
3374                 lasterr_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
3375                 lasterr_sig->ret = &mono_defaults.void_class->byval_arg;
3376                 lasterr_sig->pinvoke = 1;
3377
3378                 mono_mb_emit_native_call (mb, lasterr_sig, mono_marshal_set_last_error);
3379         }               
3380
3381         /* convert the result */
3382         if (!sig->ret->byref) {
3383                 MonoMarshalSpec *spec = mspecs [0];
3384                 type = sig->ret->type;
3385
3386                 if (spec && spec->native == MONO_NATIVE_CUSTOM) {
3387                         MonoType *mtype;
3388                         MonoClass *mklass;
3389                         MonoMethod *marshal_native_to_managed;
3390                         MonoMethod *get_instance;
3391
3392                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, method->klass->image);
3393                         g_assert (mtype != NULL);
3394                         mklass = mono_class_from_mono_type (mtype);
3395                         g_assert (mklass != NULL);
3396
3397                         marshal_native_to_managed = mono_find_method_by_name (mklass, "MarshalNativeToManaged", 1);
3398                         g_assert (marshal_native_to_managed);
3399                         get_instance = mono_find_method_by_name (mklass, "GetInstance", 1);
3400                         g_assert (get_instance);
3401                         
3402                         switch (type) {
3403                         case MONO_TYPE_CLASS:
3404                         case MONO_TYPE_OBJECT:
3405                         case MONO_TYPE_STRING:
3406                         case MONO_TYPE_ARRAY:
3407                         case MONO_TYPE_SZARRAY:
3408                                 mono_mb_emit_byte (mb, CEE_STLOC_3);
3409
3410                                 mono_mb_emit_ldstr (mb, spec->data.custom_data.cookie);
3411
3412                                 mono_mb_emit_byte (mb, CEE_CALL);
3413                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, get_instance));
3414                                 
3415                                 mono_mb_emit_byte (mb, CEE_LDLOC_3);
3416                                 
3417                                 mono_mb_emit_byte (mb, CEE_CALLVIRT);
3418                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, marshal_native_to_managed));
3419                                 
3420                                 mono_mb_emit_byte (mb, CEE_STLOC_3);
3421                                 break;
3422                         default:
3423                                 g_warning ("custom marshalling of type %x is currently not supported", type);
3424                                 g_assert_not_reached ();
3425                                 break;
3426                         }
3427                 } else {
3428
3429                 handle_enum:
3430                         switch (type) {
3431                         case MONO_TYPE_VOID:
3432                                 break;
3433                         case MONO_TYPE_I1:
3434                         case MONO_TYPE_U1:
3435                         case MONO_TYPE_I2:
3436                         case MONO_TYPE_U2:
3437                         case MONO_TYPE_I4:
3438                         case MONO_TYPE_U4:
3439                         case MONO_TYPE_I:
3440                         case MONO_TYPE_U:
3441                         case MONO_TYPE_PTR:
3442                         case MONO_TYPE_R4:
3443                         case MONO_TYPE_R8:
3444                         case MONO_TYPE_I8:
3445                         case MONO_TYPE_U8:
3446                                 /* no conversions necessary */
3447                                 mono_mb_emit_byte (mb, CEE_STLOC_3);
3448                                 break;
3449                         case MONO_TYPE_BOOLEAN:
3450                                 /* maybe we need to make sure that it fits within 8 bits */
3451                                 mono_mb_emit_byte (mb, CEE_STLOC_3);
3452                                 break;
3453                         case MONO_TYPE_VALUETYPE:
3454                                 klass = sig->ret->data.klass;
3455                                 if (klass->enumtype) {
3456                                         type = sig->ret->data.klass->enum_basetype->type;
3457                                         goto handle_enum;
3458                                 }
3459
3460                                 if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3461                                     klass->blittable) {
3462                                         mono_mb_emit_byte (mb, CEE_STLOC_3);
3463                                         break;
3464                                 }
3465                                 /* load pointer to returned value type */
3466                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3467                                 mono_mb_emit_byte (mb, CEE_MONO_VTADDR);
3468                                 /* store the address of the source into local variable 0 */
3469                                 mono_mb_emit_byte (mb, CEE_STLOC_0);
3470                                 /* set dst_ptr */
3471                                 mono_mb_emit_ldloc_addr (mb, 3);
3472                                 mono_mb_emit_byte (mb, CEE_STLOC_1);
3473                                 
3474                                 /* emit valuetype conversion code */
3475                                 emit_struct_conv (mb, sig->ret->data.klass, TRUE);
3476                                 break;
3477                         case MONO_TYPE_STRING:
3478 #ifdef GTK_SHARP_FIXED
3479                                 mono_mb_emit_byte (mb, CEE_STLOC_0);
3480                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3481 #endif
3482                                 
3483                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3484                                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3485                                 if (spec) {
3486                                         switch (spec->native) {
3487                                         case MONO_NATIVE_LPWSTR:
3488                                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPWSTR_STR);
3489                                                 break;
3490                                         default:
3491                                                 g_warning ("marshalling conversion not implemented");
3492                                                 g_assert_not_reached ();
3493                                         }
3494                                 } else {
3495                                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
3496                                 }
3497                                 mono_mb_emit_byte (mb, CEE_STLOC_3);
3498
3499 #ifdef GTK_SHARP_FIXED
3500                                 /* free the string */
3501                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3502                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3503                                 mono_mb_emit_byte (mb, CEE_MONO_FREE);
3504 #endif
3505                                 break;
3506                         case MONO_TYPE_CLASS:
3507                         case MONO_TYPE_OBJECT:
3508                                 klass = sig->ret->data.klass;
3509
3510                                 /* set src */
3511                                 mono_mb_emit_byte (mb, CEE_STLOC_0);
3512
3513                                 mono_mb_emit_byte (mb, CEE_LDNULL);
3514                                 mono_mb_emit_byte (mb, CEE_STLOC_3);
3515
3516
3517                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
3518                                 mono_mb_emit_byte (mb, CEE_BRFALSE);
3519                                 pos = mb->pos;
3520                                 mono_mb_emit_i4 (mb, 0);
3521
3522                                 /* allocate result object */
3523
3524                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3525                                 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);        
3526                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3527                                 mono_mb_emit_byte (mb, CEE_STLOC_3);
3528                                 
3529                                 /* set dst  */
3530
3531                                 mono_mb_emit_byte (mb, CEE_LDLOC_3);
3532                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3533                                 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
3534                                 mono_mb_emit_icon (mb, sizeof (MonoObject));
3535                                 mono_mb_emit_byte (mb, CEE_ADD);
3536                                 mono_mb_emit_byte (mb, CEE_STLOC_1);
3537                                                         
3538                                 /* emit conversion code */
3539                                 emit_struct_conv (mb, klass, TRUE);
3540
3541                                 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3542                                 break;
3543                         case MONO_TYPE_ARRAY:
3544                         case MONO_TYPE_SZARRAY:
3545                                 /* fixme: we need conversions here */
3546                                 mono_mb_emit_byte (mb, CEE_STLOC_3);
3547                                 break;
3548                         case MONO_TYPE_CHAR:
3549                                 /* fixme: we need conversions here */
3550                                 mono_mb_emit_byte (mb, CEE_STLOC_3);
3551                                 break;
3552                         case MONO_TYPE_TYPEDBYREF:
3553                         case MONO_TYPE_FNPTR:
3554                         default:
3555                                 g_warning ("return type 0x%02x unknown", sig->ret->type);       
3556                                 g_assert_not_reached ();
3557                         }
3558                 }
3559         } else {
3560                 mono_mb_emit_byte (mb, CEE_STLOC_3);
3561         }
3562
3563         /* we need to convert byref arguments back and free string arrays */
3564         for (i = 0; i < sig->param_count; i++) {
3565                 MonoType *t = sig->params [i];
3566                 
3567                 argnum = i + sig->hasthis;
3568
3569                 switch (t->type) {
3570                 case MONO_TYPE_STRING:
3571                         if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT)) {
3572                                 mono_mb_emit_ldarg (mb, argnum);
3573                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3574                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3575                                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
3576                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
3577                                 mono_mb_emit_byte (mb, CEE_STIND_I);            
3578                         } else {
3579                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3580                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3581                                 mono_mb_emit_byte (mb, CEE_MONO_FREE);
3582                         }
3583                         break;
3584                 case MONO_TYPE_CLASS:
3585                 case MONO_TYPE_OBJECT:                  
3586                         if (t->data.klass == mono_defaults.stringbuilder_class) {
3587                                 g_assert (!t->byref);
3588                                 mono_mb_emit_ldarg (mb, argnum);
3589                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3590                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3591                                 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
3592                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_SB);
3593                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3594                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3595                                 mono_mb_emit_byte (mb, CEE_MONO_FREE);
3596                                 break;
3597                         }
3598                         
3599                         if (!(t->byref || (t->attrs & PARAM_ATTRIBUTE_OUT)))
3600                                 continue;
3601
3602                         if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT)) {
3603                                 /* allocate a new object new object */
3604                                 mono_mb_emit_ldarg (mb, argnum);
3605                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3606                                 mono_mb_emit_byte (mb, CEE_MONO_NEWOBJ);        
3607                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
3608                                 mono_mb_emit_byte (mb, CEE_STIND_I);
3609                         }
3610
3611                         /* dst = *argument */
3612                         mono_mb_emit_ldarg (mb, argnum);
3613
3614                         if (t->byref)
3615                                 mono_mb_emit_byte (mb, CEE_LDIND_I);
3616
3617                         mono_mb_emit_byte (mb, CEE_STLOC_1);
3618
3619                         mono_mb_emit_byte (mb, CEE_LDLOC_1);
3620                         mono_mb_emit_byte (mb, CEE_BRFALSE);
3621                         pos = mb->pos;
3622                         mono_mb_emit_i4 (mb, 0);
3623
3624                         mono_mb_emit_byte (mb, CEE_LDLOC_1);
3625                         mono_mb_emit_icon (mb, sizeof (MonoObject));
3626                         mono_mb_emit_byte (mb, CEE_ADD);
3627                         mono_mb_emit_byte (mb, CEE_STLOC_1);
3628                         
3629                         /* src = tmp_locals [i] */
3630                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
3631                         mono_mb_emit_byte (mb, CEE_STLOC_0);
3632
3633                         /* emit valuetype conversion code */
3634                         emit_struct_conv (mb, klass, TRUE);
3635
3636                         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3637                         break;
3638                 case MONO_TYPE_VALUETYPE:
3639                         if (!t->byref)
3640                                 continue;
3641         
3642                         klass = t->data.klass;
3643                         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) ||
3644                             klass->blittable || klass->enumtype)
3645                                 break;
3646
3647                         /* dst = argument */
3648                         mono_mb_emit_ldarg (mb, argnum);
3649                         mono_mb_emit_byte (mb, CEE_STLOC_1);
3650
3651                         mono_mb_emit_byte (mb, CEE_LDLOC_1);
3652                         mono_mb_emit_byte (mb, CEE_BRFALSE);
3653                         pos = mb->pos;
3654                         mono_mb_emit_i4 (mb, 0);
3655
3656                         /* src = tmp_locals [i] */
3657                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
3658                         mono_mb_emit_byte (mb, CEE_STLOC_0);
3659
3660                         /* emit valuetype conversion code */
3661                         emit_struct_conv (mb, klass, TRUE);
3662                         
3663                         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3664                         break;
3665                 case MONO_TYPE_SZARRAY:
3666                         if (t->byref)
3667                                 continue;
3668  
3669                         klass = mono_class_from_mono_type (t);
3670
3671                         if (klass->element_class == mono_defaults.string_class) {
3672                                 g_assert (tmp_locals [i]);
3673
3674                                 mono_mb_emit_ldarg (mb, argnum);
3675                                 mono_mb_emit_byte (mb, CEE_BRFALSE);
3676                                 pos = mb->pos;
3677                                 mono_mb_emit_i4 (mb, 0);
3678
3679                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3680                                 mono_mb_emit_ldarg (mb, argnum);
3681                                 mono_mb_emit_byte (mb, CEE_LDLEN);                              
3682                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3683                                 mono_mb_emit_byte (mb, CEE_MONO_PROC2);
3684                                 mono_mb_emit_byte (mb, MONO_MARSHAL_FREE_ARRAY);
3685
3686                                 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
3687                         }
3688
3689                         if (t->attrs & PARAM_ATTRIBUTE_OUT) {
3690                                 /* FIXME: Optimize blittable case */
3691                                 MonoClass *eklass;
3692                                 guint32 label1, label2, label3;
3693                                 int index_var, src_ptr;
3694
3695                                 eklass = klass->element_class;
3696                                 src_ptr = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3697
3698                                 /* Check null */
3699                                 mono_mb_emit_ldarg (mb, argnum);
3700                                 mono_mb_emit_byte (mb, CEE_BRFALSE);
3701                                 label1 = mb->pos;
3702                                 mono_mb_emit_i4 (mb, 0);
3703
3704                                 mono_mb_emit_ldloc (mb, tmp_locals [i]);
3705                                 mono_mb_emit_stloc (mb, src_ptr);
3706
3707                                 /* Emit marshalling loop */
3708                                 index_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);                                
3709                                 mono_mb_emit_byte (mb, CEE_LDC_I4_0);
3710                                 mono_mb_emit_stloc (mb, index_var);
3711                                 label2 = mb->pos;
3712                                 mono_mb_emit_ldloc (mb, index_var);
3713                                 mono_mb_emit_ldarg (mb, argnum);
3714                                 mono_mb_emit_byte (mb, CEE_LDLEN);
3715                                 mono_mb_emit_byte (mb, CEE_BGE);
3716                                 label3 = mb->pos;
3717                                 mono_mb_emit_i4 (mb, 0);
3718
3719                                 /* Emit marshalling code */
3720
3721                                 /* set the src_ptr */
3722                                 mono_mb_emit_ldloc (mb, src_ptr);
3723                                 mono_mb_emit_byte (mb, CEE_STLOC_0);
3724
3725                                 /* set dst_ptr */
3726                                 mono_mb_emit_ldarg (mb, argnum);
3727                                 mono_mb_emit_ldloc (mb, index_var);
3728                                 mono_mb_emit_byte (mb, CEE_LDELEMA);
3729                                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eklass));
3730                                 mono_mb_emit_byte (mb, CEE_STLOC_1);
3731
3732                                 /* emit valuetype conversion code */
3733                                 emit_struct_conv (mb, eklass, TRUE);
3734
3735                                 mono_mb_emit_add_to_local (mb, index_var, 1);
3736                                 mono_mb_emit_add_to_local (mb, src_ptr, mono_class_native_size (eklass, NULL));
3737
3738                                 mono_mb_emit_byte (mb, CEE_BR);
3739                                 mono_mb_emit_i4 (mb, label2 - (mb->pos + 4));
3740
3741                                 mono_mb_patch_addr (mb, label1, mb->pos - (label1 + 4));
3742                                 mono_mb_patch_addr (mb, label3, mb->pos - (label3 + 4));
3743                         }
3744                         break;
3745                 case MONO_TYPE_BOOLEAN:
3746                         if (!t->byref)
3747                                 continue;
3748                         mono_mb_emit_ldarg (mb, argnum);
3749                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
3750                         if (mspecs [i + 1] != NULL && mspecs [i + 1]->native == MONO_NATIVE_VARIANTBOOL)
3751                                 mono_mb_emit_byte (mb, CEE_NEG);
3752                         mono_mb_emit_byte (mb, CEE_STIND_I1);
3753                 }
3754         }
3755
3756         if (!MONO_TYPE_IS_VOID(sig->ret))
3757                 mono_mb_emit_byte (mb, CEE_LDLOC_3);
3758
3759         mono_mb_emit_byte (mb, CEE_RET);
3760
3761         csig = g_memdup (sig, sigsize);
3762         csig->pinvoke = 0;
3763         res = mono_mb_create_and_cache (cache, method,
3764                                                                         mb, csig, csig->param_count + 16);
3765         mono_mb_free (mb);
3766
3767         for (i = sig->param_count; i >= 0; i--)
3768                 g_free (mspecs [i]);
3769         g_free (mspecs);
3770
3771         //printf ("CODE FOR %s: \n%s.\n", mono_method_full_name (res, TRUE), mono_disasm_code (0, res, ((MonoMethodNormal*)res)->header->code, ((MonoMethodNormal*)res)->header->code + ((MonoMethodNormal*)res)->header->code_size));
3772
3773         return res;
3774 }
3775
3776 /**
3777  * mono_marshal_get_struct_to_ptr:
3778  * @klass:
3779  *
3780  * generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld)
3781  */
3782 MonoMethod *
3783 mono_marshal_get_struct_to_ptr (MonoClass *klass)
3784 {
3785         MonoMethodBuilder *mb;
3786         static MonoMethod *stoptr = NULL;
3787         MonoMethod *res;
3788
3789         g_assert (klass != NULL);
3790
3791         if (klass->str_to_ptr)
3792                 return klass->str_to_ptr;
3793
3794         if (!stoptr) 
3795                 stoptr = mono_find_method_by_name (mono_defaults.marshal_class, "StructureToPtr", 3);
3796         g_assert (stoptr);
3797
3798         mb = mono_mb_new (klass, stoptr->name, MONO_WRAPPER_UNKNOWN);
3799
3800         if (klass->blittable) {
3801                 mono_mb_emit_byte (mb, CEE_LDARG_1);
3802                 mono_mb_emit_byte (mb, CEE_LDARG_0);
3803                 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3804                 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
3805                 mono_mb_emit_byte (mb, CEE_PREFIX1);
3806                 mono_mb_emit_byte (mb, CEE_CPBLK);
3807         } else {
3808
3809                 /* allocate local 0 (pointer) src_ptr */
3810                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3811                 /* allocate local 1 (pointer) dst_ptr */
3812                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3813                 /* allocate local 2 (boolean) delete_old */
3814                 mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
3815                 mono_mb_emit_byte (mb, CEE_LDARG_2);
3816                 mono_mb_emit_byte (mb, CEE_STLOC_2);
3817
3818                 /* initialize src_ptr to point to the start of object data */
3819                 mono_mb_emit_byte (mb, CEE_LDARG_0);
3820                 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3821                 mono_mb_emit_byte (mb, CEE_STLOC_0);
3822
3823                 /* initialize dst_ptr */
3824                 mono_mb_emit_byte (mb, CEE_LDARG_1);
3825                 mono_mb_emit_byte (mb, CEE_STLOC_1);
3826
3827                 emit_struct_conv (mb, klass, FALSE);
3828         }
3829
3830         mono_mb_emit_byte (mb, CEE_RET);
3831
3832         res = mono_mb_create_method (mb, stoptr->signature, 0);
3833         mono_mb_free (mb);
3834
3835         klass->str_to_ptr = res;
3836         return res;
3837 }
3838
3839 /**
3840  * mono_marshal_get_ptr_to_struct:
3841  * @klass:
3842  *
3843  * generates IL code for PtrToStructure (IntPtr src, object structure)
3844  */
3845 MonoMethod *
3846 mono_marshal_get_ptr_to_struct (MonoClass *klass)
3847 {
3848         MonoMethodBuilder *mb;
3849         static MonoMethod *ptostr = NULL;
3850         MonoMethod *res;
3851
3852         g_assert (klass != NULL);
3853
3854         if (klass->ptr_to_str)
3855                 return klass->ptr_to_str;
3856
3857         if (!ptostr) 
3858                 ptostr = mono_find_method_by_name (mono_defaults.marshal_class, "PtrToStructure", 2);
3859         g_assert (ptostr);
3860
3861         mb = mono_mb_new (klass, ptostr->name, MONO_WRAPPER_UNKNOWN);
3862
3863         if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable) {
3864                 mono_mb_emit_byte (mb, CEE_LDARG_1);
3865                 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3866                 mono_mb_emit_byte (mb, CEE_LDARG_0);
3867                 mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
3868                 mono_mb_emit_byte (mb, CEE_PREFIX1);
3869                 mono_mb_emit_byte (mb, CEE_CPBLK);
3870         } else {
3871
3872                 /* allocate local 0 (pointer) src_ptr */
3873                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3874                 /* allocate local 1 (pointer) dst_ptr */
3875                 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
3876                 
3877                 /* initialize src_ptr to point to the start of object data */
3878                 mono_mb_emit_byte (mb, CEE_LDARG_0);
3879                 mono_mb_emit_byte (mb, CEE_STLOC_0);
3880
3881                 /* initialize dst_ptr */
3882                 mono_mb_emit_byte (mb, CEE_LDARG_1);
3883                 mono_mb_emit_ldflda (mb, sizeof (MonoObject));
3884                 mono_mb_emit_byte (mb, CEE_STLOC_1);
3885
3886                 emit_struct_conv (mb, klass, TRUE);
3887         }
3888
3889         mono_mb_emit_byte (mb, CEE_RET);
3890
3891         res = mono_mb_create_method (mb, ptostr->signature, 0);
3892         mono_mb_free (mb);
3893
3894         klass->ptr_to_str = res;
3895         return res;
3896 }
3897
3898 static MonoReflectionType *
3899 type_from_handle (MonoType *handle)
3900 {
3901         MonoDomain *domain = mono_domain_get (); 
3902         MonoClass *klass = mono_class_from_mono_type (handle);
3903
3904         MONO_ARCH_SAVE_REGS;
3905
3906         mono_class_init (klass);
3907         return mono_type_get_object (domain, handle);
3908 }
3909
3910 /*
3911  * generates IL code for the synchronized wrapper: the generated method
3912  * calls METHOD while locking 'this' or the parent type.
3913  */
3914 MonoMethod *
3915 mono_marshal_get_synchronized_wrapper (MonoMethod *method)
3916 {
3917         static MonoMethodSignature *from_handle_sig = NULL;
3918         static MonoMethod *enter_method, *exit_method;
3919         MonoMethodSignature *sig;
3920         MonoExceptionClause *clause;
3921         MonoMethodHeader *header;
3922         MonoMethodBuilder *mb;
3923         MonoMethod *res;
3924         GHashTable *cache;
3925         int i, pos, this_local, ret_local;
3926
3927         g_assert (method);
3928
3929         if (method->wrapper_type == MONO_WRAPPER_SYNCHRONIZED)
3930                 return method;
3931
3932         cache = method->klass->image->synchronized_cache;
3933         if ((res = mono_marshal_find_in_cache (cache, method)))
3934                 return res;
3935
3936         sig = method->signature;
3937
3938         mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_SYNCHRONIZED);
3939
3940         /* result */
3941         if (!MONO_TYPE_IS_VOID (sig->ret))
3942                 ret_local = mono_mb_add_local (mb, sig->ret);
3943
3944         /* this */
3945         this_local = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
3946
3947         clause = g_new0 (MonoExceptionClause, 1);
3948         clause->flags = MONO_EXCEPTION_CLAUSE_FINALLY;
3949
3950         if (!enter_method) {
3951                 MonoMethodDesc *desc;
3952
3953                 desc = mono_method_desc_new ("Monitor:Enter", FALSE);
3954                 enter_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
3955                 g_assert (enter_method);
3956                 mono_method_desc_free (desc);
3957                 desc = mono_method_desc_new ("Monitor:Exit", FALSE);
3958                 exit_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
3959                 g_assert (exit_method);
3960                 mono_method_desc_free (desc);
3961
3962                 /*
3963                  * GetTypeFromHandle isn't called as a managed method because it has
3964                  * a funky calling sequence, e.g. ldtoken+GetTypeFromHandle gets
3965                  * transformed into something else by the JIT.
3966                  */
3967                 from_handle_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
3968                 from_handle_sig->params [0] = &mono_defaults.object_class->byval_arg;
3969                 from_handle_sig->ret = &mono_defaults.object_class->byval_arg;
3970         }
3971
3972         /* Push this or the type object */
3973         if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3974                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
3975                 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
3976                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, &method->klass->byval_arg));
3977                 mono_mb_emit_native_call (mb, from_handle_sig, type_from_handle);
3978         }
3979         else
3980                 mono_mb_emit_ldarg (mb, 0);
3981         mono_mb_emit_stloc (mb, this_local);
3982
3983         /* Call Monitor::Enter() */
3984         mono_mb_emit_ldloc (mb, this_local);
3985         mono_mb_emit_managed_call (mb, enter_method, NULL);
3986
3987         clause->try_offset = mb->pos;
3988
3989         /* Call the method */
3990         if (sig->hasthis)
3991                 mono_mb_emit_ldarg (mb, 0);
3992         for (i = 0; i < sig->param_count; i++)
3993                 mono_mb_emit_ldarg (mb, i + (sig->hasthis == TRUE));
3994         mono_mb_emit_managed_call (mb, method, method->signature);
3995         if (!MONO_TYPE_IS_VOID (sig->ret))
3996                 mono_mb_emit_stloc (mb, ret_local);
3997
3998         mono_mb_emit_byte (mb, CEE_LEAVE);
3999         pos = mb->pos;
4000         mono_mb_emit_i4 (mb, 0);
4001
4002         clause->try_len = mb->pos - clause->try_offset;
4003         clause->handler_offset = mb->pos;
4004
4005         /* Call Monitor::Exit() */
4006         mono_mb_emit_ldloc (mb, this_local);
4007 //      mono_mb_emit_native_call (mb, exit_sig, mono_monitor_exit);
4008         mono_mb_emit_managed_call (mb, exit_method, NULL);
4009         mono_mb_emit_byte (mb, CEE_ENDFINALLY);
4010
4011         clause->handler_len = mb->pos - clause->handler_offset;
4012
4013         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
4014         if (!MONO_TYPE_IS_VOID (sig->ret))
4015                 mono_mb_emit_ldloc (mb, ret_local);
4016         mono_mb_emit_byte (mb, CEE_RET);
4017
4018         res = mono_mb_create_and_cache (cache, method,
4019                                                                         mb, sig, sig->param_count + 16);
4020         mono_mb_free (mb);
4021
4022         header = ((MonoMethodNormal *)res)->header;
4023         header->num_clauses = 1;
4024         header->clauses = clause;
4025
4026         return res;     
4027 }
4028
4029 /* FIXME: on win32 we should probably use GlobalAlloc(). */
4030 void*
4031 mono_marshal_alloc (gpointer size) 
4032 {
4033         MONO_ARCH_SAVE_REGS;
4034
4035         return g_try_malloc ((gulong)size);
4036 }
4037
4038 void
4039 mono_marshal_free (gpointer ptr) 
4040 {
4041         MONO_ARCH_SAVE_REGS;
4042
4043         g_free (ptr);
4044 }
4045
4046 void
4047 mono_marshal_free_array (gpointer *ptr, int size) 
4048 {
4049         int i;
4050
4051         if (!ptr)
4052                 return;
4053
4054         for (i = 0; i < size; i++)
4055                 if (ptr [i])
4056                         g_free (ptr [i]);
4057 }
4058
4059 void *
4060 mono_marshal_realloc (gpointer ptr, gpointer size) 
4061 {
4062         MONO_ARCH_SAVE_REGS;
4063
4064         return g_try_realloc (ptr, (gulong)size);
4065 }
4066
4067 void *
4068 mono_marshal_string_array (MonoArray *array)
4069 {
4070         char **result;
4071         int i, len;
4072
4073         if (!array)
4074                 return NULL;
4075
4076         len = mono_array_length (array);
4077
4078         result = g_malloc (sizeof (char *) * (len + 1));
4079         for (i = 0; i < len; ++i) {
4080                 MonoString *s = (MonoString *)mono_array_get (array, gpointer, i);
4081                 result [i] = s ? mono_string_to_utf8 (s): NULL;
4082         }
4083         /* null terminate the array */
4084         result [i] = NULL;
4085
4086         return result;
4087 }
4088
4089 /**
4090  * mono_marshal_set_last_error:
4091  *
4092  * This function is invoked to set the last error value from a P/Invoke call
4093  * which has SetLastError set.
4094  */
4095 void
4096 mono_marshal_set_last_error (void)
4097 {
4098 #ifdef WIN32
4099         TlsSetValue (last_error_tls_id, (gpointer)GetLastError ());
4100 #else
4101         TlsSetValue (last_error_tls_id, (gpointer)errno);
4102 #endif
4103 }
4104
4105 void
4106 ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArray *src, gint32 start_index,
4107                                                                     gpointer dest, gint32 length)
4108 {
4109         int element_size;
4110         void *source_addr;
4111
4112         MONO_ARCH_SAVE_REGS;
4113
4114         MONO_CHECK_ARG_NULL (src);
4115         MONO_CHECK_ARG_NULL (dest);
4116
4117         g_assert (src->obj.vtable->klass->rank == 1);
4118         g_assert (start_index >= 0);
4119         g_assert (length >= 0);
4120         g_assert (start_index + length <= mono_array_length (src));
4121
4122         element_size = mono_array_element_size (src->obj.vtable->klass);
4123           
4124         source_addr = mono_array_addr_with_size (src, element_size, start_index);
4125
4126         memcpy (dest, source_addr, length * element_size);
4127 }
4128
4129 void
4130 ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer src, gint32 start_index,
4131                                                                       MonoArray *dest, gint32 length)
4132 {
4133         int element_size;
4134         void *dest_addr;
4135
4136         MONO_ARCH_SAVE_REGS;
4137
4138         MONO_CHECK_ARG_NULL (src);
4139         MONO_CHECK_ARG_NULL (dest);
4140
4141         g_assert (dest->obj.vtable->klass->rank == 1);
4142         g_assert (start_index >= 0);
4143         g_assert (length >= 0);
4144         g_assert (start_index + length <= mono_array_length (dest));
4145
4146         element_size = mono_array_element_size (dest->obj.vtable->klass);
4147           
4148         dest_addr = mono_array_addr_with_size (dest, element_size, start_index);
4149
4150         memcpy (dest_addr, src, length * element_size);
4151 }
4152
4153 #if NO_UNALIGNED_ACCESS
4154 #define RETURN_UNALIGNED(type, addr) \
4155         { \
4156                 type val; \
4157                 memcpy(&val, p + offset, sizeof(val)); \
4158                 return val; \
4159         }
4160 #define WRITE_UNALIGNED(type, addr, val) \
4161         memcpy(addr, &val, sizeof(type))
4162 #else
4163 #define RETURN_UNALIGNED(type, addr) \
4164         return *(type*)(p + offset);
4165 #define WRITE_UNALIGNED(type, addr, val) \
4166         (*(type *)(addr) = (val))
4167 #endif
4168
4169 gpointer
4170 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr, gint32 offset)
4171 {
4172         char *p = ptr;
4173
4174         MONO_ARCH_SAVE_REGS;
4175
4176         RETURN_UNALIGNED(gpointer, p + offset);
4177 }
4178
4179 unsigned char
4180 ves_icall_System_Runtime_InteropServices_Marshal_ReadByte (gpointer ptr, gint32 offset)
4181 {
4182         char *p = ptr;
4183
4184         MONO_ARCH_SAVE_REGS;
4185
4186         return *(unsigned char*)(p + offset);
4187 }
4188
4189 gint16
4190 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt16 (gpointer ptr, gint32 offset)
4191 {
4192         char *p = ptr;
4193
4194         MONO_ARCH_SAVE_REGS;
4195
4196         RETURN_UNALIGNED(gint16, p + offset);
4197 }
4198
4199 gint32
4200 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt32 (gpointer ptr, gint32 offset)
4201 {
4202         char *p = ptr;
4203
4204         MONO_ARCH_SAVE_REGS;
4205
4206         RETURN_UNALIGNED(gint32, p + offset);
4207 }
4208
4209 gint64
4210 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt64 (gpointer ptr, gint32 offset)
4211 {
4212         char *p = ptr;
4213
4214         MONO_ARCH_SAVE_REGS;
4215
4216         RETURN_UNALIGNED(gint64, p + offset);
4217 }
4218
4219 void
4220 ves_icall_System_Runtime_InteropServices_Marshal_WriteByte (gpointer ptr, gint32 offset, unsigned char val)
4221 {
4222         char *p = ptr;
4223
4224         MONO_ARCH_SAVE_REGS;
4225
4226         *(unsigned char*)(p + offset) = val;
4227 }
4228
4229 void
4230 ves_icall_System_Runtime_InteropServices_Marshal_WriteIntPtr (gpointer ptr, gint32 offset, gpointer val)
4231 {
4232         char *p = ptr;
4233
4234         MONO_ARCH_SAVE_REGS;
4235
4236         WRITE_UNALIGNED(gpointer, p + offset, val);
4237 }
4238
4239 void
4240 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt16 (gpointer ptr, gint32 offset, gint16 val)
4241 {
4242         char *p = ptr;
4243
4244         MONO_ARCH_SAVE_REGS;
4245
4246         WRITE_UNALIGNED(gint16, p + offset, val);
4247 }
4248
4249 void
4250 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt32 (gpointer ptr, gint32 offset, gint32 val)
4251 {
4252         char *p = ptr;
4253
4254         MONO_ARCH_SAVE_REGS;
4255
4256         WRITE_UNALIGNED(gint32, p + offset, val);
4257 }
4258
4259 void
4260 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt64 (gpointer ptr, gint32 offset, gint64 val)
4261 {
4262         char *p = ptr;
4263
4264         MONO_ARCH_SAVE_REGS;
4265
4266         WRITE_UNALIGNED(gint64, p + offset, val);
4267 }
4268
4269 MonoString *
4270 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi (char *ptr)
4271 {
4272         MONO_ARCH_SAVE_REGS;
4273
4274         return mono_string_new (mono_domain_get (), ptr);
4275 }
4276
4277 MonoString *
4278 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len (char *ptr, gint32 len)
4279 {
4280         MONO_ARCH_SAVE_REGS;
4281
4282         return mono_string_new_len (mono_domain_get (), ptr, len);
4283 }
4284
4285 MonoString *
4286 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni (guint16 *ptr)
4287 {
4288         MonoDomain *domain = mono_domain_get (); 
4289         int len = 0;
4290         guint16 *t = ptr;
4291
4292         MONO_ARCH_SAVE_REGS;
4293
4294         while (*t++)
4295                 len++;
4296
4297         return mono_string_new_utf16 (domain, ptr, len);
4298 }
4299
4300 MonoString *
4301 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len (guint16 *ptr, gint32 len)
4302 {
4303         MonoDomain *domain = mono_domain_get (); 
4304
4305         MONO_ARCH_SAVE_REGS;
4306
4307         return mono_string_new_utf16 (domain, ptr, len);
4308 }
4309
4310 MonoString *
4311 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR (gpointer ptr)
4312 {
4313         MONO_ARCH_SAVE_REGS;
4314
4315         g_warning ("PtrToStringBSTR not implemented");
4316         g_assert_not_reached ();
4317
4318         return NULL;
4319 }
4320
4321 guint32 
4322 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
4323 {
4324         MONO_ARCH_SAVE_REGS;
4325
4326         return ((guint32)TlsGetValue (last_error_tls_id));
4327 }
4328
4329 guint32 
4330 ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype)
4331 {
4332         MonoClass *klass;
4333
4334         MONO_ARCH_SAVE_REGS;
4335
4336         MONO_CHECK_ARG_NULL (rtype);
4337
4338         klass = mono_class_from_mono_type (rtype->type);
4339
4340         return mono_class_native_size (klass, NULL);
4341 }
4342
4343 void
4344 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old)
4345 {
4346         MonoMethod *method;
4347         gpointer pa [3];
4348
4349         MONO_ARCH_SAVE_REGS;
4350
4351         MONO_CHECK_ARG_NULL (obj);
4352         MONO_CHECK_ARG_NULL (dst);
4353
4354         method = mono_marshal_get_struct_to_ptr (obj->vtable->klass);
4355
4356         pa [0] = obj;
4357         pa [1] = &dst;
4358         pa [2] = &delete_old;
4359
4360         mono_runtime_invoke (method, NULL, pa, NULL);
4361 }
4362
4363 void
4364 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, MonoObject *dst)
4365 {
4366         MonoMethod *method;
4367         gpointer pa [2];
4368
4369         MONO_ARCH_SAVE_REGS;
4370
4371         MONO_CHECK_ARG_NULL (src);
4372         MONO_CHECK_ARG_NULL (dst);
4373
4374         method = mono_marshal_get_ptr_to_struct (dst->vtable->klass);
4375
4376         pa [0] = &src;
4377         pa [1] = dst;
4378
4379         mono_runtime_invoke (method, NULL, pa, NULL);
4380 }
4381
4382 MonoObject *
4383 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer src, MonoReflectionType *type)
4384 {
4385         MonoDomain *domain = mono_domain_get (); 
4386         MonoObject *res;
4387
4388         MONO_ARCH_SAVE_REGS;
4389
4390         MONO_CHECK_ARG_NULL (src);
4391         MONO_CHECK_ARG_NULL (type);
4392
4393         res = mono_object_new (domain, mono_class_from_mono_type (type->type));
4394
4395         ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (src, res);
4396
4397         return res;
4398 }
4399
4400 int
4401 ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *type, MonoString *field_name)
4402 {
4403         MonoMarshalType *info;
4404         MonoClass *klass;
4405         char *fname;
4406         int i, match_index = -1;
4407         
4408         MONO_ARCH_SAVE_REGS;
4409
4410         MONO_CHECK_ARG_NULL (type);
4411         MONO_CHECK_ARG_NULL (field_name);
4412
4413         fname = mono_string_to_utf8 (field_name);
4414         klass = mono_class_from_mono_type (type->type);
4415
4416         while(klass && match_index == -1) {
4417                 for (i = 0; i < klass->field.count; ++i) {
4418                         if (*fname == *klass->fields [i].name && strcmp (fname, klass->fields [i].name) == 0) {
4419                                 match_index = i;
4420                                 break;
4421                         }
4422                 }
4423
4424                 if(match_index == -1)
4425                         klass = klass->parent;
4426         }
4427
4428         g_free (fname);
4429
4430         if(match_index == -1) {
4431                MonoException* exc;
4432                gchar *tmp;
4433
4434                /* Get back original class instance */
4435                klass = mono_class_from_mono_type (type->type);
4436
4437                tmp = g_strdup_printf ("Field passed in is not a marshaled member of the type %s", klass->name);
4438                exc = mono_get_exception_argument ("fieldName", tmp);
4439                g_free (tmp);
4440  
4441                mono_raise_exception ((MonoException*)exc);
4442        }
4443
4444        info = mono_marshal_load_type_info (klass);     
4445        return info->fields [match_index].offset;
4446 }
4447
4448 gpointer
4449 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString *string)
4450 {
4451         MONO_ARCH_SAVE_REGS;
4452
4453         return mono_string_to_utf8 (string);
4454 }
4455
4456 gpointer
4457 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni (MonoString *string)
4458 {
4459         MONO_ARCH_SAVE_REGS;
4460
4461         return g_memdup (mono_string_chars (string), mono_string_length (string)*2);
4462 }
4463
4464 static void
4465 mono_struct_delete_old (MonoClass *klass, char *ptr)
4466 {
4467         MonoMarshalType *info;
4468         int i;
4469
4470         info = mono_marshal_load_type_info (klass);
4471
4472         for (i = 0; i < info->num_fields; i++) {
4473                 MonoMarshalNative ntype;
4474                 MonoMarshalConv conv;
4475                 MonoType *ftype = info->fields [i].field->type;
4476                 char *cpos;
4477
4478                 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
4479                         continue;
4480
4481                 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, 
4482                                                 klass->unicode, &conv);
4483                         
4484                 cpos = ptr + info->fields [i].offset;
4485
4486                 switch (conv) {
4487                 case MONO_MARSHAL_CONV_NONE:
4488                         if (MONO_TYPE_ISSTRUCT (ftype)) {
4489                                 mono_struct_delete_old (ftype->data.klass, cpos);
4490                                 continue;
4491                         }
4492                         break;
4493                 case MONO_MARSHAL_CONV_STR_LPWSTR:
4494                 case MONO_MARSHAL_CONV_STR_LPSTR:
4495                 case MONO_MARSHAL_CONV_STR_LPTSTR:
4496                 case MONO_MARSHAL_CONV_STR_BSTR:
4497                 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
4498                 case MONO_MARSHAL_CONV_STR_TBSTR:
4499                         g_free (*(gpointer *)cpos);
4500                         break;
4501                 default:
4502                         continue;
4503                 }
4504         }
4505 }
4506
4507 void
4508 ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure (gpointer src, MonoReflectionType *type)
4509 {
4510         MonoClass *klass;
4511
4512         MONO_ARCH_SAVE_REGS;
4513
4514         MONO_CHECK_ARG_NULL (src);
4515         MONO_CHECK_ARG_NULL (type);
4516
4517         klass = mono_class_from_mono_type (type->type);
4518
4519         mono_struct_delete_old (klass, (char *)src);
4520 }
4521
4522 MonoMarshalType *
4523 mono_marshal_load_type_info (MonoClass* klass)
4524 {
4525         int i, j, count = 0, native_size = 0;
4526         MonoMarshalType *info;
4527         guint32 layout;
4528
4529         g_assert (klass != NULL);
4530
4531         if (klass->marshal_info)
4532                 return klass->marshal_info;
4533
4534         if (!klass->inited)
4535                 mono_class_init (klass);
4536         
4537         for (i = 0; i < klass->field.count; ++i) {
4538                 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
4539                         continue;
4540                 if (mono_field_is_deleted (&klass->fields [i]))
4541                         continue;
4542                 count++;
4543         }
4544
4545         layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
4546
4547         klass->marshal_info = info = g_malloc0 (sizeof (MonoMarshalType) + sizeof (MonoMarshalField) * count);
4548         info->num_fields = count;
4549         
4550         /* Try to find a size for this type in metadata */
4551         mono_metadata_packing_from_typedef (klass->image, klass->type_token, NULL, &native_size);
4552
4553         if (klass->parent) {
4554                 int parent_size = mono_class_native_size (klass->parent, NULL);
4555
4556                 /* Add parent size to real size */
4557                 native_size += parent_size;
4558                 info->native_size = parent_size;
4559         }
4560  
4561         for (j = i = 0; i < klass->field.count; ++i) {
4562                 int size, align;
4563                 
4564                 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)
4565                         continue;
4566
4567                 if (mono_field_is_deleted (&klass->fields [i]))
4568                         continue;
4569                 if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL)
4570                         mono_metadata_field_info (klass->image, klass->field.first + i, 
4571                                                   NULL, NULL, &info->fields [j].mspec);
4572
4573                 info->fields [j].field = &klass->fields [i];
4574
4575                 if ((klass->field.count == 1) && (klass->instance_size == sizeof (MonoObject)) &&
4576                         (strcmp (klass->fields [i].name, "$PRIVATE$") == 0)) {
4577                         /* This field is a hack inserted by MCS to empty structures */
4578                         continue;
4579                 }
4580
4581                 switch (layout) {
4582                 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
4583                 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
4584                         size = mono_marshal_type_size (klass->fields [i].type, info->fields [j].mspec, 
4585                                                        &align, TRUE, klass->unicode);
4586                         align = klass->packing_size ? MIN (klass->packing_size, align): align;  
4587                         info->fields [j].offset = info->native_size;
4588                         info->fields [j].offset += align - 1;
4589                         info->fields [j].offset &= ~(align - 1);
4590                         info->native_size = info->fields [j].offset + size;
4591                         break;
4592                 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
4593                         /* FIXME: */
4594                         info->fields [j].offset = klass->fields [i].offset - sizeof (MonoObject);
4595                         info->native_size = klass->instance_size - sizeof (MonoObject);
4596                         break;
4597                 }       
4598                 j++;
4599         }
4600
4601         if(layout != TYPE_ATTRIBUTE_AUTO_LAYOUT) {
4602                 info->native_size = MAX (native_size, info->native_size);
4603         }
4604
4605         if (info->native_size & (klass->min_align - 1)) {
4606                 info->native_size += klass->min_align - 1;
4607                 info->native_size &= ~(klass->min_align - 1);
4608         }
4609
4610         return klass->marshal_info;
4611 }
4612
4613 /**
4614  * mono_class_native_size:
4615  * @klass: a class 
4616  * 
4617  * Returns: the native size of an object instance (when marshaled 
4618  * to unmanaged code) 
4619  */
4620 gint32
4621 mono_class_native_size (MonoClass *klass, guint32 *align)
4622 {
4623         
4624         if (!klass->marshal_info)
4625                 mono_marshal_load_type_info (klass);
4626
4627         if (align)
4628                 *align = klass->min_align;
4629
4630         return klass->marshal_info->native_size;
4631 }
4632
4633 /*
4634  * mono_type_native_stack_size:
4635  * @t: the type to return the size it uses on the stack
4636  *
4637  * Returns: the number of bytes required to hold an instance of this
4638  * type on the native stack
4639  */
4640 int
4641 mono_type_native_stack_size (MonoType *t, gint *align)
4642 {
4643         int tmp;
4644
4645         g_assert (t != NULL);
4646
4647         if (!align)
4648                 align = &tmp;
4649
4650         if (t->byref) {
4651                 *align = 4;
4652                 return 4;
4653         }
4654
4655         switch (t->type){
4656         case MONO_TYPE_BOOLEAN:
4657         case MONO_TYPE_CHAR:
4658         case MONO_TYPE_I1:
4659         case MONO_TYPE_U1:
4660         case MONO_TYPE_I2:
4661         case MONO_TYPE_U2:
4662         case MONO_TYPE_I4:
4663         case MONO_TYPE_U4:
4664         case MONO_TYPE_I:
4665         case MONO_TYPE_U:
4666         case MONO_TYPE_STRING:
4667         case MONO_TYPE_OBJECT:
4668         case MONO_TYPE_CLASS:
4669         case MONO_TYPE_SZARRAY:
4670         case MONO_TYPE_PTR:
4671         case MONO_TYPE_FNPTR:
4672         case MONO_TYPE_ARRAY:
4673         case MONO_TYPE_TYPEDBYREF:
4674                 *align = 4;
4675                 return 4;
4676         case MONO_TYPE_R4:
4677                 *align = 4;
4678                 return 4;
4679         case MONO_TYPE_I8:
4680         case MONO_TYPE_U8:
4681         case MONO_TYPE_R8:
4682                 *align = 4;
4683                 return 8;
4684         case MONO_TYPE_VALUETYPE: {
4685                 guint32 size;
4686
4687                 if (t->data.klass->enumtype)
4688                         return mono_type_native_stack_size (t->data.klass->enum_basetype, align);
4689                 else {
4690                         size = mono_class_native_size (t->data.klass, align);
4691                         *align = *align + 3;
4692                         *align &= ~3;
4693                         
4694                         size +=  3;
4695                         size &= ~3;
4696
4697                         return size;
4698                 }
4699         }
4700         default:
4701                 g_error ("type 0x%02x unknown", t->type);
4702         }
4703         return 0;
4704 }
4705
4706 /* __alignof__ returns the preferred alignment of values not the actual alignment used by
4707    the compiler so is wrong e.g. for Linux where doubles are aligned on a 4 byte boundary
4708    but __alignof__ returns 8 - using G_STRUCT_OFFSET works better */
4709 #define ALIGNMENT(type) G_STRUCT_OFFSET(struct { char c; type x; }, x)
4710
4711 gint32
4712 mono_marshal_type_size (MonoType *type, MonoMarshalSpec *mspec, gint32 *align, 
4713                         gboolean as_field, gboolean unicode)
4714 {
4715         MonoMarshalNative native_type = mono_type_to_unmanaged (type, mspec, as_field, unicode, NULL);
4716         MonoClass *klass;
4717
4718         switch (native_type) {
4719         case MONO_NATIVE_BOOLEAN:
4720                 *align = 4;
4721                 return 4;
4722         case MONO_NATIVE_I1:
4723         case MONO_NATIVE_U1:
4724                 *align = 1;
4725                 return 1;
4726         case MONO_NATIVE_I2:
4727         case MONO_NATIVE_U2:
4728         case MONO_NATIVE_VARIANTBOOL:
4729                 *align = 2;
4730                 return 2;
4731         case MONO_NATIVE_I4:
4732         case MONO_NATIVE_U4:
4733         case MONO_NATIVE_ERROR:
4734                 *align = 4;
4735                 return 4;
4736         case MONO_NATIVE_I8:
4737         case MONO_NATIVE_U8:
4738                 *align = ALIGNMENT(guint64);
4739                 return 8;
4740         case MONO_NATIVE_R4:
4741                 *align = 4;
4742                 return 4;
4743         case MONO_NATIVE_R8:
4744                 *align = ALIGNMENT(double);
4745                 return 8;
4746         case MONO_NATIVE_INT:
4747         case MONO_NATIVE_UINT:
4748         case MONO_NATIVE_LPSTR:
4749         case MONO_NATIVE_LPWSTR:
4750         case MONO_NATIVE_LPTSTR:
4751         case MONO_NATIVE_BSTR:
4752         case MONO_NATIVE_ANSIBSTR:
4753         case MONO_NATIVE_TBSTR:
4754         case MONO_NATIVE_LPARRAY:
4755         case MONO_NATIVE_SAFEARRAY:
4756         case MONO_NATIVE_IUNKNOWN:
4757         case MONO_NATIVE_IDISPATCH:
4758         case MONO_NATIVE_INTERFACE:
4759         case MONO_NATIVE_ASANY:
4760         case MONO_NATIVE_FUNC:
4761         case MONO_NATIVE_LPSTRUCT:
4762                 *align = ALIGNMENT(gpointer);
4763                 return sizeof (gpointer);
4764         case MONO_NATIVE_STRUCT: 
4765                 klass = mono_class_from_mono_type (type);
4766                 return mono_class_native_size (klass, align);
4767         case MONO_NATIVE_BYVALTSTR: {
4768                 int esize = unicode ? 2: 1;
4769                 g_assert (mspec);
4770                 *align = esize;
4771                 return mspec->data.array_data.num_elem * esize;
4772         }
4773         case MONO_NATIVE_BYVALARRAY: {
4774                 int esize;
4775                 klass = mono_class_from_mono_type (type);
4776                 esize = mono_class_native_size (klass->element_class, align);
4777                 g_assert (mspec);
4778                 return mspec->data.array_data.num_elem * esize;
4779         }
4780         case MONO_NATIVE_CUSTOM:
4781                 g_assert_not_reached ();
4782                 break;
4783         case MONO_NATIVE_CURRENCY:
4784         case MONO_NATIVE_VBBYREFSTR:
4785         default:
4786                 g_error ("native type %02x not implemented", native_type); 
4787                 break;
4788         }
4789         g_assert_not_reached ();
4790         return 0;
4791 }
4792