2002-07-15 Dietmar Maurer <dietmar@ximian.com>
[mono.git] / mono / metadata / marshal.c
1 /*
2  * marshal.c: Routines for marshaling complex types in P/Invoke methods.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
7  * (C) 2002 Ximian, Inc.  http://www.ximian.com
8  *
9  */
10
11 #include "config.h"
12 #include "object.h"
13 #include "loader.h"
14 #include "metadata/marshal.h"
15 #include "metadata/tabledefs.h"
16 #include "metadata/exception.h"
17 #include "metadata/appdomain.h"
18 #include "mono/metadata/debug-helpers.h"
19 #include "mono/metadata/threadpool.h"
20
21 //#define DEBUG_RUNTIME_CODE
22
23 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
24         a = i,
25
26 enum {
27 #include "mono/cil/opcode.def"
28         LAST = 0xff
29 };
30 #undef OPDEF
31
32 struct _MonoMethodBuilder {
33         MonoMethod *method;
34         GList *locals_list;
35         int locals;
36         guint32 code_size, pos;
37         unsigned char *code;
38 };
39
40 #ifdef DEBUG_RUNTIME_CODE
41 static char*
42 indenter (MonoDisHelper *dh, MonoMethod *method, guint32 ip_offset)
43 {
44         return g_strdup (" ");
45 }
46
47 static MonoDisHelper marshal_dh = {
48         "\n",
49         NULL,
50         "IL_%04x",
51         indenter, 
52         NULL,
53         NULL
54 };
55 #endif 
56
57 gpointer
58 mono_delegate_to_ftnptr (MonoDelegate *delegate)
59 {
60         MonoMethod *method, *invoke, *wrapper;
61         MonoMethodSignature *sig;
62         MonoClass *klass;
63
64         if (!delegate)
65                 return NULL;
66
67         if (delegate->delegate_trampoline)
68                 return delegate->delegate_trampoline;
69
70         klass = ((MonoObject *)delegate)->vtable->klass;
71         g_assert (klass->delegate);
72         
73         method = delegate->method_info->method;
74         sig = method->signature;
75         
76         invoke = mono_get_delegate_invoke (klass);
77         wrapper = mono_marshal_get_managed_wrapper (invoke, (MonoObject *)delegate);
78
79         delegate->delegate_trampoline =  mono_compile_method (wrapper);
80
81         return delegate->delegate_trampoline;
82 }
83
84 gpointer
85 mono_array_to_savearray (MonoArray *array)
86 {
87         if (!array)
88                 return NULL;
89
90         g_assert_not_reached ();
91         return NULL;
92 }
93
94 gpointer
95 mono_array_to_lparray (MonoArray *array)
96 {
97         if (!array)
98                 return NULL;
99
100         g_assert_not_reached ();
101         return NULL;
102 }
103
104 gpointer
105 mono_string_to_ansibstr (MonoString *string_obj)
106 {
107         g_error ("implement me");
108         return NULL;
109 }
110
111 gpointer
112 mono_string_to_bstr (MonoString *string_obj)
113 {
114         g_error ("implement me");
115         return NULL;
116 }
117
118 void
119 mono_string_to_byvalstr (gpointer dst, MonoString *src, int size)
120 {
121         char *s;
122         int len;
123
124         g_assert (dst != NULL);
125         g_assert (size > 0);
126
127         if (!src) {
128                 memset (dst, 0, size);
129                 return;
130         }
131
132         s = mono_string_to_utf8 (src);
133         len = MIN (size, strlen (s));
134         memcpy (dst, s, len);
135         g_free (s);
136
137         *((char *)dst + size - 1) = 0;
138 }
139
140 void
141 mono_string_to_byvalwstr (gpointer dst, MonoString *src, int size)
142 {
143         int len;
144
145         g_assert (dst != NULL);
146         g_assert (size > 1);
147
148         if (!src) {
149                 memset (dst, 0, size);
150                 return;
151         }
152
153         len = MIN (size, (mono_string_length (src) * 2));
154         memcpy (dst, mono_string_chars (src), len);
155
156         *((char *)dst + size - 1) = 0;
157         *((char *)dst + size - 2) = 0;
158 }
159
160
161 static MonoMethod *
162 mono_find_method_by_name (MonoClass *klass, const char *name, int param_count)
163 {
164         MonoMethod *res = NULL;
165         int i;
166
167         for (i = 0; i < klass->method.count; ++i) {
168                 if ((klass->methods [i]->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
169                     klass->methods [i]->name[0] == name [0] && 
170                     !strcmp (name, klass->methods [i]->name) &&
171                     klass->methods [i]->signature->param_count == param_count) {
172                         res = klass->methods [i];
173                         break;
174                 }
175         }
176         return res;
177 }
178
179 void
180 mono_mb_free (MonoMethodBuilder *mb)
181 {
182         g_list_free (mb->locals_list);
183         g_free (mb);
184 }
185
186 MonoMethodBuilder *
187 mono_mb_new (MonoClass *klass, const char *name)
188 {
189         MonoMethodBuilder *mb;
190         MonoMethod *m;
191
192         g_assert (klass != NULL);
193         g_assert (name != NULL);
194
195         mb = g_new0 (MonoMethodBuilder, 1);
196
197         mb->method = m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
198
199         m->klass = klass;
200         m->name = g_strdup (name);
201         m->inline_info = 1;
202         m->inline_count = -1;
203         m->wrapper_type = MONO_WRAPPER_UNKNOWN;
204
205         mb->code_size = 256;
206         mb->code = g_malloc (mb->code_size);
207         
208         return mb;
209 }
210
211 int
212 mono_mb_add_local (MonoMethodBuilder *mb, MonoType *type)
213 {
214         int res = mb->locals;
215
216         g_assert (mb != NULL);
217         g_assert (type != NULL);
218
219         mb->locals_list = g_list_append (mb->locals_list, type);
220         mb->locals++;
221
222         return res;
223 }
224
225 MonoMethod *
226 mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack)
227 {
228         MonoMethodHeader *header;
229         GList *l;
230         int i;
231
232         g_assert (mb != NULL);
233
234         ((MonoMethodNormal *)mb->method)->header = header = (MonoMethodHeader *) 
235                 g_malloc0 (sizeof (MonoMethodHeader) + mb->locals * sizeof (MonoType *));
236
237         if (max_stack < 8)
238                 max_stack = 8;
239
240         header->max_stack = max_stack;
241
242         for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
243                 header->locals [i] = (MonoType *)l->data;
244         }
245
246         mb->method->signature = signature;
247         header->code = mb->code;
248         header->code_size = mb->pos;
249         header->num_locals = mb->locals;
250
251 #ifdef DEBUG_RUNTIME_CODE
252         printf ("RUNTIME CODE FOR %s\n", mono_method_full_name (mb->method, TRUE));
253         printf ("%s\n", mono_disasm_code (&marshal_dh, mb->method, mb->code, mb->code + mb->pos));
254 #endif
255
256         return mb->method;
257 }
258
259 guint32
260 mono_mb_add_data (MonoMethodBuilder *mb, gpointer data)
261 {
262         MonoMethodWrapper *mw;
263
264         g_assert (mb != NULL);
265
266         mw = (MonoMethodWrapper *)mb->method;
267
268         mw->data = g_list_append (mw->data, data);
269
270         return g_list_length (mw->data);
271 }
272
273 void
274 mono_mb_patch_addr (MonoMethodBuilder *mb, int pos, int value)
275 {
276         *((gint32 *)(&mb->code [pos])) = value;
277 }
278
279 void
280 mono_mb_emit_byte (MonoMethodBuilder *mb, guint8 op)
281 {
282         if (mb->pos >= mb->code_size) {
283                 mb->code_size += 64;
284                 mb->code = g_realloc (mb->code, mb->code_size);
285         }
286
287         mb->code [mb->pos++] = op;
288 }
289
290 void
291 mono_mb_emit_i4 (MonoMethodBuilder *mb, gint32 data)
292 {
293         if ((mb->pos + 4) >= mb->code_size) {
294                 mb->code_size += 64;
295                 mb->code = g_realloc (mb->code, mb->code_size);
296         }
297
298         *((gint32 *)(&mb->code [mb->pos])) = data;
299         mb->pos += 4;
300 }
301
302 void
303 mono_mb_emit_i2 (MonoMethodBuilder *mb, gint16 data)
304 {
305         if ((mb->pos + 2) >= mb->code_size) {
306                 mb->code_size += 64;
307                 mb->code = g_realloc (mb->code, mb->code_size);
308         }
309
310         *((gint16 *)(&mb->code [mb->pos])) = data;
311         mb->pos += 2;
312 }
313
314 void
315 mono_mb_emit_ldarg (MonoMethodBuilder *mb, guint argnum)
316 {
317         if (argnum < 4) {
318                 mono_mb_emit_byte (mb, CEE_LDARG_0 + argnum);
319         } else if (argnum < 256) {
320                 mono_mb_emit_byte (mb, CEE_LDARG_S);
321                 mono_mb_emit_byte (mb, argnum);
322         } else {
323                 mono_mb_emit_byte (mb, CEE_PREFIX1);
324                 mono_mb_emit_byte (mb, CEE_LDARG);
325                 mono_mb_emit_i4 (mb, argnum);
326         }
327 }
328
329 void
330 mono_mb_emit_ldarg_addr (MonoMethodBuilder *mb, guint argnum)
331 {
332         if (argnum < 256) {
333                 mono_mb_emit_byte (mb, CEE_LDARGA_S);
334                 mono_mb_emit_byte (mb, argnum);
335         } else {
336                 mono_mb_emit_byte (mb, CEE_PREFIX1);
337                 mono_mb_emit_byte (mb, CEE_LDARGA);
338                 mono_mb_emit_i4 (mb, argnum);
339         }
340 }
341
342 void
343 mono_mb_emit_ldloc (MonoMethodBuilder *mb, guint num)
344 {
345         if (num < 4) {
346                 mono_mb_emit_byte (mb, CEE_LDLOC_0 + num);
347         } else if (num < 256) {
348                 mono_mb_emit_byte (mb, CEE_LDLOC_S);
349                 mono_mb_emit_byte (mb, num);
350         } else {
351                 mono_mb_emit_byte (mb, CEE_PREFIX1);
352                 mono_mb_emit_byte (mb, CEE_LDLOC);
353                 mono_mb_emit_i4 (mb, num);
354         }
355 }
356
357 void
358 mono_mb_emit_stloc (MonoMethodBuilder *mb, guint num)
359 {
360         if (num < 4) {
361                 mono_mb_emit_byte (mb, CEE_STLOC_0 + num);
362         } else if (num < 256) {
363                 mono_mb_emit_byte (mb, CEE_STLOC_S);
364                 mono_mb_emit_byte (mb, num);
365         } else {
366                 mono_mb_emit_byte (mb, CEE_PREFIX1);
367                 mono_mb_emit_byte (mb, CEE_STLOC);
368                 mono_mb_emit_i4 (mb, num);
369         }
370 }
371
372 void
373 mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value)
374 {
375         if (value >= -1 && value < 8) {
376                 mono_mb_emit_byte (mb, CEE_LDC_I4_0 + value);
377         } else if (value >= -128 && value <= 127) {
378                 mono_mb_emit_byte (mb, CEE_LDC_I4_S);
379                 mono_mb_emit_byte (mb, value);
380         } else {
381                 mono_mb_emit_byte (mb, CEE_LDC_I4);
382                 mono_mb_emit_i4 (mb, value);
383         }
384 }
385
386 void
387 mono_mb_emit_managed_call (MonoMethodBuilder *mb, MonoMethod *method, MonoMethodSignature *opt_sig)
388 {
389         if (!opt_sig)
390                 opt_sig = method->signature;
391         mono_mb_emit_byte (mb, CEE_PREFIX1);
392         mono_mb_emit_byte (mb, CEE_LDFTN);
393         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
394         mono_mb_emit_byte (mb, CEE_CALLI);
395         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, opt_sig));
396 }
397
398 void
399 mono_mb_emit_native_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, gpointer func)
400 {
401         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
402         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
403         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, func));
404         mono_mb_emit_byte (mb, CEE_CALLI);
405         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
406 }
407
408 void
409 mono_mb_emit_exception (MonoMethodBuilder *mb)
410 {
411         mono_mb_emit_byte (mb, CEE_LDNULL);
412         mono_mb_emit_byte (mb, CEE_THROW);
413         
414 }
415
416 void
417 mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint8 local, gint8 incr)
418 {
419         mono_mb_emit_ldloc (mb, local); 
420         mono_mb_emit_icon (mb, incr);
421         mono_mb_emit_byte (mb, CEE_ADD);
422         mono_mb_emit_stloc (mb, local); 
423 }
424
425 static void
426 emit_ptr_to_str_conv (MonoMethodBuilder *mb, MonoMarshalConv conv, int usize, int msize)
427 {
428         /* fixme: dont know what do do here - docs say 
429            this does not work for value types  */
430
431         g_warning ("not implemented");
432         g_assert_not_reached ();
433 }
434
435 static void
436 emit_str_to_ptr_conv (MonoMethodBuilder *mb, MonoMarshalConv conv, int usize, int msize)
437 {
438         switch (conv) {
439         case MONO_MARSHAL_CONV_BOOL_I4:
440                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
441                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
442                 mono_mb_emit_byte (mb, CEE_LDIND_U1);
443                 mono_mb_emit_byte (mb, CEE_STIND_I4);
444                 break;
445         case MONO_MARSHAL_CONV_STR_LPWSTR:
446         case MONO_MARSHAL_CONV_STR_LPSTR:
447         case MONO_MARSHAL_CONV_STR_LPTSTR:
448         case MONO_MARSHAL_CONV_STR_BSTR:
449         case MONO_MARSHAL_CONV_STR_ANSIBSTR:
450         case MONO_MARSHAL_CONV_STR_TBSTR:
451         case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
452         case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
453                 /* free space if ARG_2 == true */
454                 mono_mb_emit_byte (mb, CEE_LDARG_2);
455                 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
456                 mono_mb_emit_byte (mb, 4);
457                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
458                 mono_mb_emit_byte (mb, CEE_LDIND_I);
459                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
460                 mono_mb_emit_byte (mb, CEE_MONO_FREE);
461                 
462                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
463                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
464                 mono_mb_emit_byte (mb, CEE_LDIND_I);
465                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
466                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
467                 mono_mb_emit_byte (mb, conv);
468                 mono_mb_emit_byte (mb, CEE_STIND_I);
469                 break;
470         case MONO_MARSHAL_CONV_STR_BYVALSTR: 
471         case MONO_MARSHAL_CONV_STR_BYVALWSTR: {
472                 if (!usize)
473                         break;
474
475                 mono_mb_emit_byte (mb, CEE_LDLOC_1); /* dst */
476                 mono_mb_emit_byte (mb, CEE_LDLOC_0);    
477                 mono_mb_emit_byte (mb, CEE_LDIND_I); /* src String */
478                 mono_mb_emit_icon (mb, usize);
479                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
480                 mono_mb_emit_byte (mb, CEE_MONO_PROC3);
481                 mono_mb_emit_byte (mb, conv);
482                 break;
483         }
484         case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
485                 if (!usize) 
486                         break;
487
488                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
489                 mono_mb_emit_byte (mb, CEE_LDIND_I);            
490                 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
491                 mono_mb_emit_byte (mb, 15);
492
493                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
494                 mono_mb_emit_byte (mb, CEE_LDLOC_0);    
495                 mono_mb_emit_byte (mb, CEE_LDIND_I);    
496                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
497                 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
498                 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
499                 mono_mb_emit_byte (mb, CEE_ADD);
500                 mono_mb_emit_icon (mb, usize);
501                 mono_mb_emit_byte (mb, CEE_PREFIX1);
502                 mono_mb_emit_byte (mb, CEE_CPBLK);                      
503                 break;
504         }
505         case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
506         default:
507                 g_error ("marshalling conversion %d not implemented", conv);
508         }
509 }
510
511 static void
512 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
513 {
514         MonoMarshalType *info;
515         int i;
516
517         info = mono_marshal_load_type_info (klass);
518
519         for (i = 0; i < info->num_fields; i++) {
520                 MonoMarshalNative ntype;
521                 MonoMarshalConv conv;
522                 MonoType *ftype = info->fields [i].field->type;
523                 int msize = 0;
524                 int usize = 0;
525                 gboolean last_field = i < (info->num_fields -1) ? 0 : 1;
526
527                 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
528                         continue;
529
530                 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, klass->unicode, &conv);
531                         
532                 if (last_field) {
533                         msize = klass->instance_size - info->fields [i].field->offset;
534                         usize = info->native_size - info->fields [i].offset;
535                 } else {
536                         msize = klass->fields [i + 1].offset - info->fields [i].field->offset;
537                         usize = info->fields [i + 1].offset - info->fields [i].offset;
538                 }
539                 g_assert (msize > 0 && usize > 0);
540
541                 switch (conv) {
542                 case MONO_MARSHAL_CONV_NONE:
543
544                         if (ftype->byref || ftype->type == MONO_TYPE_I ||
545                             ftype->type == MONO_TYPE_U) {
546                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
547                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
548                                 mono_mb_emit_byte (mb, CEE_LDIND_I);
549                                 mono_mb_emit_byte (mb, CEE_STIND_I);
550                                 break;
551                         }
552
553                         switch (ftype->type) {
554                         case MONO_TYPE_I4:
555                         case MONO_TYPE_U4:
556                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
557                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
558                                 mono_mb_emit_byte (mb, CEE_LDIND_I4);
559                                 mono_mb_emit_byte (mb, CEE_STIND_I4);
560                                 break;
561                         case MONO_TYPE_I1:
562                         case MONO_TYPE_U1:
563                         case MONO_TYPE_BOOLEAN:
564                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
565                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
566                                 mono_mb_emit_byte (mb, CEE_LDIND_I1);
567                                 mono_mb_emit_byte (mb, CEE_STIND_I1);
568                                 break;
569                         case MONO_TYPE_I2:
570                         case MONO_TYPE_U2:
571                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
572                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
573                                 mono_mb_emit_byte (mb, CEE_LDIND_I2);
574                                 mono_mb_emit_byte (mb, CEE_STIND_I2);
575                                 break;
576                         case MONO_TYPE_I8:
577                         case MONO_TYPE_U8:
578                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
579                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
580                                 mono_mb_emit_byte (mb, CEE_LDIND_I8);
581                                 mono_mb_emit_byte (mb, CEE_STIND_I8);
582                                 break;
583                         case MONO_TYPE_R4:
584                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
585                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
586                                 mono_mb_emit_byte (mb, CEE_LDIND_R4);
587                                 mono_mb_emit_byte (mb, CEE_STIND_R4);
588                                 break;
589                         case MONO_TYPE_R8:
590                                 mono_mb_emit_byte (mb, CEE_LDLOC_1);
591                                 mono_mb_emit_byte (mb, CEE_LDLOC_0);
592                                 mono_mb_emit_byte (mb, CEE_LDIND_R8);
593                                 mono_mb_emit_byte (mb, CEE_STIND_R8);
594                                 break;
595                         case MONO_TYPE_VALUETYPE:
596                                 emit_struct_conv (mb, ftype->data.klass, to_object);
597                                 break;
598                         default:
599                                 g_error ("marshalling type %02x not implemented", ftype->type);
600                         }
601                         break;
602
603                 default:
604                         if (to_object) 
605                                 emit_ptr_to_str_conv (mb, conv, usize, msize);
606                         else
607                                 emit_str_to_ptr_conv (mb, conv, usize, msize);  
608                 }
609
610                 if (!last_field) {
611                         mono_mb_emit_add_to_local (mb, 0, msize);
612                         mono_mb_emit_add_to_local (mb, 1, usize);
613                 }               
614         }
615 }
616
617 static MonoAsyncResult *
618 mono_delegate_begin_invoke (MonoDelegate *delegate, gpointer *params)
619 {
620         MonoMethodMessage *msg;
621         MonoDelegate *async_callback;
622         MonoObject *state;
623         MonoMethod *im;
624         MonoClass *klass;
625         MonoMethod *method = NULL;
626         int i;
627
628         g_assert (delegate);
629
630         klass = delegate->object.vtable->klass;
631
632         method = mono_get_delegate_invoke (klass);
633         for (i = 0; i < klass->method.count; ++i) {
634                 if (klass->methods [i]->name[0] == 'B' && 
635                     !strcmp ("BeginInvoke", klass->methods [i]->name)) {
636                         method = klass->methods [i];
637                         break;
638                 }
639         }
640
641         g_assert (method != NULL);
642
643         im = mono_get_delegate_invoke (method->klass);
644         
645         msg = mono_method_call_message_new (method, params, im, &async_callback, &state);
646
647         return mono_thread_pool_add ((MonoObject *)delegate, msg, async_callback, state);
648 }
649
650 static int
651 mono_mb_emit_save_args (MonoMethodBuilder *mb, MonoMethodSignature *sig, gboolean save_this)
652 {
653         int i, params_var, tmp_var;
654
655         /* allocate local (pointer) *params[] */
656         params_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
657         /* allocate local (pointer) tmp */
658         tmp_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
659
660         /* alloate space on stack to store an array of pointers to the arguments */
661         mono_mb_emit_icon (mb, sizeof (gpointer) * (sig->param_count + 1));
662         mono_mb_emit_byte (mb, CEE_PREFIX1);
663         mono_mb_emit_byte (mb, CEE_LOCALLOC);
664         mono_mb_emit_stloc (mb, params_var);
665
666         /* tmp = params */
667         mono_mb_emit_ldloc (mb, params_var);
668         mono_mb_emit_stloc (mb, tmp_var);
669
670         if (save_this && sig->hasthis) {
671                 mono_mb_emit_ldloc (mb, tmp_var);
672                 mono_mb_emit_ldarg_addr (mb, 0);
673                 mono_mb_emit_byte (mb, CEE_STIND_I);
674                 /* tmp = tmp + sizeof (gpointer) */
675                 if (sig->param_count)
676                         mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
677
678         }
679
680         for (i = 0; i < sig->param_count; i++) {
681                 mono_mb_emit_ldloc (mb, tmp_var);
682                 mono_mb_emit_ldarg_addr (mb, i + sig->hasthis);
683                 mono_mb_emit_byte (mb, CEE_STIND_I);
684                 /* tmp = tmp + sizeof (gpointer) */
685                 if (i < (sig->param_count - 1))
686                         mono_mb_emit_add_to_local (mb, tmp_var, sizeof (gpointer));
687         }
688
689         return params_var;
690 }
691
692 MonoMethod *
693 mono_marshal_get_delegate_begin_invoke (MonoMethod *method)
694 {
695         MonoMethodSignature *sig;
696         static MonoMethodSignature *csig = NULL;
697         MonoMethodBuilder *mb;
698         MonoMethod *res;
699         GHashTable *cache;
700         int params_var;
701
702         g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
703                   !strcmp (method->name, "BeginInvoke"));
704
705         sig = method->signature;
706
707         cache = method->klass->image->delegate_begin_invoke_cache;
708         if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
709                 return res;
710
711         g_assert (sig->hasthis);
712
713         if (!csig) {
714                 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
715                 csig = g_malloc0 (sigsize);
716
717                 /* MonoAsyncResult * begin_invoke (MonoDelegate *delegate, gpointer params[]) */
718                 csig->param_count = 2;
719                 csig->ret = &mono_defaults.object_class->byval_arg;
720                 csig->params [0] = &mono_defaults.object_class->byval_arg;
721                 csig->params [1] = &mono_defaults.int_class->byval_arg;
722         }
723
724         mb = mono_mb_new (method->klass, method->name);
725         mb->method->wrapper_type = MONO_WRAPPER_DELEGATE_BEGIN_INVOKE;
726         mb->method->save_lmf = 1;
727
728         params_var = mono_mb_emit_save_args (mb, sig, FALSE);
729
730         mono_mb_emit_ldarg (mb, 0);
731         mono_mb_emit_ldloc (mb, params_var);
732         mono_mb_emit_native_call (mb, csig, mono_delegate_begin_invoke);
733         mono_mb_emit_byte (mb, CEE_RET);
734
735         res = mono_mb_create_method (mb, sig, 0);
736         mono_mb_free (mb);
737         g_hash_table_insert (cache, sig, res);
738         return res;
739 }
740
741 static MonoObject *
742 mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params)
743 {
744         MonoDomain *domain = mono_domain_get ();
745         MonoAsyncResult *ares;
746         MonoMethod *method = NULL;
747         MonoMethodSignature *sig;
748         MonoMethodMessage *msg;
749         MonoObject *res, *exc;
750         MonoArray *out_args;
751         MonoClass *klass;
752         int i;
753
754         g_assert (delegate);
755
756         if (!delegate->method_info || !delegate->method_info->method)
757                 g_assert_not_reached ();
758
759         klass = delegate->object.vtable->klass;
760
761         for (i = 0; i < klass->method.count; ++i) {
762                 if (klass->methods [i]->name[0] == 'E' && 
763                     !strcmp ("EndInvoke", klass->methods [i]->name)) {
764                         method = klass->methods [i];
765                         break;
766                 }
767         }
768
769         g_assert (method != NULL);
770
771         sig = method->signature;
772
773         msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
774
775         ares = mono_array_get (msg->args, gpointer, sig->param_count - 1);
776         g_assert (ares);
777
778         res = mono_thread_pool_finish (ares, &out_args, &exc);
779
780         if (exc) {
781                 char *strace = mono_string_to_utf8 (((MonoException*)exc)->stack_trace);
782                 char  *tmp;
783                 tmp = g_strdup_printf ("%s\nException Rethrown at:\n", strace);
784                 g_free (strace);        
785                 ((MonoException*)exc)->stack_trace = mono_string_new (domain, tmp);
786                 g_free (tmp);
787                 mono_raise_exception ((MonoException*)exc);
788         }
789
790         mono_method_return_message_restore (method, params, out_args);
791         return res;
792 }
793
794 static void
795 mono_mb_emit_restore_result (MonoMethodBuilder *mb, MonoType *return_type)
796 {
797         if (return_type->byref)
798                 return_type = &mono_defaults.int_class->byval_arg;
799         else if (return_type->type == MONO_TYPE_VALUETYPE && return_type->data.klass->enumtype)
800                 return_type = return_type->data.klass->enum_basetype;
801
802         switch (return_type->type) {
803         case MONO_TYPE_VOID:
804                 g_assert_not_reached ();
805                 break;
806         case MONO_TYPE_STRING:
807         case MONO_TYPE_CLASS: 
808         case MONO_TYPE_OBJECT: 
809         case MONO_TYPE_ARRAY: 
810         case MONO_TYPE_SZARRAY: 
811                 /* nothing to do */
812                 break;
813         case MONO_TYPE_U1:
814         case MONO_TYPE_BOOLEAN:
815                 mono_mb_emit_byte (mb, CEE_UNBOX);
816                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
817                 mono_mb_emit_byte (mb, CEE_LDIND_U1);
818                 break;
819         case MONO_TYPE_I1:
820                 mono_mb_emit_byte (mb, CEE_UNBOX);
821                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
822                 mono_mb_emit_byte (mb, CEE_LDIND_I1);
823                 break;
824         case MONO_TYPE_U2:
825         case MONO_TYPE_CHAR:
826                 mono_mb_emit_byte (mb, CEE_UNBOX);
827                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
828                 mono_mb_emit_byte (mb, CEE_LDIND_U2);
829                 break;
830         case MONO_TYPE_I2:
831                 mono_mb_emit_byte (mb, CEE_UNBOX);
832                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
833                 mono_mb_emit_byte (mb, CEE_LDIND_I2);
834                 break;
835 #if SIZEOF_VOID_P == 4
836         case MONO_TYPE_I:
837 #endif
838         case MONO_TYPE_I4:
839                 mono_mb_emit_byte (mb, CEE_UNBOX);
840                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
841                 mono_mb_emit_byte (mb, CEE_LDIND_I4);
842                 break;
843 #if SIZEOF_VOID_P == 4
844         case MONO_TYPE_U:
845 #endif
846         case MONO_TYPE_U4:
847                 mono_mb_emit_byte (mb, CEE_UNBOX);
848                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
849                 mono_mb_emit_byte (mb, CEE_LDIND_U4);
850                 break;
851         case MONO_TYPE_U8:
852         case MONO_TYPE_I8:
853                 mono_mb_emit_byte (mb, CEE_UNBOX);
854                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
855                 mono_mb_emit_byte (mb, CEE_LDIND_I8);
856                 break;
857         case MONO_TYPE_R4:
858                 mono_mb_emit_byte (mb, CEE_UNBOX);
859                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
860                 mono_mb_emit_byte (mb, CEE_LDIND_R4);
861                 break;
862         case MONO_TYPE_R8:
863                 mono_mb_emit_byte (mb, CEE_UNBOX);
864                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (return_type)));
865                 mono_mb_emit_byte (mb, CEE_LDIND_R8);
866                 break;
867         case MONO_TYPE_VALUETYPE: {
868                 int class;
869                 mono_mb_emit_byte (mb, CEE_UNBOX);
870                 class = mono_mb_add_data (mb, mono_class_from_mono_type (return_type));
871                 mono_mb_emit_i4 (mb, class);
872                 mono_mb_emit_byte (mb, CEE_LDOBJ);
873                 mono_mb_emit_i4 (mb, class);
874                 break;
875         }
876         default:
877                 g_warning ("type 0x%x not handled", return_type->type);
878                 g_assert_not_reached ();
879         }
880
881         mono_mb_emit_byte (mb, CEE_RET);
882 }
883
884 MonoMethod *
885 mono_marshal_get_delegate_end_invoke (MonoMethod *method)
886 {
887         MonoMethodSignature *sig;
888         static MonoMethodSignature *csig = NULL;
889         MonoMethodBuilder *mb;
890         MonoMethod *res;
891         GHashTable *cache;
892         int params_var;
893
894         g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
895                   !strcmp (method->name, "EndInvoke"));
896
897         sig = method->signature;
898
899         cache = method->klass->image->delegate_end_invoke_cache;
900         if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
901                 return res;
902
903         g_assert (sig->hasthis);
904
905         if (!csig) {
906                 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
907                 csig = g_malloc0 (sigsize);
908
909                 /* MonoObject *end_invoke (MonoDelegate *delegate, gpointer params[]) */
910                 csig->param_count = 2;
911                 csig->ret = &mono_defaults.object_class->byval_arg;
912                 csig->params [0] = &mono_defaults.object_class->byval_arg;
913                 csig->params [1] = &mono_defaults.int_class->byval_arg;
914         }
915
916         mb = mono_mb_new (method->klass, method->name);
917         mb->method->wrapper_type = MONO_WRAPPER_DELEGATE_END_INVOKE;
918         mb->method->save_lmf = 1;
919
920         params_var = mono_mb_emit_save_args (mb, sig, FALSE);
921
922         mono_mb_emit_ldarg (mb, 0);
923         mono_mb_emit_ldloc (mb, params_var);
924         mono_mb_emit_native_call (mb, csig, mono_delegate_end_invoke);
925
926         if (sig->ret->type == MONO_TYPE_VOID)
927                 mono_mb_emit_byte (mb, CEE_POP);
928         else
929                 mono_mb_emit_restore_result (mb, sig->ret);
930
931         res = mono_mb_create_method (mb, sig, 0);
932         mono_mb_free (mb);
933         g_hash_table_insert (cache, sig, res);
934         return res;
935 }
936
937 static MonoObject *
938 mono_remoting_wrapper (MonoMethod *method, gpointer *params)
939 {
940         MonoMethodMessage *msg;
941         MonoTransparentProxy *this;
942         MonoObject *res, *exc;
943         MonoArray *out_args;
944
945         this = *((MonoTransparentProxy **)params [0]);
946
947         g_assert (this);
948         g_assert (((MonoObject *)this)->vtable->klass == mono_defaults.transparent_proxy_class);
949         
950         /* skip the this pointer */
951         params++;
952
953         msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
954
955         res = mono_remoting_invoke ((MonoObject *)this->rp, msg, &exc, &out_args);
956
957         if (exc)
958                 mono_raise_exception ((MonoException *)exc);
959
960         mono_method_return_message_restore (method, params, out_args);
961
962         return res;
963
964
965 MonoMethod *
966 mono_marshal_get_remoting_invoke (MonoMethod *method)
967 {
968         MonoMethodSignature *sig;
969         static MonoMethodSignature *csig = NULL;
970         MonoMethodBuilder *mb;
971         MonoMethod *res;
972         GHashTable *cache;
973         int params_var;
974
975         g_assert (method);
976
977         if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE)
978                 return method;
979
980         sig = method->signature;
981
982         /* we cant remote methods without this pointer */
983         if (!sig->hasthis)
984                 return method;
985
986         cache = method->klass->image->remoting_invoke_cache;
987         if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
988                 return res;
989
990         if (!csig) {
991                 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
992                 csig = g_malloc0 (sigsize);
993
994                 /* MonoObject *remoting_wrapper (MonoMethod *method, gpointer params[]) */
995                 csig->param_count = 2;
996                 csig->ret = &mono_defaults.object_class->byval_arg;
997                 csig->params [0] = &mono_defaults.int_class->byval_arg;
998                 csig->params [1] = &mono_defaults.int_class->byval_arg;
999         }
1000
1001         mb = mono_mb_new (method->klass, method->name);
1002         mb->method->wrapper_type = MONO_WRAPPER_REMOTING_INVOKE;
1003
1004         params_var = mono_mb_emit_save_args (mb, sig, TRUE);
1005
1006         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1007         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1008         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
1009         mono_mb_emit_ldloc (mb, params_var);
1010         mono_mb_emit_native_call (mb, csig, mono_remoting_wrapper);
1011
1012         if (sig->ret->type == MONO_TYPE_VOID)
1013                 mono_mb_emit_byte (mb, CEE_POP);
1014         else
1015                 mono_mb_emit_restore_result (mb, sig->ret);
1016
1017         res = mono_mb_create_method (mb, sig, 0);
1018         mono_mb_free (mb);
1019         g_hash_table_insert (cache, method, res);
1020         return res;
1021 }
1022
1023 /*
1024  * the returned method invokes all methods in a multicast delegate 
1025  */
1026 MonoMethod *
1027 mono_marshal_get_delegate_invoke (MonoMethod *method)
1028 {
1029         MonoMethodSignature *sig, *static_sig;
1030         int i, sigsize;
1031         MonoMethodBuilder *mb;
1032         MonoMethod *res;
1033         GHashTable *cache;
1034         int pos [3];
1035
1036         g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
1037                   !strcmp (method->name, "Invoke"));
1038                 
1039         sig = method->signature;
1040
1041         cache = method->klass->image->delegate_invoke_cache;
1042         if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
1043                 return res;
1044
1045         sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1046         static_sig = g_memdup (sig, sigsize);
1047         static_sig->hasthis = 0;
1048
1049         mb = mono_mb_new (method->klass, method->name);
1050         mb->method->wrapper_type = MONO_WRAPPER_DELEGATE_INVOKE;
1051
1052         /* allocate local 0 (object) prev */
1053         mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1054         /* allocate local 1 (object) target */
1055         mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1056         /* allocate local 2 (pointer) mptr */
1057         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1058
1059         /* allocate local 3 to store the return value */
1060         if (sig->ret->type != MONO_TYPE_VOID)
1061                 mono_mb_add_local (mb, sig->ret);
1062
1063         g_assert (sig->hasthis);
1064
1065         /* prev = addr of delegate */
1066         mono_mb_emit_ldarg (mb, 0);
1067         mono_mb_emit_stloc (mb, 0);
1068
1069         /* loop */
1070         pos [0] = mb->pos;
1071         /* target = delegate->target */
1072         mono_mb_emit_ldloc (mb, 0);
1073         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1074         mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
1075         mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoDelegate, target));
1076         mono_mb_emit_byte (mb, CEE_ADD);
1077         mono_mb_emit_byte (mb, CEE_LDIND_I);
1078         mono_mb_emit_stloc (mb, 1);
1079
1080         /* mptr = delegate->method_ptr */
1081         mono_mb_emit_ldloc (mb, 0);
1082         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1083         mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
1084         mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
1085         mono_mb_emit_byte (mb, CEE_ADD);
1086         mono_mb_emit_byte (mb, CEE_LDIND_I);
1087         mono_mb_emit_stloc (mb, 2);
1088
1089         /* target == null ? */
1090         mono_mb_emit_ldloc (mb, 1);
1091         mono_mb_emit_byte (mb, CEE_BRTRUE); 
1092         pos [1] = mb->pos;
1093         mono_mb_emit_i4 (mb, 0);
1094
1095         /* emit static method call */
1096
1097         for (i = 0; i < sig->param_count; i++)
1098                 mono_mb_emit_ldarg (mb, i + 1);
1099
1100         mono_mb_emit_ldloc (mb, 2);
1101         mono_mb_emit_byte (mb, CEE_CALLI);
1102         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, static_sig));
1103
1104         if (sig->ret->type != MONO_TYPE_VOID)
1105                 mono_mb_emit_stloc (mb, 3);
1106
1107         mono_mb_emit_byte (mb, CEE_BR);
1108         pos [2] = mb->pos;
1109         mono_mb_emit_i4 (mb, 0);
1110    
1111         /* target != null, emit non static method call */
1112
1113         mono_mb_patch_addr (mb, pos [1], mb->pos - (pos [1] + 4));
1114         mono_mb_emit_ldloc (mb, 1);
1115
1116         for (i = 0; i < sig->param_count; i++)
1117                 mono_mb_emit_ldarg (mb, i + 1);
1118         
1119         mono_mb_emit_ldloc (mb, 2);
1120         mono_mb_emit_byte (mb, CEE_CALLI);
1121         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
1122
1123         if (sig->ret->type != MONO_TYPE_VOID)
1124                 mono_mb_emit_stloc (mb, 3);
1125
1126         mono_mb_patch_addr (mb, pos [2], mb->pos - (pos [2] + 4));
1127
1128         /* prev = delegate->prev */
1129         mono_mb_emit_ldloc (mb, 0);
1130         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1131         mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
1132         mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoMulticastDelegate, prev));
1133         mono_mb_emit_byte (mb, CEE_ADD);
1134         mono_mb_emit_byte (mb, CEE_LDIND_I);
1135         mono_mb_emit_stloc (mb, 0);
1136
1137         /* if prev != null goto loop */
1138         mono_mb_emit_ldloc (mb, 0);
1139         mono_mb_emit_byte (mb, CEE_BRTRUE);
1140         mono_mb_emit_i4 (mb, pos [0] - (mb->pos + 4));
1141
1142         if (sig->ret->type != MONO_TYPE_VOID)
1143                 mono_mb_emit_ldloc (mb, 3);
1144
1145         mono_mb_emit_byte (mb, CEE_RET);
1146
1147         res = mono_mb_create_method (mb, sig, 0);
1148         mono_mb_free (mb);
1149
1150         g_hash_table_insert (cache, sig, res);
1151
1152         return res;     
1153 }
1154
1155 /*
1156  * generates IL code for the runtime invoke function 
1157  * MonoObject *runtime_invoke (MonoObject *this, void **params, MonoObject **exc)
1158  *
1159  * we also catch exceptions if exc != null
1160  */
1161 MonoMethod *
1162 mono_marshal_get_runtime_invoke (MonoMethod *method)
1163 {
1164         MonoMethodSignature *sig, *csig;
1165         MonoExceptionClause *clause;
1166         MonoMethodHeader *header;
1167         MonoMethodBuilder *mb;
1168         MonoMethod *res;
1169         GHashTable *cache;
1170         static MonoString *string_dummy = NULL;
1171         int i, pos, sigsize;
1172
1173         g_assert (method);
1174
1175         cache = method->klass->image->runtime_invoke_cache;
1176         if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1177                 return res;
1178         
1179         /* to make it work with our special string constructors */
1180         if (!string_dummy)
1181                 string_dummy = mono_string_new_wrapper ("dummy");
1182
1183         sig = method->signature;
1184
1185         sigsize = sizeof (MonoMethodSignature) + 3 * sizeof (MonoType *);
1186         csig = g_malloc0 (sigsize);
1187
1188         csig->param_count = 3;
1189         csig->ret = &mono_defaults.object_class->byval_arg;
1190         csig->params [0] = &mono_defaults.object_class->byval_arg;
1191         csig->params [1] = &mono_defaults.int_class->byval_arg;
1192         csig->params [2] = &mono_defaults.int_class->byval_arg;
1193
1194         mb = mono_mb_new (method->klass, method->name);
1195         mb->method->wrapper_type = MONO_WRAPPER_RUNTIME_INVOKE;
1196
1197         /* allocate local 0 (object) tmp */
1198         mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1199         /* allocate local 1 (object) exc */
1200         mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
1201
1202         /* cond set *exc to null */
1203         mono_mb_emit_byte (mb, CEE_LDARG_2);
1204         mono_mb_emit_byte (mb, CEE_BRFALSE_S);
1205         mono_mb_emit_byte (mb, 3);      
1206         mono_mb_emit_byte (mb, CEE_LDARG_2);
1207         mono_mb_emit_byte (mb, CEE_LDNULL);
1208         mono_mb_emit_byte (mb, CEE_STIND_I);
1209
1210         if (sig->hasthis) {
1211                 if (method->string_ctor) {
1212                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1213                         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1214                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, string_dummy));
1215                 } else {
1216                         mono_mb_emit_ldarg (mb, 0);
1217                 }
1218         }
1219
1220         for (i = 0; i < sig->param_count; i++) {
1221                 MonoType *t = sig->params [i];
1222                 int type;
1223
1224                 mono_mb_emit_ldarg (mb, 1);
1225                 if (i) {
1226                         mono_mb_emit_icon (mb, sizeof (gpointer) * i);
1227                         mono_mb_emit_byte (mb, CEE_ADD);
1228                 }
1229                 mono_mb_emit_byte (mb, CEE_LDIND_I);
1230
1231                 if (t->byref)
1232                         continue;
1233
1234                 type = sig->params [i]->type;
1235 handle_enum:
1236                 switch (type) {
1237                 case MONO_TYPE_I1:
1238                         mono_mb_emit_byte (mb, CEE_LDIND_I1);
1239                         break;
1240                 case MONO_TYPE_BOOLEAN:
1241                 case MONO_TYPE_U1:
1242                         mono_mb_emit_byte (mb, CEE_LDIND_U1);
1243                         break;
1244                 case MONO_TYPE_I2:
1245                         mono_mb_emit_byte (mb, CEE_LDIND_I2);
1246                         break;
1247                 case MONO_TYPE_U2:
1248                 case MONO_TYPE_CHAR:
1249                         mono_mb_emit_byte (mb, CEE_LDIND_U2);
1250                         break;
1251 #if SIZEOF_VOID_P == 4
1252                 case MONO_TYPE_I:
1253 #endif
1254                 case MONO_TYPE_I4:
1255                         mono_mb_emit_byte (mb, CEE_LDIND_I4);
1256                         break;
1257 #if SIZEOF_VOID_P == 4
1258                 case MONO_TYPE_U:
1259 #endif
1260                 case MONO_TYPE_U4:
1261                         mono_mb_emit_byte (mb, CEE_LDIND_U4);
1262                         break;
1263                 case MONO_TYPE_R4:
1264                         mono_mb_emit_byte (mb, CEE_LDIND_R4);
1265                         break;
1266                 case MONO_TYPE_R8:
1267                         mono_mb_emit_byte (mb, CEE_LDIND_R8);
1268                         break;
1269 #if SIZEOF_VOID_P == 8
1270                 case MONO_TYPE_I:
1271                 case MONO_TYPE_U:
1272 #endif
1273                 case MONO_TYPE_I8:
1274                 case MONO_TYPE_U8:
1275                         mono_mb_emit_byte (mb, CEE_LDIND_I8);
1276                         break;
1277                 case MONO_TYPE_STRING:
1278                 case MONO_TYPE_CLASS:  
1279                 case MONO_TYPE_ARRAY:
1280                 case MONO_TYPE_PTR:
1281                 case MONO_TYPE_SZARRAY:
1282                 case MONO_TYPE_OBJECT:
1283                         /* do nothing */
1284                         break;
1285                 case MONO_TYPE_VALUETYPE:
1286                         if (t->data.klass->enumtype) {
1287                                 type = t->data.klass->enum_basetype->type;
1288                                 goto handle_enum;
1289                         }
1290                         g_assert_not_reached ();
1291                         break;
1292                 default:
1293                         g_assert_not_reached ();
1294                 }               
1295         }
1296
1297         if (method->string_ctor) {
1298                 MonoMethodSignature *strsig;
1299
1300                 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1301                 strsig = g_memdup (sig, sigsize);
1302                 strsig->ret = &mono_defaults.string_class->byval_arg;
1303
1304                 mono_mb_emit_managed_call (mb, method, strsig);         
1305         } else 
1306                 mono_mb_emit_managed_call (mb, method, NULL);
1307
1308         switch (sig->ret->type) {
1309         case MONO_TYPE_VOID:
1310                 if (!method->string_ctor)
1311                         mono_mb_emit_byte (mb, CEE_LDNULL);
1312                 break;
1313         case MONO_TYPE_I1:
1314         case MONO_TYPE_U1:
1315         case MONO_TYPE_I2:
1316         case MONO_TYPE_U2:
1317         case MONO_TYPE_I4:
1318         case MONO_TYPE_U4:
1319         case MONO_TYPE_I:
1320         case MONO_TYPE_U:
1321         case MONO_TYPE_R4:
1322         case MONO_TYPE_R8:
1323         case MONO_TYPE_I8:
1324         case MONO_TYPE_U8:
1325         case MONO_TYPE_VALUETYPE:
1326                 /* box value types */
1327                 mono_mb_emit_byte (mb, CEE_BOX);
1328                 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (sig->ret)));
1329                 break;
1330         case MONO_TYPE_STRING:
1331         case MONO_TYPE_CLASS:  
1332         case MONO_TYPE_ARRAY:
1333         case MONO_TYPE_SZARRAY:
1334         case MONO_TYPE_OBJECT:
1335                 /* nothing to do */
1336                 break;
1337         case MONO_TYPE_PTR:
1338         default:
1339                 g_assert_not_reached ();
1340         }
1341
1342         mono_mb_emit_stloc (mb, 0);
1343                 
1344         mono_mb_emit_byte (mb, CEE_LEAVE);
1345         pos = mb->pos;
1346         mono_mb_emit_i4 (mb, 0);
1347
1348         /* fixme: use a filter clause and only catch exceptions
1349          * when exc != null. With RETHROW we get wrong stack 
1350          * traces. */
1351         clause = g_new0 (MonoExceptionClause, 1);
1352         clause->flags = MONO_EXCEPTION_CLAUSE_NONE;
1353         clause->try_offset = 0;
1354         clause->try_len = mb->pos;
1355         clause->handler_offset = mb->pos;
1356
1357         /* handler code */
1358
1359         /* store exception */
1360         mono_mb_emit_stloc (mb, 1);
1361         
1362         mono_mb_emit_byte (mb, CEE_LDARG_2);
1363         mono_mb_emit_byte (mb, CEE_BRTRUE_S);
1364         mono_mb_emit_byte (mb, 2);
1365         mono_mb_emit_byte (mb, CEE_PREFIX1);
1366         mono_mb_emit_byte (mb, CEE_RETHROW);
1367         
1368         mono_mb_emit_byte (mb, CEE_LDARG_2);
1369         mono_mb_emit_ldloc (mb, 1);
1370         mono_mb_emit_byte (mb, CEE_STIND_I);
1371
1372         mono_mb_emit_byte (mb, CEE_LEAVE);
1373         mono_mb_emit_i4 (mb, 0);
1374
1375         clause->handler_len = mb->pos - clause->handler_offset;
1376
1377         /* return result */
1378         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1379         mono_mb_emit_ldloc (mb, 0);
1380         mono_mb_emit_byte (mb, CEE_RET);
1381         
1382         res = mono_mb_create_method (mb, csig, 0);
1383         mono_mb_free (mb);
1384
1385         header = ((MonoMethodNormal *)res)->header;
1386         header->num_clauses = 1;
1387         header->clauses = clause;
1388
1389         g_hash_table_insert (cache, method, res);
1390
1391         return res;     
1392 }
1393
1394 /*
1395  * generates IL code to call managed methods from unmanaged code 
1396  */
1397 MonoMethod *
1398 mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this)
1399 {
1400         MonoMethodSignature *sig, *csig;
1401         MonoMethodBuilder *mb;
1402         MonoMethod *res;
1403         GHashTable *cache;
1404         int i, sigsize;
1405
1406         g_assert (method != NULL);
1407
1408         cache = method->klass->image->managed_wrapper_cache;
1409         if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1410                 return res;
1411
1412         sig = method->signature;
1413
1414         mb = mono_mb_new (method->klass, method->name);
1415         mb->method->wrapper_type = MONO_WRAPPER_NATIVE_TO_MANAGED;
1416
1417         /* we copy the signature, so that we can modify it */
1418         sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1419         csig = g_memdup (sig, sigsize);
1420         csig->hasthis = 0;
1421
1422         /* fixme: howto handle this ? */
1423         if (sig->hasthis) {
1424
1425                 if (this) {
1426                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1427                         mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1428                         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, this));
1429
1430
1431                 } else {
1432                         /* fixme: */
1433                         g_assert_not_reached ();
1434                 }
1435         } 
1436
1437         for (i = 0; i < sig->param_count; i++) {
1438                 MonoType *t = sig->params [i];
1439                 
1440                 switch (t->type) {
1441                 case MONO_TYPE_I1:
1442                 case MONO_TYPE_U1:
1443                 case MONO_TYPE_I2:
1444                 case MONO_TYPE_U2:
1445                 case MONO_TYPE_I4:
1446                 case MONO_TYPE_U4:
1447                 case MONO_TYPE_I:
1448                 case MONO_TYPE_U:
1449                 case MONO_TYPE_PTR:
1450                 case MONO_TYPE_R4:
1451                 case MONO_TYPE_R8:
1452                 case MONO_TYPE_I8:
1453                 case MONO_TYPE_U8:
1454                         mono_mb_emit_ldarg (mb, i);
1455                         break;
1456                 case MONO_TYPE_STRING:
1457                         csig->params [i] = &mono_defaults.int_class->byval_arg;
1458                         mono_mb_emit_ldarg (mb, i);
1459                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1460                         mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1461                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
1462                         break;  
1463                 case MONO_TYPE_CLASS:  
1464                 case MONO_TYPE_ARRAY:
1465                 case MONO_TYPE_SZARRAY:
1466                 case MONO_TYPE_OBJECT:
1467                         /* fixme: conversions ? */
1468                         mono_mb_emit_ldarg (mb, i);
1469                         break;
1470                 default:
1471                         g_warning ("type 0x%02x unknown", t->type);     
1472                         g_assert_not_reached ();
1473                 }
1474         }
1475
1476         mono_mb_emit_managed_call (mb, method, NULL);
1477         
1478         /* fixme: add return type conversions */
1479
1480         mono_mb_emit_byte (mb, CEE_RET);
1481
1482         res = mono_mb_create_method (mb, csig, 0);
1483         mono_mb_free (mb);
1484
1485         g_hash_table_insert (cache, method, res);
1486
1487         return res;
1488 }
1489
1490 /*
1491  * generates IL code for the pinvoke wrapper (the generated method
1492  * call the unamnage code in method->addr)
1493  */
1494 MonoMethod *
1495 mono_marshal_get_native_wrapper (MonoMethod *method)
1496 {
1497         MonoMethodSignature *sig, *csig;
1498         MonoMethodBuilder *mb;
1499         MonoMethod *res;
1500         GHashTable *cache;
1501         MonoClass *klass;
1502         gboolean pinvoke = FALSE;
1503         int i, argnum, *tmp_locals;
1504         int type, sigsize;
1505
1506         g_assert (method != NULL);
1507
1508         cache = method->klass->image->native_wrapper_cache;
1509         if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1510                 return res;
1511
1512         sig = method->signature;
1513
1514         if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
1515             (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
1516                 pinvoke = TRUE;
1517
1518         mb = mono_mb_new (method->klass, method->name);
1519         mb->method->wrapper_type = MONO_WRAPPER_MANAGED_TO_NATIVE;
1520
1521         mb->method->save_lmf = 1;
1522
1523         if (pinvoke && !method->addr)
1524                 mono_lookup_pinvoke_call (method);
1525
1526         if (!method->addr) {
1527                 mono_mb_emit_exception (mb);
1528                 res = mono_mb_create_method (mb, sig, 0);
1529                 mono_mb_free (mb);
1530                 g_hash_table_insert (cache, method, res);
1531                 return res;
1532         }
1533
1534         /* we copy the signature, so that we can modify it */
1535         sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1536         csig = g_memdup (sig, sigsize);
1537
1538         if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
1539
1540                 if (method->string_ctor)
1541                         csig->ret = &mono_defaults.string_class->byval_arg;
1542
1543                 if (sig->hasthis)
1544                         mono_mb_emit_byte (mb, CEE_LDARG_0);
1545
1546                 for (i = 0; i < sig->param_count; i++)
1547                         mono_mb_emit_ldarg (mb, i + sig->hasthis);
1548
1549                 g_assert (method->addr);
1550                 mono_mb_emit_native_call (mb, csig, method->addr);
1551
1552                 mono_mb_emit_byte (mb, CEE_RET);
1553
1554                 res = mono_mb_create_method (mb, csig, 0);
1555                 mono_mb_free (mb);
1556                 g_hash_table_insert (cache, method, res);
1557                 return res;
1558         }
1559
1560         g_assert (pinvoke);
1561
1562         /* we allocate local for use with emit_struct_conv() */
1563         /* allocate local 0 (pointer) src_ptr */
1564         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1565         /* allocate local 1 (pointer) dst_ptr */
1566         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1567         /* allocate local 2 (pointer) as tmp/scratch storage */
1568         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1569
1570         if (sig->ret->type != MONO_TYPE_VOID) {
1571                 /* allocate local 3 to store the return value */
1572                 mono_mb_add_local (mb, sig->ret);
1573         }
1574
1575         /* we first do all conversions */
1576         tmp_locals = alloca (sizeof (int) * sig->param_count);
1577         for (i = 0; i < sig->param_count; i ++) {
1578                 MonoType *t = sig->params [i];
1579
1580                 argnum = i + sig->hasthis;
1581
1582                 /* allocate one tmp/scratch storage for each parameter */
1583                 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1584
1585                 switch (t->type) {
1586                 case MONO_TYPE_VALUETYPE:
1587                         klass = sig->params [i]->data.klass;
1588                         if (klass->enumtype)
1589                                 break;
1590                         
1591                         /* store the address of the source into local variable 0 */
1592                         mono_mb_emit_byte (mb, CEE_LDARGA);
1593                         mono_mb_emit_i2 (mb, argnum);
1594                         mono_mb_emit_byte (mb, CEE_STLOC_0);
1595                         
1596                         /* allocate space for the native struct and
1597                          * store the address into local variable 1 (dest) */
1598                         mono_mb_emit_icon (mb, mono_class_native_size (klass));
1599                         mono_mb_emit_byte (mb, CEE_LOCALLOC);
1600                         mono_mb_emit_stloc (mb, tmp_locals [i]);
1601                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
1602                         mono_mb_emit_byte (mb, CEE_STLOC_1);
1603
1604                         /* emit valuetype convnversion code code */
1605                         emit_struct_conv (mb, sig->params [i]->data.klass, FALSE);
1606
1607                         break;
1608                 case MONO_TYPE_STRING:
1609                         /* fixme: load the address instead */
1610                         mono_mb_emit_ldarg (mb, argnum);
1611                         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1612                         mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1613                         mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
1614                         mono_mb_emit_stloc (mb, tmp_locals [i]);
1615                         break;
1616                 case MONO_TYPE_CLASS:
1617                 case MONO_TYPE_OBJECT:
1618                         if (t->data.klass->delegate) {
1619                                 mono_mb_emit_ldarg (mb, argnum);
1620                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1621                                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1622                                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_DEL_FTN);
1623                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
1624                         } else {
1625                                 mono_mb_emit_ldarg (mb, argnum);
1626                                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1627                                 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
1628                                 /* fixme: convert to what ? */
1629                                 mono_mb_emit_stloc (mb, tmp_locals [i]);
1630                         }
1631                         break;
1632                 }
1633         }
1634
1635         /* push all arguments */
1636
1637         if (sig->hasthis)
1638                 mono_mb_emit_byte (mb, CEE_LDARG_0);
1639
1640         for (i = 0; i < sig->param_count; i++) {
1641                 MonoType *t = sig->params [i];
1642                 
1643                 argnum = i + sig->hasthis;
1644
1645                 if (t->byref) {
1646                         mono_mb_emit_ldarg (mb, argnum);
1647                         continue;
1648                 }
1649
1650                 switch (t->type) {
1651                 case MONO_TYPE_BOOLEAN:
1652                         mono_mb_emit_ldarg (mb, argnum);
1653                         break;
1654                 case MONO_TYPE_I1:
1655                 case MONO_TYPE_U1:
1656                 case MONO_TYPE_I2:
1657                 case MONO_TYPE_U2:
1658                 case MONO_TYPE_I4:
1659                 case MONO_TYPE_U4:
1660                 case MONO_TYPE_I:
1661                 case MONO_TYPE_U:
1662                 case MONO_TYPE_PTR:
1663                 case MONO_TYPE_R4:
1664                 case MONO_TYPE_R8:
1665                 case MONO_TYPE_I8:
1666                 case MONO_TYPE_U8:
1667                         mono_mb_emit_ldarg (mb, argnum);
1668                         break;
1669                 case MONO_TYPE_VALUETYPE:
1670                         klass = sig->params [i]->data.klass;
1671                         if (klass->enumtype) {
1672                                 mono_mb_emit_ldarg (mb, argnum);
1673                                 break;
1674                         }                       
1675                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
1676                         //mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1677                         //mono_mb_emit_byte (mb, CEE_MONO_LDOBJ);
1678                         //mono_mb_emit_i4 (mb, mono_klass_native_size (klass));
1679
1680                         break;
1681                 case MONO_TYPE_STRING:
1682                         /* fixme: load the address instead */
1683                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
1684                         break;
1685                 case MONO_TYPE_CLASS:
1686                 case MONO_TYPE_OBJECT:
1687                         mono_mb_emit_ldloc (mb, tmp_locals [i]);
1688                         break;
1689                 case MONO_TYPE_CHAR:
1690                 case MONO_TYPE_ARRAY:
1691                 case MONO_TYPE_SZARRAY:
1692                 case MONO_TYPE_TYPEDBYREF:
1693                 case MONO_TYPE_FNPTR:
1694                 default:
1695                         g_warning ("type 0x%02x unknown", t->type);     
1696                         g_assert_not_reached ();
1697                 }
1698         }                       
1699
1700         /* call the native method */
1701         mono_mb_emit_native_call (mb, csig, method->addr);
1702
1703         type = sig->ret->type;
1704 handle_enum:
1705         switch (type) {
1706         case MONO_TYPE_VOID:
1707         case MONO_TYPE_I1:
1708         case MONO_TYPE_U1:
1709         case MONO_TYPE_I2:
1710         case MONO_TYPE_U2:
1711         case MONO_TYPE_I4:
1712         case MONO_TYPE_U4:
1713         case MONO_TYPE_I:
1714         case MONO_TYPE_U:
1715         case MONO_TYPE_PTR:
1716         case MONO_TYPE_R4:
1717         case MONO_TYPE_R8:
1718         case MONO_TYPE_I8:
1719         case MONO_TYPE_U8:
1720                 /* no conversions necessary */
1721                 break;
1722         case MONO_TYPE_BOOLEAN:
1723                 /* maybe we need to make sure that it fits within 8 bits */
1724                 break;
1725         case MONO_TYPE_VALUETYPE:
1726                 if (sig->ret->data.klass->enumtype) {
1727                         type = sig->ret->data.klass->enum_basetype->type;
1728                         goto handle_enum;
1729                 } else {
1730                         g_warning ("generic valutype %s not handled", sig->ret->data.klass->name);
1731                         g_assert_not_reached ();
1732                 }
1733                 break;
1734         case MONO_TYPE_STRING:
1735                 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1736                 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1737                 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
1738                 break;
1739         case MONO_TYPE_ARRAY:
1740         case MONO_TYPE_SZARRAY:
1741         case MONO_TYPE_CLASS:
1742         case MONO_TYPE_OBJECT:
1743                 /* fixme: we need conversions here */
1744                 break;
1745         case MONO_TYPE_CHAR:
1746         case MONO_TYPE_TYPEDBYREF:
1747         case MONO_TYPE_FNPTR:
1748         default:
1749                 g_warning ("return type 0x%02x unknown", sig->ret->type);       
1750                 g_assert_not_reached ();
1751         }
1752
1753         mono_mb_emit_byte (mb, CEE_RET);
1754
1755         res = mono_mb_create_method (mb, sig, 0);
1756         mono_mb_free (mb);
1757
1758         g_hash_table_insert (cache, method, res);
1759
1760         return res;
1761 }
1762
1763 /*
1764  * generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld)
1765  */
1766 MonoMethod *
1767 mono_marshal_get_struct_to_ptr (MonoClass *klass)
1768 {
1769         MonoMethodBuilder *mb;
1770         static MonoMethod *stoptr = NULL;
1771         MonoMethod *res;
1772
1773         g_assert (klass != NULL);
1774
1775         if (klass->str_to_ptr)
1776                 return klass->str_to_ptr;
1777
1778         if (!stoptr) 
1779                 stoptr = mono_find_method_by_name (mono_defaults.marshal_class, "StructureToPtr", 3);
1780         g_assert (stoptr);
1781
1782         mb = mono_mb_new (stoptr->klass, stoptr->name);
1783
1784         /* allocate local 0 (pointer) src_ptr */
1785         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1786         /* allocate local 1 (pointer) dst_ptr */
1787         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1788         /* allocate local 2 (pointer) as tmp/scratch storage */
1789         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1790
1791         /* initialize src_ptr to point to the start of object data */
1792         mono_mb_emit_byte (mb, CEE_LDARG_0);
1793         mono_mb_emit_icon (mb, sizeof (MonoObject));
1794         mono_mb_emit_byte (mb, CEE_ADD);
1795         mono_mb_emit_byte (mb, CEE_STLOC_0);
1796
1797         /* initialize dst_ptr */
1798         mono_mb_emit_byte (mb, CEE_LDARG_1);
1799         mono_mb_emit_byte (mb, CEE_STLOC_1);
1800
1801         emit_struct_conv (mb, klass, FALSE);
1802
1803         mono_mb_emit_byte (mb, CEE_RET);
1804
1805         res = mono_mb_create_method (mb, stoptr->signature, 0);
1806         mono_mb_free (mb);
1807
1808         klass->str_to_ptr = res;
1809         return res;
1810 }
1811
1812 /*
1813  * generates IL code for PtrToStructure (IntPtr src, object structure)
1814  */
1815 MonoMethod *
1816 mono_marshal_get_ptr_to_struct (MonoClass *klass)
1817 {
1818         MonoMethodBuilder *mb;
1819         static MonoMethod *ptostr = NULL;
1820         MonoMethod *res;
1821
1822         g_assert (klass != NULL);
1823
1824         if (klass->ptr_to_str)
1825                 return klass->ptr_to_str;
1826
1827         if (!ptostr) 
1828                 ptostr = mono_find_method_by_name (mono_defaults.marshal_class, "PtrToStructure", 2);
1829         g_assert (ptostr);
1830
1831         mb = mono_mb_new (ptostr->klass, ptostr->name);
1832
1833         /* allocate local 0 (pointer) src_ptr */
1834         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1835         /* allocate local 1 (pointer) dst_ptr */
1836         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1837         /* allocate local 2 (pointer) as tmp/scratch storage */
1838         mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1839
1840         /* initialize src_ptr to point to the start of object data */
1841         mono_mb_emit_byte (mb, CEE_LDARG_0);
1842         mono_mb_emit_byte (mb, CEE_STLOC_0);
1843
1844         /* initialize dst_ptr */
1845         mono_mb_emit_byte (mb, CEE_LDARG_1);
1846         mono_mb_emit_icon (mb, sizeof (MonoObject));
1847         mono_mb_emit_byte (mb, CEE_ADD);
1848         mono_mb_emit_byte (mb, CEE_STLOC_1);
1849
1850         emit_struct_conv (mb, klass, TRUE);
1851
1852         mono_mb_emit_byte (mb, CEE_RET);
1853
1854         res = mono_mb_create_method (mb, ptostr->signature, 0);
1855         mono_mb_free (mb);
1856
1857         klass->ptr_to_str = res;
1858         return res;
1859 }
1860
1861 /* FIXME: on win32 we should probably use GlobalAlloc(). */
1862 void*
1863 mono_marshal_alloc (gpointer size) {
1864         return g_try_malloc ((gulong)size);
1865 }
1866
1867 void
1868 mono_marshal_free (gpointer ptr) {
1869         g_free (ptr);
1870 }
1871
1872 void*
1873 mono_marshal_realloc (gpointer ptr, gpointer size) {
1874         return g_try_realloc (ptr, (gulong)size);
1875 }
1876
1877 void*
1878 mono_marshal_string_array (MonoArray *array)
1879 {
1880         char **result;
1881         int i, len;
1882
1883         if (!array)
1884                 return NULL;
1885
1886         len = mono_array_length (array);
1887
1888         result = g_malloc (sizeof (char*) * len);
1889         for (i = 0; i < len; ++i) {
1890                 MonoString *s = (MonoString*)mono_array_get (array, gpointer, i);
1891                 result [i] = s ? mono_string_to_utf8 (s): NULL;
1892         }
1893         return result;
1894 }
1895
1896 void
1897 ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArray *src, gint32 start_index,
1898                                                                     gpointer dest, gint32 length)
1899 {
1900         int element_size;
1901         void *source_addr;
1902
1903         MONO_CHECK_ARG_NULL (src);
1904         MONO_CHECK_ARG_NULL (dest);
1905
1906         g_assert (src->obj.vtable->klass->rank == 1);
1907         g_assert (start_index >= 0 && start_index < mono_array_length (src));
1908         g_assert (start_index + length <= mono_array_length (src));
1909
1910         element_size = mono_array_element_size (src->obj.vtable->klass);
1911           
1912         source_addr = mono_array_addr_with_size (src, element_size, start_index);
1913
1914         memcpy (dest, source_addr, length * element_size);
1915 }
1916
1917 void
1918 ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer src, gint32 start_index,
1919                                                                       MonoArray *dest, gint32 length)
1920 {
1921         int element_size;
1922         void *dest_addr;
1923
1924         MONO_CHECK_ARG_NULL (src);
1925         MONO_CHECK_ARG_NULL (dest);
1926
1927         g_assert (dest->obj.vtable->klass->rank == 1);
1928         g_assert (start_index >= 0 && start_index < mono_array_length (dest));
1929         g_assert (start_index + length <= mono_array_length (dest));
1930
1931         element_size = mono_array_element_size (dest->obj.vtable->klass);
1932           
1933         dest_addr = mono_array_addr_with_size (dest, element_size, start_index);
1934
1935         memcpy (dest_addr, src, length * element_size);
1936 }
1937
1938 gpointer
1939 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr, gint32 offset)
1940 {
1941         char *p = ptr;
1942         return *(gpointer*)(p + offset);
1943 }
1944
1945 unsigned char
1946 ves_icall_System_Runtime_InteropServices_Marshal_ReadByte (gpointer ptr, gint32 offset)
1947 {
1948         char *p = ptr;
1949         return *(unsigned char*)(p + offset);
1950 }
1951
1952 gint16
1953 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt16 (gpointer ptr, gint32 offset)
1954 {
1955         char *p = ptr;
1956         return *(gint16*)(p + offset);
1957 }
1958
1959 gint32
1960 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt32 (gpointer ptr, gint32 offset)
1961 {
1962         char *p = ptr;
1963         return *(gint32*)(p + offset);
1964 }
1965
1966 gint64
1967 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt64 (gpointer ptr, gint32 offset)
1968 {
1969         char *p = ptr;
1970         return *(gint64*)(p + offset);
1971 }
1972
1973 void
1974 ves_icall_System_Runtime_InteropServices_Marshal_WriteByte (gpointer ptr, gint32 offset, unsigned char val)
1975 {
1976         char *p = ptr;
1977         *(unsigned char*)(p + offset) = val;
1978 }
1979
1980 void
1981 ves_icall_System_Runtime_InteropServices_Marshal_WriteIntPtr (gpointer ptr, gint32 offset, gpointer val)
1982 {
1983         char *p = ptr;
1984         *(gpointer*)(p + offset) = val;
1985 }
1986
1987 void
1988 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt16 (gpointer ptr, gint32 offset, gint16 val)
1989 {
1990         char *p = ptr;
1991         *(gint16*)(p + offset) = val;
1992 }
1993
1994 void
1995 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt32 (gpointer ptr, gint32 offset, gint32 val)
1996 {
1997         char *p = ptr;
1998         *(gint32*)(p + offset) = val;
1999 }
2000
2001 void
2002 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt64 (gpointer ptr, gint32 offset, gint64 val)
2003 {
2004         char *p = ptr;
2005         *(gint64*)(p + offset) = val;
2006 }
2007
2008 MonoString*
2009 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAuto (gpointer ptr)
2010 {
2011         MonoDomain *domain = mono_domain_get (); 
2012
2013         return mono_string_new (domain, (char *)ptr);
2014 }
2015
2016 guint32 
2017 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
2018 {
2019         return (GetLastError ());
2020 }
2021
2022 guint32 
2023 ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype)
2024 {
2025         MonoClass *klass;
2026
2027         MONO_CHECK_ARG_NULL (rtype);
2028
2029         klass = mono_class_from_mono_type (rtype->type);
2030
2031         return mono_class_native_size (klass);
2032 }
2033
2034 void
2035 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old)
2036 {
2037         MonoMethod *method;
2038         gpointer pa [3];
2039
2040         MONO_CHECK_ARG_NULL (obj);
2041         MONO_CHECK_ARG_NULL (dst);
2042
2043         method = mono_marshal_get_struct_to_ptr (obj->vtable->klass);
2044
2045         pa [0] = obj;
2046         pa [1] = &dst;
2047         pa [2] = &delete_old;
2048
2049         mono_runtime_invoke (method, NULL, pa, NULL);
2050 }
2051
2052 void
2053 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, MonoObject *dst)
2054 {
2055         MonoMethod *method;
2056         gpointer pa [2];
2057
2058         MONO_CHECK_ARG_NULL (src);
2059         MONO_CHECK_ARG_NULL (dst);
2060
2061         method = mono_marshal_get_ptr_to_struct (dst->vtable->klass);
2062
2063         pa [0] = &src;
2064         pa [1] = dst;
2065
2066         mono_runtime_invoke (method, NULL, pa, NULL);
2067 }