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