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