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